Mention input

A textarea with @people and #channel mentions that act as single tokens, with suggestions at the caret.

inputsnew
Preview
Mention input preview

When to use

  • Comment and reply boxes where people are tagged with @ and should be notified by id.
  • Chat or task composers that link #channels or projects inline.
  • Any text field whose stored value needs structured references alongside the plain text.

When not to use

  • Use textarea for plain notes with no references.
  • Use tag-input when the tokens are a separate list rather than part of a sentence.
  • Use rich-text-editor when the text also needs headings, lists, or links.

shadcn CLI

Also installs (1)

  • manicat-foundation
Manual install(+)
registry.jsonjson
{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "mention-input",
  "type": "registry:ui",
  "title": "Mention input",
  "description": "A textarea with @people and #channel mentions that act as single tokens, with suggestions at the caret.",
  "categories": [
    "inputs"
  ],
  "dependencies": [
    "lucide-react",
    "motion"
  ],
  "registryDependencies": [
    "https://manicat.viraza.net/r/manicat-foundation.json"
  ],
  "files": [
    {
      "path": "registry/components/mention-input/mention-input.tsx",
      "type": "registry:component",
      "target": "@components/manicat/mention-input/mention-input.tsx"
    },
    {
      "path": "registry/components/mention-input/mention-input.module.css",
      "type": "registry:component",
      "target": "@components/manicat/mention-input/mention-input.module.css"
    }
  ],
  "docs": "Docs and live preview: https://uiarc.dev/components/mention-input",
  "meta": {
    "tier": "free",
    "kind": "component",
    "docs": "https://manicat.viraza.net/components/mention-input",
    "markdown": "https://uiarc.dev/components/mention-input/markdown",
    "tags": [
      "inputs",
      "new"
    ]
  }
}

Usage

Install the component, then copy this into your app. Change the content and the props to fit your screen.

example.tsxtsx
"use client";

import { MentionInput } from "@/components/manicat/mention-input/mention-input";

export function MentionInputExample() {
  return (
    <MentionInput
      aria-label="Note"
      placeholder="Write a note, @ to mention someone"
      people={[{ id: "ada", name: "Ada Lovelace", role: "Engineering" }]}
      channels={[{ id: "general", name: "general", members: 12 }]}
    />
  );
}

Examples

Real screens rather than isolated props. Switch to Code to copy a whole example into your project.

Team note Mention people with @ and channels with # while writing a note.

Team note Mention people with @ and channels with # while writing a note. preview

Keyboard interactions

KeysAction
@ / #Opens people or channel suggestions after a space, line start, or opening bracket or quote.
Arrow Down / Arrow UpMoves through suggestions, wrapping at the ends.
Enter / TabTurns the highlighted suggestion into a mention.
EscapeDismisses suggestions for the current trigger without leaving the field.
Backspace / DeleteNext to a mention, one press removes the whole token.
Arrow Left / Arrow RightSteps over a mention as one unit.
Enter / Shift+EnterWith submitOnEnter, Enter submits and Shift+Enter adds a line.

Accessibility

  • The textarea is a combobox with aria-autocomplete="list", aria-expanded, aria-controls, and aria-activedescendant pointing at the highlighted option.
  • Suggestions are a listbox labelled People or Channels, with options marked aria-selected.
  • A polite live region announces the result count, such as 3 people or No matches.
  • Mention tints come from an aria-hidden mirror behind a transparent textarea, so assistive tech reads the plain text.
  • Choosing a suggestion types through execCommand insertText, so native undo keeps working.

Motion

  • The field height springs to its content between minRows and maxRows.
  • Suggestions pop in from the caret with a small scale and a snappy spring; the highlight glides between rows and the panel height springs as results change.
  • Reduced motion jumps the height and highlight and fades the panel without scale or offset.

Responsive behavior

  • Fills its container width. The suggestion panel is 272px wide, capped to the field width, and clamped so it never runs past the right edge.
  • With placement auto the panel flips above the caret near the bottom of the viewport, which suits composers pinned to the bottom of a mobile screen.
  • Options use pointer events and click, so touch taps choose a suggestion without a hover state.

Performance

  • Each edit rebuilds a mirror of the text to draw token tints and reconciles mention offsets with a prefix and suffix diff; fine for messages, not for pages of text.
  • Two ResizeObservers drive the field and panel height springs; ranking runs over the full people and channels arrays each keystroke, so pass a pre-filtered list past a few thousand entries.

Notes for AI

  • Choose it for comment boxes, message composers, and task descriptions that tag people or channels. Use textarea for plain multi-line text and tag-input for a list of chips outside the text.
  • Store serializeMentions(value) or the mentions array, not only value.text, so renamed people still resolve by id.
  • Filter people on the server by passing a fresh people array per keystroke; ranking is prefix, then word start, then substring, then role or description.
  • Hook a toolbar @ button to ref.openSuggestions("person").