Skip to content

Mentions ​

A mention input component that pops a suggestion overlay when typing @ (or # etc.), suited for @member / @task / comment-posting scenarios.

Basic Usage ​

Basic usage

Typing @ pops the suggestion list: ↑/↓ to select, Enter to insert (the selected item is merged into the text), Esc or clicking outside closes it.

Keyword Filtering ​

Keyword filtering

Continue typing after @ to filter: by default it fuzzy-matches label OR value (case-insensitive) (@alice hits "Alice"); when nothing matches, the built-in empty state "No matching mentions" shows. For a custom matcher, set the el.filterOption(query, option) function (JS property channel).

Trigger Right After Chinese Text ​

Trigger without a leading space

No whitespace is required before @: the scan walks back from the caret until a space/newline, so 大家好@张 (Chinese text glued to @) triggers. A keyword segment containing a space or newline does not trigger. While an IME is composing (pinyin candidate not yet confirmed), Enter/↑/↓ will not select suggestions or insert a newline; the panel re-scans after the composition commits.

Multiple Triggers (@ for members / # for tasks) ​

trigger array (@ / #)

trigger defaults to @; it accepts a single string or a JSON array like ["@","#"]. The oas-search/oas-select details carry the matched prefix field, letting the host route each trigger to its own data source. prefix is a compatibility alias of trigger, usable through both attribute and property channels.

Async Suggestions (oas-search + loading) ​

Remote search (simulated)

When a prefix is hit or the keyword changes, oas-search fires immediately (detail { query, prefix }, no built-in debounce — debounce in the host). While the host is fetching, set loading and the panel shows "Loading…"; after options is filled in the list appears. Moving the caret within the same keyword does not re-fire; re-triggering or a keyword change does.

Custom Option Rendering (rich labels / avatars) ​

Rich options (oas-option-render)

After each option row is rendered, oas-option-render fires with detail { index, option, element } — element is the label container the host can rewrite (avatar / two-line rich content), and option carries every extra field from the options JSON. Alternatively, put a <template slot="option"> skeleton inside the component; the [data-option-label] node is bound to the option text automatically.

Disabled Options ​

Disabled options (visible but not selectable)

Options with disabled: true stay visible but are not selectable: ↑/↓, Home/End keyboard navigation skips them, clicks are ignored, and aria-disabled is synced. When every option is disabled, Enter just closes the panel without inserting anything.

Clearable ​

Clearable

Panel direction & separator (placement / split) ​

placement + split

When the text is non-empty and the field is neither disabled nor readonly, a clear button shows in the top-right corner; clicking it clears the text and fires oas-clear (detail carries the previous value) plus an empty oas-change.

Auto-grow (autosize) ​

Comment box (autosize + max-rows)

With autosize, the height adapts between min-rows (default 1) and max-rows (default 6; an explicit "0" means unlimited) and scrolls past the cap. min-rows="2" is typical for comment boxes to leave a comfortable first-line height.

Whole delete (whole) ​

Backspace removes a whole mention in one stroke (whole)

Place the caret right after a mentioned member and press Backspace to remove the whole "@Alice" in one stroke

With whole on, pressing Backspace while the caret sits right after an inserted mention (e.g. "@Alice"; long names containing spaces like "@Bob (teammate)" are also removed in one stroke) removes the whole "trigger + member name" and fires oas-whole-remove (detail { value, option, prefix }, where option is the full original option object). Caret positions that do not match still delete character by character; the separator between the mention and the following text (a space by default) is not removed along with it — delete it separately as needed. Without whole, Backspace deletes character by character (press several times for long names, or undo to restore).

Single-line mode (type) ​

Single-line @assign (type=input)

type defaults to textarea (multi-line); set it to input to compress the field into a single-line input (height locked to one row, Enter does not break the line), suited for scenarios like "single-line @assign"; it still combines with autosize / clearable etc.

Size / Variant / Status / Readonly ​

Size

size supports small / medium / large (follows the size injected by a nearby oas-config-provider).

Variant

Status

status supports success / warning / error: error also sets aria-invalid on the combobox, and it can be driven by oas-form-item / oas-form validation (a host-level aria-invalid is mirrored onto the input automatically).

Readonly / Disabled

readonly is focusable and copyable but not editable and never opens the panel; disabled is fully greyed out.

Header / footer / empty slots

Hint: type @ to mention a member2 members · right-click @ for moreTry another keyword, or type @ to list all

The header / footer slots render panel chrome (hint bar / summary), and the empty slot replaces the default "No matching mentions" text. The split attribute (default: space) controls the delimiter used both for scanning boundaries and for the space inserted after a mention — switch it when you need a different separator such as a comma.

Deleting a Mention ​

A mention is written into the text as plain text. With whole on, pressing Backspace with the caret right after a mention removes the whole segment at once; without whole, deletion is character by character (long names containing spaces need several presses — undo also helps). While the suggestion panel is open, Home/End jump to the first/last suggestion and ↑/↓ cycle (skipping disabled items); in type=input single-line mode, Enter with the panel closed is intercepted and does not break the line.

Events ​

Event feedback

oas-select detail is { value, label, option, prefix } — option is the full original option object (including extra fields), so the host does not need to look up the id afterwards.

Accessible Name (label) ​

label (accessible name)

label becomes the accessible name (aria-label) of the combobox input: screen readers announce it once set; otherwise it falls back to placeholder → built-in text "Mentions input".

Controlled Value ​

value (controlled)

The value attribute is the controlled channel; external changes sync to the textarea immediately. While the user is typing, unrelated attribute changes (options/loading) never overwrite the in-progress draft.

required ​

required (native validation chain)

required drives the native validation chain (form-associated): when unfilled, checkValidity() returns false (valueMissing) and native form submission is blocked; it recovers to :valid once filled.

Programmatic read/write of the current value goes through the public value property (like the native textarea.value): el.value reads the full current text (including @mention marks); el.value = x writes the controlled value attribute and immediately syncs the inner control (controlled assignment takes precedence over unconfirmed drafts) without dispatching events.

API ​

oas-mentions ​

Attributes ​

AttributeDescriptionTypeDefault
autosizeAuto-grow (pair with min-rows/max-rows)boolean—
clearableClear button (clears all content, fires oas-clear)boolean—
disabledDisabledboolean—
labelAccessible name (built-in text by default)——
loadingSuggestion panel loading state (during remote search; pair with oas-search)boolean—
max-rowsMaximum rows (with autosize; "0" uncaps)string—
min-rowsMinimum rows (with autosize)string1
optionsOptions, JSON array [{ label, value }]Option[] | string[]
placeholderPlaceholder textstring—
placementPanel direction: auto (default) / top / bottomstringauto
readonlyRead-only (focusable and readable, no suggestion panel)boolean—
requiredRequired marker (drives the native valueMissing validation chain; not passed through to the inner control)boolean—
sizeSize preset small / medium (default) / largestringmedium
splitSeparator between a mention and following text (default space; not doubled when already separated)string
statusValidation status: error / warning / successstring—
triggerTrigger: default @, accepts a single string or a JSON array like ["@","#"] for multiple triggersstring | string[]@
typeVariant: textarea (default) / input (single-line lock, Enter does not break line)stringtextarea
valueValue (controlled, full text)string—
variantVariant: outlined (default) / filled / borderlessstringoutlined
wholeWhole delete: when cursor is right after a mention, Backspace removes the whole prefix + label and fires oas-whole-removeboolean—

Property (JS property; see each row for attribute reflection) ​

PropertyDescriptionTypeDefault
valueCurrent value: the full text including @mention tokensstring—

Events ​

EventDescription
oas-blurFires on blur, detail: { value: this.ta.value }
oas-changeText changed after insertion, detail: { value } (full text)
oas-clearFires on clear, detail: { value } (pre-clear value)
oas-focusFires on focus, detail: { value: t.value }
oas-inputFires on input (not during IME composition), detail: { value }
oas-option-renderFires on option render (rich option channel), detail: { index, option, element }
oas-searchFires when the trigger scan finds pending text (remote search hook), detail: { query, prefix }
oas-selectSuggestion selected, detail: { value, label, option, prefix } (option is the full original option object)
oas-whole-removeFires when a mention is whole-deleted, detail: { value, option, prefix } (option is the full original option object)

Slots ​

NameDescription
emptyEmpty-state content when nothing matches (replaces the default noMatch text)
footerPanel footer content
headerPanel header content
template[slot="option"]Custom option template ([data-option-label] binding)

CSS Variables ​

CSS VariableDefault
--oas-glass-blurnone
--oas-glass-ringtransparent

Released under the MIT OR Apache-2.0 License.