При работе с современными веб-приложениями, особенно одностраничными (SPA), управление фокусом становится критически важным для доступности (accessibility) и удобства взаимодействия с интерфейсом. TanStack Router предоставляет встроенные механизмы для контроля фокуса при переходе между маршрутами, обеспечивая согласованное поведение навигации и соответствие стандартам WCAG.
По умолчанию TanStack Router поддерживает автоматическое управление фокусом при навигации. Основная идея заключается в том, что после перехода на новый маршрут фокус перемещается на первый интерактивный элемент страницы или на контейнер контента маршрута.
Механизм работает следующим образом:
При переходе на новый маршрут:
tabindex="-1".button, a[href], input,
textarea, select).Фокус сохраняется между переходами при
использовании back и forward в браузере, если
состояние маршрута включает информацию о последнем активном
элементе.
Пример базовой конфигурации маршрута с фокусом:
import { createRouter, createRoute } from '@tanstack/router';
const rootRoute = createRoute({
path: '/',
component: RootComponent,
onFocus: (el) => {
// Настраиваем кастомное поведение фокуса при загрузке маршрута
if (el) el.focus();
},
});
const router = createRouter({
routeTree: rootRoute,
});
Здесь ключевой момент — использование колбэка onFocus,
который позволяет указать, какой элемент должен получить фокус после
навигации.
Для вложенных маршрутов важно контролировать, чтобы фокус корректно перемещался при каждом уровне маршрута. TanStack Router позволяет настраивать фокус на уровне конкретного маршрута, что обеспечивает гибкость при сложной структуре приложения.
Пример вложенного маршрута:
const dashboardRoute = createRoute({
path: '/dashboard',
component: Dashboard,
children: [
createRoute({
path: 'settings',
component: Settings,
onFocus: (el) => {
// Фокус на первом input в форме настроек
const firstInput = el.querySelector('input');
if (firstInput) firstInput.focus();
},
}),
],
});
В этом примере при переходе на /dashboard/settings фокус
автоматически устанавливается на первый input формы настроек. Такой
подход обеспечивает логичную последовательность
навигации для пользователей, использующих клавиатуру или
вспомогательные технологии.
В некоторых сценариях требуется отложенное выставление
фокуса, например, если компоненты загружаются асинхронно.
TanStack Router поддерживает использование setTimeout или
requestAnimationFrame в onFocus для
задержки:
onFocus: (el) => {
requestAnimationFrame(() => {
const firstButton = el.querySelector('button');
if (firstButton) firstButton.focus();
});
}
Такой подход гарантирует, что фокус будет установлен только после полной отрисовки DOM-элементов маршрута.
tabindex="-1" для контейнеров
страниц: это позволяет легко программно управлять фокусом, не
влияя на естественный порядок табуляции.Фокус-менеджмент напрямую связан с доступностью:
TanStack Router обеспечивает интеграцию с этим подходом на уровне маршрутов, что уменьшает необходимость вручную писать обработчики на каждый переход.
TanStack Router предоставляет гибкие API для настройки поведения фокуса:
onFocus(el) — кастомная логика при переходе на
маршрут.defaultFocusElement — элемент, на который
устанавливается фокус, если колбэк не задан.preserveFocus — опция для сохранения текущего фокуса
при определённых переходах.Пример использования:
const profileRoute = createRoute({
path: '/profile',
component: Profile,
onFocus: (el) => el.querySelector('h1')?.focus(),
preserveFocus: true,
});
Здесь фокус устанавливается на заголовок профиля, и при возвращении на маршрут сохраняется последний активный элемент, что улучшает UX.
Хотите, я могу сделать следующую часть о интеграции focus management с React Transition Group и анимациями переходов в TanStack Router для сложных интерфейсов? Это логичное продолжение темы.