Marble UI
← Components

Mentions

Preview: Default

Textarea with mention suggestions (combobox pattern): type @ to open, arrows to move, Enter/Tab to insert, Escape to close. The textarea is a combobox (`aria-expanded`, `aria-activedescendant`); the text is controlled (`value`/`onChange`) or uncontrolled (`defaultValue`), and inserted mentions are reported through onMentionsChange.

Import

import { MentionsInput } from '@marbleui/ui'

Props

<MentionsInput>

PropTypeDefaultDescription
users *requiredMentionUser[]—
classNamestring—
defaultValuestring''
labelstring'Comment'
namestring—Form field name; the textarea submits its text.
onChange(value: string) => void—
onMentionsChange(ids: string[]) => void—
placeholderstring'Write a comment… use @ to mention'
valuestring—

Usage notes

Comment box that suggests people when you type @. For plain text use TextArea; to pick people from a list use ComboBox or TagsInput.

const team = [{ id: 'u1', name: 'Maya Chen', handle: 'maya' }, { id: 'u2', name: 'Charles Webb', handle: 'charles' }]
<MentionsInput label="Comment" users={team} onMentionsChange={setNotifyIds} />
  • @ at the start or after a space lists up to six people matching name or handle. ↑/↓ move, Enter or Tab inserts @handle , Escape closes; the active option uses aria-activedescendant and the match count is announced.
  • onMentionsChange receives the ids mentioned in the text whenever that set changes, including when a mention is deleted by hand. Handles match whole words, so @ada isn’t found inside @adam.
  • The text is controlled (value + onChange) or uncontrolled (defaultValue); name submits it with a form.
  • The textarea has role="combobox" with aria-expanded, so screen readers know when the list is open.
  • users is a fixed list; there’s no async search.
Example source · show
import { useState } from 'react'
import { MentionsInput } from './mentions'

const users = [{ id: '1', name: 'Maya Chen', handle: 'maya' }, { id: '2', name: 'Charles Webb', handle: 'charles' }, { id: '3', name: 'Ada Park', handle: 'ada' }, { id: '4', name: 'Grace Hopper', handle: 'grace' }, { id: '5', name: 'Leo Martins', handle: 'leo' }]
function Demo() {
  const [ids, setIds] = useState<string[]>([])
  return <div className="flex w-96 flex-col gap-2"><MentionsInput users={users} onMentionsChange={setIds} /><span className="text-xs text-fg-muted" aria-live="polite">Notifying: {ids.map((i) => users.find((u) => u.id === i)!.name).join(', ') || 'nobody'}</span></div>
}
export const styles = { Default: Demo }

Source: packages/ui/src/mentions/mentions.tsx

Catalog

Category
editor
Priority
Extra
Primitive
composed
React Aria
Autocomplete
Base UI
Autocomplete