Skip to content
PПромтбук
RUEN
02UI-компоненты

Дизайн поискового поля и подсказок

Что в placeholder, как показывать recents, как обрабатывать no-results и did-you-mean, scope-chips. Поиск, который реально находит.

Действуй как UX-инженер. Поиск — это не «input с лупой». Это отдельный продукт внутри продукта со своим жизненным циклом: пустой → ввод → загрузка → результаты / ничего / ошибка.

Scope: {{scope}} Объём результатов: {{result_count}}

7 принципов поиска, который работает

  1. Affordance видна. Иконка лупы слева + placeholder с конкретным примером. «Search...» — мёртвый паттерн. «Search projects, docs, people...» — живой.
  2. Открыт по умолчанию (на focus или клик). Дропдаун с подсказками появляется до ввода — это recents и suggestions.
  3. Highlight совпадений. Найденные символы выделены в результатах. Без этого юзер не верит результату.
  4. Скорость > точность. Лучше показать 5 правильных за 100ms, чем 50 идеальных за 800ms. Streaming-результаты ОК.
  5. Did-you-mean ОБЯЗАТЕЛЕН при no-results, если есть похожие термины. «Ничего» без альтернативы — провал.
  6. Поиск — это URL. Query → query-param. Шеринг ссылки восстанавливает результаты. Browser-back возвращает к результатам.
  7. Persistence. Recents — last 5 query. Recently opened — last 5 объектов. Хранить локально, очищать при logout.

Анатомия поля

┌─────────────────────────────────────────┐
│ [🔍] Search projects, docs, people...  │  ← placeholder с примерами
└─────────────────────────────────────────┘
       ↓ on focus
┌─────────────────────────────────────────┐
│ [🔍] |                            [⌘K] │  ← shortcut hint
├─────────────────────────────────────────┤
│ Recent searches                          │  ← если есть
│ • API design                             │
│ • Q2 roadmap                             │
├─────────────────────────────────────────┤
│ Recently opened                          │  ← если есть
│ [icon] Project Alpha                     │
│ [icon] Onboarding doc                    │
├─────────────────────────────────────────┤
│ Try: type / for commands                 │  ← подсказка modes
└─────────────────────────────────────────┘

Scope chips (если scope = multi-type)

Чипсы под input'ом для фильтрации по типу:

[All] [Projects] [Documents] [People] [Tasks]
  • Active chip — заполненный (filled).
  • Click — фильтрует результаты без перезагрузки.
  • Состояние в URL: ?q=foo&scope=projects.
  • Если для query результаты есть только в одном scope — auto-select этот scope.

States

Empty (poле в фокусе, ничего не введено)

  • Recent searches (если есть): 3-5 пунктов с иконкой clock.
  • Recently opened: 3-5 объектов с типом-иконкой.
  • Hint: «Try typing / for commands» (если есть command palette).
  • Если пусто и нет истории — короткий tutorial-text: «Search across {{scope}}. Try project name or keyword.»

Typing (>= 2 символов)

  • Debounce 100-150ms.
  • Loading: skeleton-строки 3-5 штук (НЕ spinner).
  • Streaming: первые 3 результата за 100ms, остальные за 300ms.
  • Highlight совпавших символов в результатах.

Results

  • Группировка по типу (если multi-type): секции с заголовками («Projects (3)», «Docs (12)»).
  • Каждый результат: иконка типа + название (с highlight) + 1 строка контекста (snippet с highlight).
  • Внизу: «Show all 47 results» если есть >5 на тип.
  • Keyboard: ↑↓ + Enter.

No results

No results for "{{query}}"

Did you mean: "kickoff"?    ← если есть похожие

Try:
  • Different keywords
  • Remove filters
  • Search in {other_scope}

Or [+] Create new "{{query}}"  ← если применимо

Error

  • Inline сообщение в области результатов: «Search failed. [Retry]»
  • НЕ toast (юзер уже смотрит сюда).

Search snippet (выдержка из результата)

  • 1-2 строки контекста вокруг совпавшего слова.
  • Совпавшие термины — <mark>.
  • Truncate с … по обе стороны: ...the kickoff <mark>meeting</mark> is on Friday at...
  • Если совпадение в title — snippet не нужен (title уже видно).

Did-you-mean

  • Триггер: zero results AND fuzzy-similarity > 0.7 на одном из term'ов.
  • Алгоритм: Levenshtein distance ≤ 2, или soundex, или Trie nearest-neighbor.
  • Показ: «Did you mean: <link>correct_query</link>?» — клик меняет query и обновляет результаты.
  • Тихий редирект (auto-search) — нет. Пусть юзер сам подтвердит.

Performance

  • < 100 объектов: client-side search, мгновенный.
  • 100-1000: client-side с indexed search (Fuse.js, MiniSearch).
  • > 1000: server-side с debounce 200ms, кэш последних 5 query.
  • Cancel предыдущего запроса при новом вводе (AbortController).

A11y

  • Input — role="combobox", aria-autocomplete="list", aria-expanded синхронизировано с дропдауном.
  • Дропдаун — role="listbox".
  • Результаты — role="option", aria-selected на активном.
  • Loading state — aria-busy="true" на дропдауне.
  • Announce: «{N} results» при появлении.
  • Esc закрывает дропдаун, возвращает фокус на input.

Формат вывода

Placeholder

Конкретная строка для данного scope: «Search ___, ___, ___»

Архитектура дропдауна

ASCII-схема или markdown-описание:

  • Empty state: что показывается
  • Typing state: что меняется
  • Results state: группировка
  • No results: содержимое

Scope chips

Список chip'ов в порядке появления + правило auto-select.

Snippet-формат

Пример строки результата + правила truncation.

Did-you-mean

Триггер + алгоритм (общими словами) + UI.

Performance

  • Threshold для client vs server
  • Debounce ms
  • Cancel-policy

A11y чеклист

ARIA + keyboard + announce.

Anti-patterns (НЕ делать)

  • ❌ Placeholder «Search». Юзер не знает что искать. Конкретные примеры.
  • ❌ No-results без альтернативы. «Ничего» — это тупик. Did-you-mean / Create / Switch scope.
  • ❌ Spinner поверх всего дропдауна. Skeleton + streaming.
  • ❌ Поиск без highlight совпадений. Юзер сравнивает с глазами, какое совпало.
  • ❌ Без recents. 80% поисков — повторение того, что искал минуту назад.
  • ❌ Auto-redirect на единственный результат. Покажи его, пусть юзер кликнет. Иначе он не поймёт что произошло.
  • ❌ Search-URL без shareability. /search → /search?q=foo. Без q юзер не может вернуться.
  • ❌ Поиск без aria-live announce. Screen reader юзер не знает, есть ли результаты.
К подразделу «UI-компоненты»
Похожие промты