feat(slash): interactive slash-command picker - filtering, visible highlight, argument hints (LC-509) #476

Merged
longjacksonle merged 5 commits from feat/LC-509-slash-command-picker into main 2026-06-28 04:44:51 +02:00

Turns the composer's slash-command autocomplete into a polished Slack/Discord-style interactive picker, reusing the existing @mention combobox interaction model. Stack stays Askama + HTMX + Tailwind.

What changed

Live filtering + empty state. The server already prefix-filtered; now visible_commands also matches a description keyword (e.g. /action surfaces /me). A query that matches nothing renders a subtle "no matching commands" state instead of silently hiding (the list view now carries the typed query so the template can tell "nothing typed" from "typed, no match").

Visible keyboard highlight. The highlighted option was ARIA-only (invisible) - arrow-key navigation gave no feedback. Added a shared .lc-ac-option rule where hover and aria-selected share one surface-sunken highlight, applied to the slash, mention, and emoji popovers so all three composer autocompletes look uniform.

Argument hinting. While typing a recognized command's arguments (e.g. /poll ), a new hint=true endpoint mode returns a non-interactive usage bar showing the expected syntax + description (/poll "Question" "Option A" "Option B" ...). Inserting a command now drops the caret after the trailing space and immediately surfaces that hint. Because the hint bar has no role=option, the keyboard nav no-ops and Enter sends the message as normal.

Panel polish. Small uppercase header, consistent padding, monospace command token vs muted description, anchored above the composer.

Keyboard model unchanged and consistent with mentions: arrows move the highlight, Tab/Enter insert (trailing space, caret positioned for args), Esc dismisses, click inserts. A stale hint/list is cleared after a send (the box clears with no input event, so a form afterRequest listener re-evaluates).

Tests

Added coverage for the empty state, description-keyword matching, hint mode (usage bar for a known command, empty for an unknown one). just check, just test, just test-saas, just build-css all pass.

Turns the composer's slash-command autocomplete into a polished Slack/Discord-style interactive picker, reusing the existing @mention combobox interaction model. Stack stays Askama + HTMX + Tailwind. ## What changed **Live filtering + empty state.** The server already prefix-filtered; now `visible_commands` also matches a description keyword (e.g. `/action` surfaces `/me`). A query that matches nothing renders a subtle "no matching commands" state instead of silently hiding (the list view now carries the typed query so the template can tell "nothing typed" from "typed, no match"). **Visible keyboard highlight.** The highlighted option was ARIA-only (invisible) - arrow-key navigation gave no feedback. Added a shared `.lc-ac-option` rule where hover and `aria-selected` share one `surface-sunken` highlight, applied to the slash, mention, and emoji popovers so all three composer autocompletes look uniform. **Argument hinting.** While typing a recognized command's arguments (e.g. `/poll `), a new `hint=true` endpoint mode returns a non-interactive usage bar showing the expected syntax + description (`/poll "Question" "Option A" "Option B" ...`). Inserting a command now drops the caret after the trailing space and immediately surfaces that hint. Because the hint bar has no `role=option`, the keyboard nav no-ops and Enter sends the message as normal. **Panel polish.** Small uppercase header, consistent padding, monospace command token vs muted description, anchored above the composer. Keyboard model unchanged and consistent with mentions: arrows move the highlight, Tab/Enter insert (trailing space, caret positioned for args), Esc dismisses, click inserts. A stale hint/list is cleared after a send (the box clears with no input event, so a form `afterRequest` listener re-evaluates). ## Tests Added coverage for the empty state, description-keyword matching, hint mode (usage bar for a known command, empty for an unknown one). `just check`, `just test`, `just test-saas`, `just build-css` all pass.
Extend the autocomplete endpoint: visible_commands now also matches a
description keyword (not just the name prefix); a new hint=true mode returns a
single command's argument-usage bar for the active command; and the list view
carries the typed query so the template can show a 'no matching commands'
empty state instead of just hiding. Adds the room-slash-no-match string (en+es).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
slash_popover gains a header + a 'no matching commands' state and tags rows
with the shared lc-ac-option class; new slash_hint renders the non-interactive
argument-usage bar. Mention + emoji popover rows get the same lc-ac-option
class so all composer autocompletes share the keyboard-highlight styling.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The slash IIFE now also fires while typing a recognized command's arguments
(SLASH_ARGS) and requests the hint bar; inserting a command drops the caret
after the trailing space and immediately surfaces its hint; a form afterRequest
listener clears a stale hint/list after a send (which clears the box with no
input event).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add .lc-ac-header and .lc-ac-option (hover + aria-selected share one
surface-sunken highlight) so the keyboard-highlighted option is visible, not
ARIA-only, across the slash/mention/emoji popovers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
test(slash): cover empty state, description-keyword match, hint mode (LC-509)
All checks were successful
check-secrets / TruffleHog (push) Successful in 4s
check-secrets / Nosey parker (push) Successful in 5s
check-secrets / Kingfisher (push) Successful in 5s
check-secrets / TruffleHog (pull_request) Successful in 5s
Check / clippy + fmt + tests (pull_request) Successful in 3m20s
check-secrets / Nosey parker (pull_request) Successful in 3s
check-secrets / Kingfisher (pull_request) Successful in 7s
Create release / Create release from merged PR (pull_request) Has been skipped
52d25fedeb
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
longjacksonle scheduled this pull request to auto merge when all checks succeed 2026-06-28 04:41:57 +02:00
longjacksonle deleted branch feat/LC-509-slash-command-picker 2026-06-28 04:44:51 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!476
No description provided.