feat(FN-1946): add slash skill autocomplete to chat input

- Fetch discovered skills per project and track autocomplete menu/filter/highlight state in ChatView
- Detect slash triggers in the composer, render filtered skill suggestions, and insert /skill:<name> on selection
- Support keyboard and focus UX for the menu (arrow navigation, Enter/Tab select, Escape dismiss, blur/focus timing)
- Add chat skill menu styling for desktop and mobile layouts using existing dashboard tokens
- Expand ChatView tests to cover menu rendering, filtering, selection flows, loading state, and fetch failures
This commit is contained in:
Fusion
2026-04-17 06:10:10 -07:00
committed by gsxdsm
parent d32db262fe
commit cab4b8390d
3 changed files with 469 additions and 11 deletions

View File

@@ -30770,6 +30770,7 @@ html .column.drag-over * {
/* Input area */
.chat-input-area {
position: relative;
padding: 12px 16px;
border-top: 1px solid var(--border);
display: flex;
@@ -30777,6 +30778,68 @@ html .column.drag-over * {
gap: 8px;
}
/* === Chat Skill Menu === */
.chat-skill-menu {
position: absolute;
left: var(--space-lg);
bottom: calc(100% + var(--space-xs));
min-width: calc((var(--space-xl) * 10) + var(--space-2xl) + (var(--space-xs) * 2));
max-width: calc(100% - (var(--space-lg) * 2));
max-height: calc(var(--space-xl) * 10);
overflow-y: auto;
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius-md);
box-shadow: var(--shadow-lg);
z-index: 50;
}
.chat-skill-menu-item {
width: 100%;
border: none;
background: transparent;
color: inherit;
text-align: left;
padding: var(--space-sm) var(--space-md);
cursor: pointer;
display: flex;
flex-direction: column;
gap: var(--space-xs);
transition: background var(--transition-fast);
}
.chat-skill-menu-item:hover,
.chat-skill-menu-item--highlighted {
background: var(--card-hover);
}
.chat-skill-menu-item:focus-visible {
outline: none;
box-shadow: var(--focus-ring-strong);
background: var(--card-hover);
}
.chat-skill-menu-item-name {
font-size: 0.8125rem;
color: var(--text);
font-family: var(--font-mono);
}
.chat-skill-menu-item-description {
font-size: 0.75rem;
color: var(--text-muted);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: calc((var(--space-xl) * 10) + var(--space-lg) + var(--space-xs));
}
.chat-skill-menu-empty {
padding: var(--space-sm) var(--space-md);
color: var(--text-muted);
font-size: 0.8125rem;
}
.chat-input-textarea {
flex: 1;
resize: none;
@@ -32746,6 +32809,13 @@ html .column.drag-over * {
.chat-thread-header {
padding: 8px 12px;
}
.chat-skill-menu {
left: var(--space-md);
right: calc(var(--space-md) + var(--mobile-nav-height));
min-width: 0;
max-width: none;
}
}
/* === Task Documents === */