Mention Autocomplete
An @ inside a sentence that opens a member list, driven by the keyboard as much as the mouse.
Build an @-mention autocomplete inside a text field. The trigger is the part to get right: match an @ AT A WORD BOUNDARY at the end of the current value, with a regex like /(?:^|\s)@(\w*)$/. Without the boundary, typing an email address opens the menu halfway through the domain, which is how most hand-rolled versions fail. Keyboard support must be COMPLETE or nobody uses it twice: - ArrowDown and ArrowUp move a cursor index, wrapping at both ends - Enter AND Tab both insert the highlighted person - Escape closes without inserting And the highlighted row must be REAL STATE with a visible background, not a hover-only effect. A list you can arrow through but cannot see the cursor in is worse than no keyboard support at all. On insert, replace the trailing @query with the name AND A TRAILING SPACE. Without the space the sentence does not flow and the pattern re-triggers on the name just inserted. Filter from the first character so a long team never shows a menu of everyone. Accessibility: aria-autocomplete="list" and aria-expanded on the input; role="listbox" with an aria-label on the panel; role="option" with aria-selected on each row. Motion: the panel enters on opacity with y -5, 150ms. It is a keyboard-speed surface, so keep it short. Under prefers-reduced-motion, use opacity only. Filtering and keyboard navigation are unchanged. Colors as tokens: accent at low alpha for the highlighted row, accent with on-primary ink for the avatar initials, surface and border for the panel. Use neutral placeholder names. Build the component, not this demo of it. - Ambient motion that IS the component may loop: a drifting background, a marquee, a spinner while something is genuinely loading. - Do not add any timer, interval, loop or script that performs a person's action by itself. No auto-hover, no auto-click, no cycling through states, no pretend submitting, no replaying the interaction on a schedule. - Every state that answers a person waits for a real event from that person. - Placeholder copy and sample content are welcome. Simulated behaviour is not.