Навигация с клавиатуры — критически важный аспект доступности веб-приложений. В Preact реализация клавиатурной навигации требует понимания событий клавиатуры, управления фокусом и правильной структуры компонентов. Preact предоставляет легковесный API, позволяющий эффективно работать с этими задачами без дополнительных библиотек.
В Preact события клавиатуры обрабатываются через стандартные обработчики, аналогичные React:
function handleKeyDown(event) {
if (event.key === 'ArrowDown') {
console.log('Пользователь нажал стрелку вниз');
}
}
Подключение обработчика к элементу осуществляется через атрибут
onKeyDown:
<button onKeyD own={handleKeyDown}>Нажми меня</button>
Особенности работы с Preact:
onKeyDown,
onKeyUp и onKeyPress. Рекомендуется
использовать onKeyDown для обработки навигации, так как оно
срабатывает при нажатии клавиши, до её отпускания.event.key обеспечивает кроссбраузерную совместимость, в
отличие от устаревшего event.keyCode.Фокус — основной инструмент навигации с клавиатуры. В Preact управление фокусом производится через рефы:
import { h } from 'preact';
import { useRef } from 'preact/hooks';
function FocusableInput() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} type="text" />
<button onCl ick={focusInput}>Сфокусировать поле</button>
</div>
);
}
Ключевые моменты:
useRef возвращает объект с полем current,
указывающим на DOM-элемент..focus() позволяет программно установить фокус на
элемент.<div> или <span>
можно использовать tabIndex={0}, чтобы сделать их
фокусируемыми.Порядок перемещения фокуса с клавишей Tab определяется естественным
потоком документа и атрибутом tabIndex:
<div tabIndex={0}>Элемент 1</div>
<div tabIndex={0}>Элемент 2</div>
<div tabIndex={0}>Элемент 3</div>
Особенности использования tabIndex:
tabIndex={0} — элемент доступен в естественном порядке
табуляции.tabIndex={-1} — элемент фокусируемый программно, но
пропускается при обычной навигации Tab.tabIndex={>0} — задаёт явный порядок обхода.
Используется редко, так как может усложнять поддерживаемость.В крупных приложениях часто требуется перемещаться между компонентами, например, списками или меню. Для этого применяются массивы рефов:
import { useRef } from 'preact/hooks';
function Menu() {
const itemsRef = useRef([]);
const handleKeyDown = (index) => (event) => {
if (event.key === 'ArrowDown') {
const nextIndex = (index + 1) % itemsRef.current.length;
itemsRef.current[nextIndex].focus();
}
if (event.key === 'ArrowUp') {
const prevIndex = (index - 1 + itemsRef.current.length) % itemsRef.current.length;
itemsRef.current[prevIndex].focus();
}
};
return (
<ul>
{['Пункт 1', 'Пункт 2', 'Пункт 3'].map((item, i) => (
<li
key={i}
tabIndex={0}
ref={el => itemsRef.current[i] = el}
onKeyD own={handleKeyDown(i)}
>
{item}
</li>
))}
</ul>
);
}
Особенности данного подхода:
% и сложения с длиной массива.Для правильной навигации с клавиатуры важно учитывать ARIA-атрибуты:
role="menu" и role="menuitem" для
меню.aria-selected для выделенных элементов.aria-expanded для раскрывающихся списков.Пример интеграции с Preact:
<li
role="menuitem"
aria-selected={selectedIndex === i}
tabIndex={0}
onKeyD own={handleKeyDown(i)}
>
{item}
</li>
Принципы работы:
Для сложной навигации часто требуется реагировать на комбинации клавиш:
function handleKeyCombination(event) {
if (event.ctrlKey && event.key === 'ArrowRight') {
console.log('Переход к следующему разделу');
}
}
Рекомендации:
ctrlKey, shiftKey,
altKey или metaKey.onKeyDown для обработки нажатий.useRef и .focus() для управления
фокусом.tabIndex элементам для правильного
обхода.Эта стратегия обеспечивает гибкую, доступную и управляемую навигацию с клавиатуры в приложениях на Preact, сохраняя лёгкость и высокую производительность фреймворка.