intermediate

Управление фокусом

Переносите, удерживайте, восстанавливайте и визуально оформляйте focus для dialog, смены route, ошибок валидации и кастомных виджетов.

Управление фокусом намеренно переносит клавиатурное внимание: в открытый dialog, внутри trap пока модалка активна, обратно на trigger при закрытии и на ошибки валидации после submit. Смена route в SPA должна переносить focus на main или объявлять новый экран.

					function openDialog(trigger: HTMLElement, dialog: HTMLElement) {
  lastFocus = trigger;
  dialog.showModal();
  dialog.querySelector<HTMLElement>('[data-autofocus]')?.focus();
}
function closeDialog() {
  dialog.close();
  lastFocus?.focus();
}
				

| Сценарий | Паттерн | |----------|---------| | Открытие modal | Focus на первый focusable или titled region | | Закрытие modal | Возврат focus на trigger | | Client route | Focus на `<h1>` или `main` с `tabindex="-1"` | | Inline error | Focus на первое невалидное поле + `aria-invalid` |

Focus trap должен допускать Escape и возврат focus — trap без выхода не проходит WCAG и ломает реальных пользователей.

На интервью: autofocus vs programmatic focus; `inert` vs библиотеки trap; focus после навигации React Router.

Типовые ошибки: modal без переноса focus; focus на удалённом узле; блокировка scroll без focus; несколько trap одновременно.

Компромисс — полировка анимаций против немедленного keyboard-контекста после смены UI.

Чеклист:

  • Сохранять и восстанавливать focus trigger для overlay.
  • Переносить focus при route и крупных сменах состояния.
  • Сочетать перенос focus с live announcements при необходимости.
  • Прогон tab cycle внутри dialog end to end.