Installation
import { WrMention, type WrMentionItem } from 'ngwr/mention';
@Component({ imports: [WrMention, FormsModule] })
export class MyComponent {
protected readonly users = [{ label: 'Ada' }, { label: 'Alan' }];
}Basic
Type @ at the start or after a space to open the picker. Arrows navigate, Enter / Tab commits, Esc cancels.
<textarea
wrMention
[wrMentionItems]="users"
[(ngModel)]="text"
></textarea>
<!-- Type @ to open the picker. Arrows + Enter / Tab to commit, Esc to cancel. -->Custom trigger
triggers accepts any character (or set of characters). Use # for tags, : for emoji, etc.
<textarea
wrMention
[wrMentionItems]="tags"
[triggers]="['#']"
[(ngModel)]="text"
></textarea>Types
Data shapes used by the inputs and outputs above.
interface WrMentionItem {
label: string;
[key: string]: unknown;
}| Name | Description | Type | Default |
|---|---|---|---|
WrMentionItem | A mentionable entry — extend with any extra metadata. | interface | — |
labelrequired | Text inserted and shown in the panel. | string | — |
[key: string] | Anything else your app needs back on (selected). | unknown | — |
Accessibility
The field keeps its native role=\textbox\` — it holds prose, and the mention is a fragment inside it, not the field's value. It is deliberately not a combobox: that role is disallowed on <textarea> and would drop aria-multiline`, so a screen reader would stop reporting the field as multi-line for the whole editing session. Nothing here is configurable, and nothing is required of you.
<!-- What the directive renders. You write none of this. -->
<textarea
wrMention
aria-autocomplete="list" <!-- static: a permanent capability of the field, -->
aria-haspopup="listbox" <!-- announced on focus before you type a trigger -->
aria-controls="wr-mention-listbox-1"
aria-activedescendant="wr-mention-listbox-1-opt-2" <!-- only while open -->
></textarea>
<!-- In the overlay: -->
<ul id="wr-mention-listbox-1" role="listbox" aria-label="Mentions">
<li id="wr-mention-listbox-1-opt-0" role="option" aria-selected="false">Ada Lovelace</li>
<li id="wr-mention-listbox-1-opt-2" role="option" aria-selected="true">Grace Hopper</li>
</ul>
<!-- Plus a polite live region on <body>, because aria-expanded is not a
supported state of role=textbox — so "a list appeared" and "X was
inserted" have nowhere else to go: "Matches available: 4" -->API
| Name | Description | Type | Default |
|---|---|---|---|
wrMentionItems | Items to filter against the typed query. | readonly T[] | [] |
triggers | Trigger characters that open the panel. | readonly string[] | ['@'] |
displayWith | Maps an item to its display label. | (item: T) => string | `item.label` |
valueWith | Returns the text to insert into the textarea on commit. Receives the picked item and the trigger char. | ((item: T, trigger: string) => string) | null | `${trigger}${displayWith(item)}` |
filterWith | Custom filter. | ((query: string, item: T) => boolean) | null | case-insensitive `includes` over `displayWith(item)`. |
maxResults | Maximum number of items shown in the panel. | number | 8 |
(wrMentionSelected) | Emits the selected item, trigger, and query whenever the user commits. | WrMentionCommit<T> | — |