Xzero UI
Pro library

Mention input

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

$ pnpm dlx shadcn@4.23.0 add @xzero-ui/mention-input
Live · keyboard ready

When to use

When not to use

Installation

Register both Xzero UI namespaces in your project's components.json:

{
  "registries": {
    "@xzero-ui": "https://mcp.xzero.co.uk/r/{name}.json",
    "@xzero-ui-pro": "https://mcp.xzero.co.uk/r/pro/{name}.json"
  }
}
npx shadcn@4.23.0 add @xzero-ui/mention-input

Install xzero-foundation once, and import @/components/xzero/foundation.css in your app root. No Xzero token is used by this snapshot. For sample portraits, photos, fonts, or logos, download https://mcp.xzero.co.uk/install-assets.mjs and run node xzero-install-assets.mjs <receiving-project>.

Usage

import { useState } from "react";
import { MentionInput, serializeMentions, type MentionValue } from "@/components/xzero/mention-input/mention-input";

const people = [
  { id: "u1", name: "Maya Chen", role: "Design lead" },
  { id: "u2", name: "Theo Park", role: "Engineer" },
];
const channels = [{ id: "c1", name: "launch", description: "Release planning", members: 14 }];

export function CommentBox({ onPost }: { onPost: (body: string) => void }) {
  const [value, setValue] = useState<MentionValue>({ text: "", mentions: [] });
  return (
    <MentionInput
      aria-label="Comment"
      placeholder="Write a comment, @ to mention"
      people={people}
      channels={channels}
      value={value}
      onChange={setValue}
      submitOnEnter
      onSubmit={next => {
        onPost(serializeMentions(next));
        setValue({ text: "", mentions: [] });
      }}
    />
  );
}

API reference

MentionInput

An autosizing textarea with @ people and # channel mentions. Mentions are atomic tokens, and the value carries plain text plus a structured mentions array with offsets.

PropTypeDefaultDescription
valueMentionValue–Controlled value: { text, mentions }. Each mention has kind, id, label, start, and end offsets into text.
defaultValueMentionValue–Initial value when uncontrolled. Defaults to empty text and no mentions.
onChange(value: MentionValue) => void–Called on every edit with the new text and the mentions moved or dropped to match it.
peopleMentionPerson[]–People offered after @. Each has id, name, and optional role and avatar. Leave it out to turn person mentions off.
channelsMentionChannel[]–Channels offered after #. Each has id, name, and optional description and members count. Leave it out to turn channel mentions off.
onMentionAdd(mention: Mention) => void–Called when a suggestion is chosen and becomes a mention.
onSubmit(value: MentionValue) => void–Called on Enter when submitOnEnter is set and the text is not blank.
submitOnEnterbooleanfalseEnter submits and Shift+Enter adds a line. Enter during IME composition never submits.
placeholderstring–Placeholder text for the empty field.
minRowsnumber1Starting height in rows.
maxRowsnumber8The field grows to this many rows, then scrolls.
placement"auto" | "top" | "bottom""auto"Where suggestions open. auto flips above the caret when there is less than 300px below it and more room above.
maxSuggestionsnumber6Most suggestions shown at once, best matches first.
disabledboolean–Disables the textarea and dims the field.
namestring–Forwarded to the textarea. The form value is the plain text; use serializeMentions to keep ids.
idstring–Forwarded to the textarea, for an external label.
aria-labelstring–Accessible name when there is no visible label.
aria-describedbystring–Id of help or error text for the textarea.
classNamestring–Extra class on the root.

MentionInputHandle

Methods on the ref.

PropTypeDefaultDescription
focus() => void–Focuses the textarea.
insert(text: string) => void–Inserts text at the caret as if typed, so it joins the native undo stack.
openSuggestions(kind: MentionKind) => void–Types @ or # at the caret so suggestions open, adding a space first when needed. Useful for a mention button.
clear() => void–Empties the text and mentions.
textareaHTMLTextAreaElement | null–The underlying textarea.

serializeMentions

Turns a value into storage friendly text, <@id> for people and <#id> for channels by default.

PropTypeDefaultDescription
value (required)MentionValue–The value to serialize.
format(mention: Mention) => string–Custom token for each mention, such as a markdown link.

mentionText

Returns the visible text of a mention, @label or #label.

PropTypeDefaultDescription
kind (required)MentionKind–"person" or "channel".
label (required)string–The mention label.

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

Motion

Responsive behavior

Performance

Notes for AI

Also in special inputs

Guidance for AI tools

Mention input: A textarea with @people and #channel mentions that act as single tokens, with suggestions at the caret. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://ui.xzero.co.uk/llms.txt

Browse all components