Контекстні меню та швидкі дії
1) Призначення та сфера застосування
Контекстні меню і швидкі дії скорочують шлях до часто використовуваних операцій:- Локальні дії над об'єктом (картка, рядок таблиці, коефіцієнт).
- Пакетні дії над виділенням.
- Приховані, але не критичні опції (другорядні).
- Правило: критичні і первинні дії не ховати тільки в контекстне меню.
2) Тригери і варіанти
Right-click/Shift + F10/Menu key - класичне контекстне.
Icon button (kebab'⋮', meatballs'...', context) - універсально для тач/десктопа.
Long-press (400-600 мс) - мобільний еквівалент right-click.
Command palette (⇧⌘P/Ctrl + K) - глобальні швидкі команди з пошуком.
Swipe-reveal (iOS/Android списки) - відкриває ряд швидких шорткатів.
Рекомендація: забезпечте мінімум два способи виклику (іконка + контекстний клік/клавіша).
3) Зміст і пріоритет
Перші 1-3 пункти - часті дії; потім роздільник; далі - рідше використовувані.
Деструктивні - в кінці, позначені кольором/іконкою (і часто - через підтвердження/undo).
Формулювання - дієслово + об'єкт («Додати в обране», «Скопіювати ID»).
Лейбл ≠ тільки іконка: іконка - підсилювач, не заміна тексту.
4) Угруповання і стан
Роздільники для логічних блоків (перегляд, редагування, адмін, небезпечні).
Стани: `disabled`, `checked` (`menuitemcheckbox`/`menuitemradio`), `destructive`.
Не показуємо недоступні по ролі якщо це плутає; альтернативно - показуємо як «disabled» з підказкою причини.
5) Доступність (A11y)
Контейнер: 'role = «menu»', елементи: `role="menuitem"` / `menuitemcheckbox` / `menuitemradio`.
Roving tabindex: єдиний'tabindex =» 0»'на поточному елементі, решта'-1'.
Стрілки ↑↓ - переміщення, →/← - вхід/вихід з підменю. Enter/Space - активація, Esc - закрити.
Typeahead: друк першої літери переносить фокус на пункт.
Фокус-кільце видно; контраст тексту та іконок ≥ AA.
Для іконки-кнопки використовуйте'aria-haspopup =» menu»'і'aria-expanded'.
html
<button id="more" aria-haspopup="menu" aria-expanded="false" aria-controls="menu-1">Еще</button>
<ul id="menu-1" role="menu" aria-labelledby="more" hidden>
<li role="menuitem" tabindex="0">Открыть</li>
<li role="menuitem">Скопировать ссылку</li>
<li role="menuitemcheckbox" aria-checked="true">В избранном</li>
<li role="menuitem" data-danger="true">Удалить</li>
</ul>
Навігація (схема roving tabindex):
js const menu = document.getElementById('menu-1');
menu.addEventListener('keydown', e=>{
const items=[...menu.querySelectorAll('[role^="menuitem"]')];
let i=items.findIndex(n=>n.tabIndex===0);
if(e.key==='ArrowDown'){ items[i].tabIndex=-1; items[(i+1)%items.length].tabIndex=0; items[(i+1)%items.length].focus(); e.preventDefault(); }
if(e.key==='ArrowUp'){ items[i].tabIndex=-1; items[(i-1+items.length)%items.length].tabIndex=0; items[(i-1+items.length)%items.length].focus(); e.preventDefault(); }
if(e.key==='Escape'){ menu.hidden=true; document.getElementById('more').focus(); }
});
6) Позиціонування та перформанс
Відкривайте меню біля джерела (клік-точка/іконка), зсув 4-8 px; слідкуйте за краями екрану (flip/shift).
Портал/шар поверх ('z-index') з ловлею кліка поза.
Рендеріть ліниво, рециклюйте список в довгих меню (віртуалізація не потрібна, але уникайте сотень пунктів).
Анімації тільки'opacity/transform', тривалість 140-200 мс (out швидше: 100-160 мс).
Підменю відкривайте по'ArrowRight'і hover із затримкою 80-120 мс (anti-flicker).
7) Мобільні патерни
Long-press з хаптикою; таймінг 450 ± 100 мс.
Bottom sheet як форма контекстного меню (thumb-reachable).
Swipe actions у списках: ліворуч - «архів/вибране», праворуч - «видалити» (підтвердження/undo).
Зони кліка ≥ 44 × 44, підписи короткі, іконки 20-24 px.
8) Підтвердження, undo і безпека
Деструктивні дії: або друге підтвердження (modal/confirm pattern), або undo 5-10 с.
Фінансові/ризикові - через явний confirm з контекстом наслідків.
Показуйте причину'disabled'( «Недостатньо прав», «Досягнуто ліміт»).
9) Швидкі дії без меню
Inline-шорткати в рядку (іконки «», «», «» ⋯ «»).
Hover-reveal (десктоп): показувати дії при наведенні, але залишати і явний тригер.
Command palette: пошук за діями, гарячі клавіші в підказках («⌘S», «Ctrl + Enter»).
10) Копірайтинг та іконки
Дієслово + об'єкт, 2-3 слова.
Починайте з дії («Видалити запис»...), не з іменника («Видалення запису»).
Іконки з єдиного набору; використовуйте однакові піктограми для однакових дій у всьому продукті.
Пояснюючі підказки ('title '/tooltip) для неоднозначних пунктів.
11) Телеметрія та експерименти
CTR по пунктах, медіана часу від відкриття до кліка, частота відмін/undo.
Число misclick'ів (деструктивні → скасовані).
A/B: порядок і групування пунктів, наявність швидких шорткатів у списку.
Логи «невидимих» пунктів (ніхто не використовує) - кандидати на видалення/перенесення.
12) Токени дизайн-системи (приклад)
json
{
"menu": {
"minWidth": 208,
"itemHeight": 36,
"gap": 4,
"padding": 8,
"radius": 12,
"elev": 8,
"anim": { "inMs": 180, "outMs": 120, "ease": "cubic-bezier(0.2,0,0.2,1)" }
},
"swipe": { "revealThresholdPx": 56, "confirmDestructive": true }
}
CSS-пресети:
css
.menu{min-width:208px;padding:8px;border-radius:12px;box-shadow:var(--elev-3);background:var(--bg-elevated)}
.menu [role^="menuitem"]{height:36px;padding:0 12px;display:flex;gap:8px;align-items:center;border-radius:10px}
.menu [role^="menuitem"]:hover,
.menu [role^="menuitem"][tabindex="0"]{background:var(--bg-hover)}
.menu [data-danger="true"]{color:var(--role-danger)}
13) Патерни за компонентами
Картки/плитки: іконка «⋯» у правому верхньому кутку; на hover - показується, на тач - видно завжди.
Рядки таблиці: '⋯'в останній колонці; при множинному виділенні - панель пакетних дій зверху/знизу.
Списки чатів/повідомлень: swipe-actions (архів/прочитано/видалити) з undo.
Медіа-галереї: довгий тап → режим мультивибору + нижня панель дій.
14) Специфіка iGaming
Швидка ставка (quick bet): в контекстному меню коефіцієнта - «Поставити X» (передбудови), «Додати в купон», «Підписатися на зміну коефіцієнта». Підтвердження/undo обов'язкові.
Вибране/підписки: «Додати провайдера/гру в обране», «Підписатися на турнір».
Кеш-аут: з інлайн-підтвердженням і поточною сумою; доступно тільки при статусі ринку.
Модерація/репорти: «Поскаржитися», «Заблокувати чат» - безпечні, видно за ролями.
Відповідальна гра: «Встановити ліміт», «Пауза 24ч» - без агресивних кольорів, з ясним описом наслідків.
15) Анти-патерни
Критичні дії заховані тільки в контекстне меню.
Пункти без тексту (одні іконки), особливо в списках.
Випадкове закриття на догляд курсора при переході в підменю (немає затримки/коридору).
Меню перекриває елемент-джерело або йде за екран (немає flip/shift).
Деструктивні без підтвердження/undo.
Неочевидні права (пункт пропадає без пояснення).
16) QA-чек-лист
Доступність
- 'role = «menu «'/' menuitem'коректні, roving tabindex і стрілки працюють.
- Esc закриває меню, фокус повертається до джерела.
- Контраст і фокус-кільця відповідають AA.
Поведінка
- Порядок пунктів відображає частоту і ризик; деструктивні внизу.
- Позиціонування враховує краї (flip/shift); анімації швидкі (≤ 200 мс).
Підменю відкривається по ArrowRight і не «тремтить» (hover-intent 80-120 мс).
Мобільні
- Long-press з хаптикою; bottom-sheet зручний великим пальцем.
- Swipe-actions мають undo; зони кліка ≥ 44 × 44.
Безпека
- Підтвердження/undo для небезпечних дій; причини disabled зрозумілі.
- Немає витоку приватних даних в підказках/лейблах.
Метрики
- Знімається CTR/час до кліка; misclick/undo моніторяться.
17) Реалізація: відкриття/закриття і клік-поза
js const btn=document.getElementById('more'), menu=document.getElementById('menu-1');
const open=()=>{ menu.hidden=false; btn.setAttribute('aria-expanded','true'); menu.querySelector('[role^="menuitem"]').focus(); };
const close=()=>{ menu.hidden=true; btn.setAttribute('aria-expanded','false'); btn.focus(); };
btn.addEventListener('click', e=>{ menu.hidden?open():close(); });
document.addEventListener('pointerdown', e=>{ if(!menu.hidden &&!menu.contains(e.target) && e.target!==btn) close(); });
window.addEventListener('blur', close);
18) Документація в дизайн-системі
Компоненти: `ContextMenu`, `MenuItem`, `Submenu`, `BottomSheet`, `SwipeAction`, `CommandPalette`.
Токени розмірів/висоти рядка/радіуса/анімацій.
Гайди за доступністю (ARIA, клавіатура, typeahead).
«Do/Don't» з прикладами угруповання, позиціонування і підтверджень.
Коротке резюме
Контекстні меню і швидкі дії прискорюють роботу, якщо вони передбачувані, доступні і безпечні: два шляхи виклику, ясні лейбли з іконками, розумне угруповання, підтвердження/undo для ризику, коректна клавіатурна навігація і чітке позиціонування. Зафіксуйте токени і патерни в дизайн-системі - і користувачі будуть діяти швидко, не побоюючись помилитися.