diff --git a/frontend/css/main.css b/frontend/css/main.css index 60957d3..6247f1b 100644 --- a/frontend/css/main.css +++ b/frontend/css/main.css @@ -76,6 +76,21 @@ body { max-height: 360px; padding: 4px 0; overflow-y: auto; z-index: 100; } .workspace-switcher.open .workspace-switcher-menu { display: block; } +/* #16: sticky type-to-filter search header inside the (scrolling) menu. */ +.workspace-switcher-search { + position: sticky; top: 0; z-index: 1; + background: var(--bg-card); padding: 8px; + border-bottom: 1px solid var(--border); +} +.workspace-switcher-search input { + width: 100%; box-sizing: border-box; padding: 6px 8px; + background: var(--bg-input); border: 1px solid var(--border); + border-radius: var(--radius); color: var(--text-primary); font-size: 13px; +} +.workspace-switcher-search input:focus { outline: none; border-color: var(--accent); } +.workspace-switcher-noresults { + padding: 12px; color: var(--text-muted); font-size: 13px; text-align: center; +} .workspace-switcher-item { display: flex; align-items: center; gap: 8px; padding: 8px 12px; cursor: pointer; @@ -84,6 +99,8 @@ body { } .workspace-switcher-item:last-child { border-bottom: none; } .workspace-switcher-item:hover { background: var(--bg-input); } +/* keyboard-cursor highlight (arrow keys) - same surface as hover */ +.workspace-switcher-item.highlighted { background: var(--bg-input); } .workspace-switcher-item.current { font-weight: 600; } .workspace-switcher-item .check { flex-shrink: 0; color: var(--accent); width: 14px; diff --git a/frontend/js/components/workspace-switcher.js b/frontend/js/components/workspace-switcher.js index 1f324b9..69dd68a 100644 --- a/frontend/js/components/workspace-switcher.js +++ b/frontend/js/components/workspace-switcher.js @@ -42,6 +42,12 @@ export function renderWorkspaceSwitcher(me) { const sorted = [...list].sort((a, b) => a.name.localeCompare(b.name)); const current = sorted.find(w => w.id === currentId) || sorted[0]; + // Issue #16: show a type-to-filter search box once the list is big enough to + // be painful to scroll (MSPs run 100+ orgs). Below the threshold a plain list + // is fine. The full list is already loaded from /me, so filtering is client-side. + const SHOW_SEARCH_THRESHOLD = 8; + const showSearch = sorted.length >= SHOW_SEARCH_THRESHOLD; + container.innerHTML = `