Cmd+K command bar — спецификация UX
Командная палитра, которая реально ускоряет работу: ranking, секции, shortcuts, recently used, empty state, fuzzy match. Без «поиск с симпатичной анимацией».
Действуй как product designer, который проектировал командные палитры в Linear / Notion / Raycast. Cmd+K — это не «modal с поиском». Это главный keyboard-API продукта. От него зависит, насколько продукт нравится power-юзерам.
Домен: {{domain}} Объём данных у юзера: {{user_volume}}
Закон Cmd+K: 5 принципов
- Открывается всегда одинаково. Cmd+K (Mac) / Ctrl+K (Win). Не Cmd+P, не Cmd+/. Стандарт индустрии — соблюдай.
- Open → type → enter за <2 секунды. Если юзер ждёт 500ms открытия — не использует.
- Ranking важнее полноты. Лучше показать 5 правильных результатов, чем 50 в случайном порядке.
- Ничего не работает без recents. 80% использований — «вернуться к тому, с чем работал минуту назад».
- Discoverable но не intrusive. Хинт в углу или в search-баре. Не модал «попробуйте Cmd+K!» при первом входе.
Анатомия
┌─────────────────────────────────────────────────┐
│ [icon] Search or jump to... [Esc] │ ← input + dismiss
├─────────────────────────────────────────────────┤
│ Recently used │ ← section header (small caps, грей)
│ [icon] Project Alpha ↩ │
│ [icon] Switch to Inbox ⌘1 │ ← shortcut hint справа
├─────────────────────────────────────────────────┤
│ Actions │
│ [+ icon] Create new task ⌘N │
│ [→ icon] Go to Settings │
├─────────────────────────────────────────────────┤
│ Projects (12) │ ← счёт после fuzzy match
│ [icon] Project Beta │
│ [icon] Project Gamma │
├─────────────────────────────────────────────────┤
│ ↑↓ navigate ↩ open ⌘⌫ delete ? help │ ← footer hints (не всегда виден)
└─────────────────────────────────────────────────┘
Секции (показывать в этом порядке)
- Recently used (3-5 элементов) — самое первое при пустом query. Не показывать после ввода 2+ символов.
- Suggested actions — контекстные действия, релевантные текущему экрану («Edit this page», «Share current doc»).
- Actions — глобальные действия (Create, Switch theme, Logout, Settings).
- Objects по типам — Projects, Documents, Contacts. Разделить визуально, дать счёт в header (
Projects (12)). - Help / docs — последняя секция, показывать только если query совпадает с темой.
Ranking (порядок результатов)
Score = sum of:
- Exact prefix match: +100 (
promatchesProject Alphafirst) - Word boundary match: +50 (
alpmatchesProject Alpha) - Fuzzy match (subsequence): +10 (
pamatchesProject Alpha) - Recency: +30 if opened in last hour, +15 in last day, +5 in last week
- Frequency: +20 if accessed >10 times
- Type weight: actions > objects > help (для коротких query)
Внутри секции сортируй по score, между секциями — по фиксированному порядку.
Поведение
Open
- Cmd+K из любого места.
- Esc — close, восстановить фокус на предыдущий элемент.
- Open с пустым query → показать recents + suggested actions.
Type
- Debounce 50-80ms (быстро, но не каждое нажатие).
- При смене query — обновить результаты, скроллнуть вверх, сфокусироваться на первом результате.
- Highlight совпавших символов (например,
<mark>тег с тонким фоном).
Navigate
- ↑↓ — между результатами, включая переходы между секциями.
- Tab / Shift+Tab — внутри секции (опционально, для двух-колоночной раскладки).
- Enter — open selected.
- Cmd+Enter — open в новой вкладке (для объектов с URL).
- Cmd+Backspace — удалить из recents.
Modes (опционально, для продвинутых)
>префикс → только actions#→ только tags / labels@→ только users / contacts/→ переход к роуту
Подсказка о modes — в footer или help (?).
Empty state
- Нет recents → одна строка с примерами: "Try: Project name, /settings, +task".
- Нет результатов → "Nothing matches '{{query}}'" + кнопка «Create new {{query}}» (если применимо).
Loading
- Если результаты грузятся из бэкенда — показывай skeleton-строки в области результатов, НЕ spinner.
- Локальные результаты (recents, actions) показывай мгновенно поверх loading remote.
Производительность
- < 100 объектов — fuzzy match на клиенте.
- 100-1000 — fuzzy match на клиенте с web-worker для тяжёлых query.
- > 1000 — серверный search с локальным fallback на recents.
- Кэш последних 5 query на 60 секунд.
A11y
- Input —
role="combobox",aria-autocomplete="list". - Results —
role="listbox", каждый —role="option". - Активная опция —
aria-selected="true". - Screen reader announce: «{N} results» при смене query.
- Esc и click-outside dismiss обязательны.
Формат вывода
Концепция
2-3 предложения: что это палитра делает для данного домена.
Структура секций
Список секций в порядке появления + правила показа.
Ranking
Формула + примеры (3 query → ожидаемый порядок результатов).
Shortcuts
| Действие | Клавиша | Заметки |
States
- Open (empty query):
- Open (typed):
- No results:
- Loading:
- Error:
Modes
Список префиксов и что они фильтруют (если применимо).
A11y чеклист
ARIA-роли, keyboard-поведение, announce-сообщения.
Anti-patterns (НЕ делать)
- ❌ Открывать на Cmd+P, Cmd+/ или другой комбинации. Юзеры знают Cmd+K.
- ❌ Анимация открытия > 200ms. Cmd+K — это инструмент, не цирк.
- ❌ Показывать 50 результатов без ранжирования. Лучше 5 правильных + «X more».
- ❌ Search без fuzzy. «kicktof» должен находить «Kickoff meeting». Substring-only — каменный век.
- ❌ Recents, в которые попадает всё подряд. Recents — только то, что юзер реально открыл (не hover, не preview).
- ❌ Spinner поверх результатов. Skeleton или partial-results.
- ❌ Closing на mouseover вне палитры. Закрывается только Esc / click-outside / Enter.
- ❌ Палитра, в которой нельзя создать новый объект. «Create new "{{query}}"» — must-have для большинства доменов.
Billing-страница
Что показывать: план, история, способ оплаты, инвойсы, отмена.
Дизайн внутреннего поиска по сайту
Стратегия индексации, ранжирование, фасеты, поведение «ничего не найдено», UX поискового поля и страницы результатов.
Сгенерировать варианты UI-компонента
Создать 4-6 разных подходов к компоненту с разным визуальным языком и трейд-оффами.