Дизайн фильтров и сортировки
Chips vs facets vs sidebar — что выбрать. Multi-select UX, applied-state, reset, persist в URL. Без «гнусной collapsible-панели слева».
Действуй как product designer. Фильтры — это переговоры между «всё показать» и «уточнить». Плохой фильтр прячет важное; хороший — экономит секунды на каждом действии.
Фильтров: {{filter_count}} Тип контента: {{result_density}} Устройство: {{device_focus}}
4 паттерна — где работает каждый
| Паттерн | Когда выбирать | Где живёт |
|---|---|---|
| Inline chips (горизонтальная полоса) | 2-5 фильтров, главные | Над списком, sticky при скролле |
| Faceted sidebar (левая колонка) | 5-15 фильтров, e-commerce / каталог | Левая колонка на desktop, drawer на mobile |
| Toolbar dropdowns | 4-8 фильтров, рабочие интерфейсы | Над таблицей в один ряд |
| Filter sheet (полный список в overlay) | 8+ фильтров на mobile, или продвинутый режим на desktop | Bottom-sheet (mobile), modal/drawer (desktop) |
Карта выбора
- filter_count ≤ 3 + любое устройство → inline chips.
- filter_count 4-7 + desktop-first → toolbar dropdowns.
- filter_count 4-7 + mobile-first → top-3 chips + «More filters» → sheet.
- filter_count 8+ + e-commerce → faceted sidebar.
- filter_count 8+ + admin / dashboard → toolbar dropdowns + advanced sheet.
Anatomy паттернов
Inline chips
Filter: [All ▾] [Status ▾] [Owner ▾] [+ Add filter]
───── ────────── ───────
дефолт активный неактивный
- Активный chip — заполненный (filled), показывает выбранное значение (
Status: Active). - Click → popover/dropdown с опциями.
- × на активном chip — снимает фильтр.
- «+ Add filter» — для редких / опциональных.
Faceted sidebar
┌─────────────┐
│ Category │ ← collapsible group
│ □ Phones (42)│
│ □ Laptops(15)│
├─────────────┤
│ Price │
│ [____|____] │ ← range slider
│ $0 — $1200 │
├─────────────┤
│ Brand │ ← с поиском, если >10
│ 🔍 Search │
│ □ Apple (8) │
│ □ Samsung(5)│
│ Show more (12)│
└─────────────┘
- Counts рядом с опцией: «(42)» — сколько результатов после применения.
- Collapsible groups (категории сворачиваются).
- Search внутри группы при >10 опций.
- «Show more» если >5 опций в группе.
Toolbar dropdowns
[Status: Active ▾] [Owner: Anyone ▾] [Date: Last 30d ▾] [+ Filter] [Sort: Newest ▾]
- В один ряд, sort справа.
- Каждый dropdown — multi-select с чекбоксами.
- Footer popover: «Apply» / «Clear».
Filter sheet (mobile)
┌─────────────────────┐
│ Filters [X] │
├─────────────────────┤
│ Category │
│ [ Phones ] │
│ [ Laptops ] │
│ ────────── │
│ Price │
│ [____|____] │
│ ────────── │
│ ... (scroll) │
├─────────────────────┤
│ [Reset] [Apply (47)] │ ← sticky footer
└─────────────────────┘
- Bottom-sheet с drag-handle.
- Sticky footer с count: «Apply (47)» — сколько результатов покажется.
- Reset рядом с Apply.
- Изменения применяются по Apply, не live (иначе на mobile нет смысла).
Multi-select UX
- Checkboxes, не chips внутри dropdown (chips — для top-level).
- Selection count в trigger:
Status: Active +2если выбрано 3. - Order: выбранные сверху, остальные ниже — после открытия dropdown.
- Search внутри dropdown при >10 опций.
- «All / None» quick toggle в шапке.
Applied state и reset
- Bar с applied filters над списком:
Active: [Status: Active ×] [Owner: Me ×] [Price: $0-$500 ×] Clear all - × на каждом chip снимает фильтр.
- «Clear all» — справа, всегда видно.
- Если фильтров много — collapse в «3 filters applied — Show».
URL persistence (обязательно)
- Каждый фильтр → query-param:
?status=active&owner=me&price_min=0&price_max=500. - Sort → отдельный param:
?sort=date_desc. - Pagination — тоже в URL:
?page=2. - Share URL → восстанавливает фильтры + сортировку + страницу.
- Browser back возвращает к предыдущему состоянию фильтров.
- Не используй hash-routing для фильтров — теряется при SSR/share/social-card.
Sort
- Отдельный dropdown справа, не смешивать с фильтрами.
- Опции — короткие: «Newest», «Oldest», «A→Z», «Z→A», «Most popular», «Price low to high».
- Default sort — релевантность или «Newest». В UI отмечен как «(default)».
- Sort persistance — в URL, как фильтр.
States
- Loading после filter change: skeleton-список (НЕ spinner поверх). Показывай старые данные с blur+disable на 1 сек, потом skeleton.
- No results после фильтра: «No matches for these filters. [Reset filters]» + предложение убрать конкретный фильтр.
- Большое количество фильтров с конфликтом: «3 filters return no results. Try removing: [Status]».
Counts и live preview
- Если возможно — показывать счёт результатов в каждой опции и в Apply-кнопке.
- Async-counts (server-side): debounce 200ms на изменение → server считает.
- Если счёт дорогой — обновлять только по запросу или ленивее.
A11y
- Каждый dropdown / popover —
role="dialog"илиrole="listbox". - Чекбоксы — нативные
<input type="checkbox">, label по клику. - Applied chips — кнопка remove с
aria-label="Remove filter: Status Active". - Live region с количеством результатов после применения: «{N} results».
- Keyboard: Tab по фильтрам, Enter — open, ↑↓ — между опциями, Esc — close.
Формат вывода
Решение
Одна строка: «<chips / sidebar / toolbar / sheet> для desktop, <...> для mobile».
Spec выбранного паттерна
- Расположение
- Поведение клика
- Multi-select правила
- Apply vs live update
- Counts (где и когда)
Applied state
Описание + где живёт + правила reset.
URL-схема
Список параметров: ?filter1=...&filter2=...&sort=...
Sort
- Опции
- Default
- Где живёт
States
- Loading (после filter change)
- No results
- Error
Mobile-адаптация (если desktop-first)
Что меняется на 375px.
A11y чеклист
Роли, keyboard, announce.
Anti-patterns (НЕ делать)
- ❌ Sidebar на mobile без drawer. 30% экрана заняты sidebar'ом — контент не виден.
- ❌ Фильтры без URL. Шеринг ссылки → юзер видит несфильтрованный список.
- ❌ Sort внутри фильтров. Это разные операции — разные UI.
- ❌ Live-update на mobile при каждой выборке. Mobile = batch (Apply).
- ❌ Applied filters только в дропдауне. Юзер не видит что отфильтровал — нужен chip-bar снаружи.
- ❌ Reset кнопка где-то в углу. Должна быть рядом с фильтрами.
- ❌ Counts, которые отстают на полсекунды и врут. Лучше без count, чем с врущими.
- ❌ Filter «Date» с открытым календарём прямо в sidebar. Слишком много UI — popover.
Billing-страница
Что показывать: план, история, способ оплаты, инвойсы, отмена.
Дизайн внутреннего поиска по сайту
Стратегия индексации, ранжирование, фасеты, поведение «ничего не найдено», UX поискового поля и страницы результатов.
Сгенерировать варианты UI-компонента
Создать 4-6 разных подходов к компоненту с разным визуальным языком и трейд-оффами.