# @mention field
> Textarea with @mention suggestions for files, people and agents; matched letters are marked and inserted mentions become dotted chips.
- Element: `<hf-mention>`
- React: `import { HfMention } from "@/components/lumesec/hf-mention"`
- Collection: Pixel HD (https://elements.lumesec.ai/components/pixel-hd)
- Registry item: https://elements.lumesec.ai/r/hf-mention.json
- Page: https://elements.lumesec.ai/components/pixel-hd/mention



Live preview: https://elements.lumesec.ai/view/hf-mention

```html
<hf-mention name="msg" label="Message"></hf-mention>
```

## Playground

Change a prop and the component updates. Props marked live animate to the new value; the others rebuild the element.

## Installation

```bash
npx shadcn@latest add @lumesec/hf-mention
```

First time with the @lumesec registry? Register it once, or install by URL:

```bash
npx shadcn@latest registry add @lumesec=https://elements.lumesec.ai/r/{name}.json
npx shadcn@latest add https://elements.lumesec.ai/r/hf-mention.json
```

## Usage

React:

```tsx
import { HfMention } from "@/components/lumesec/hf-mention";

export function Example() {
  return (
    <HfMention name="msg" label="Message" />
  );
}
```

HTML:

```html
<script type="module" src="https://elements.lumesec.ai/cdn/hf-mention.js"></script>

<hf-mention name="msg" label="Message"></hf-mention>
```

## Behaviour

Type @ for files, people and agents. Suggestions filter as you type with matched letters marked; inserted mentions become dotted chips that flash in.

## API reference

### Attributes

| Attribute     | React prop    | Type     | Default                                                   | Description                                                                                  |
| ------------- | ------------- | -------- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| `label`       | `label`       | `string` | `Message`                                                 | Label text, also the textarea's `aria-label`. Read once on connect.                          |
| `placeholder` | `placeholder` | `string` | `Type @ to mention a file, person or agent`               | Placeholder for the empty textarea.                                                          |
| `value`       | `value`       | `string` | `Can @lukas look at @src/auth/session.ts before we ship?` | Initial text. Read once on connect; omitting it or leaving it empty loads the demo sentence. |
| `name`        | `name`        | `string` | —                                                         | Form field name used when the element is inside a form.                                      |

### Events

Events bubble and cross the shadow boundary unless the description says otherwise.

| Event     | React prop  | Detail              | Description                                                                                                     |
| --------- | ----------- | ------------------- | --------------------------------------------------------------------------------------------------------------- |
| `input`   | `onInput`   | `{ value: string }` | Fires on each edit and after a mention is inserted, with the full text.                                         |
| `mention` | `onMention` | `{ value: string }` | Fires when a suggestion is inserted. `value` is the mention without the `@`, for example `src/auth/session.ts`. |

### Properties

| Property           | Type                      | Description                                                                                                 |
| ------------------ | ------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `value`            | `string`                  | The textarea text. Setting it replaces the text and updates the chips and form value without firing events. |
| `form` (read-only) | `HTMLFormElement \| null` | The owning form, from `ElementInternals`.                                                                   |
| `name` (read-only) | `string \| null`          | The `name` attribute. There is no setter; set the attribute instead.                                        |

## Keyboard

| Keys                | Action                                                      |
| ------------------- | ----------------------------------------------------------- |
| ArrowDown / ArrowUp | While suggestions are open: move the highlight, wrapping.   |
| Enter / Tab         | While suggestions are open: insert the highlighted mention. |
| Escape              | While suggestions are open: close the list.                 |

## Accessibility

* The textarea has an `aria-label` from `label`, `aria-autocomplete="list"` and `aria-haspopup="listbox"`.
* Suggestions use `role="listbox"` and `role="option"`, with `aria-selected` on the highlighted entry. Focus stays in the textarea; there is no `aria-activedescendant` or `aria-expanded`.
* The visible label element is not associated with the textarea; the `aria-label` provides the name.
* Chips and suggestion icons are drawn on an `aria-hidden` canvas.
* Form-associated through `ElementInternals`.
* Submits the full text under `name`. There is no validation, and form reset and `disabled` are not handled.
* Reduced motion: the highlight jumps between suggestions instead of springing and the hint line changes without rolling; the flash on an inserted chip still plays.

## Theming

The element reads your shadcn theme tokens through its shadow root, so light and dark follow your theme. The accent comes from `--lumesec`. See [Theming](/docs/theming).

This component reads `--border`, `--card`, `--foreground`, `--lumesec` and `--muted-foreground`.

To restyle only LumeSec elements, set the matching `--ui-*` overrides: `--ui-accent`, `--ui-border`, `--ui-fg`, `--ui-font`, `--ui-mono`, `--ui-muted` and `--ui-surface`.

## Notes

* Suggestions come from a built-in list of six demo entries (three files, two people and one reviewer agent) and cannot be configured. Up to five matches show; the query matches the name or the description.
* The list opens after an `@` at the start of the text or after whitespace, followed by letters, digits, `.`, `/`, `_` or `-`.
* Only mentions from the built-in list are drawn as chips. The textarea grows with its content from a minimum of 92px.
* The inner textarea's native `input` events stay inside the shadow root, so `input` listeners on the host receive one event per keystroke, the element's own, with `detail.value`.


