MDX (Markdown + JSX) позволяет объединять разметку Markdown с компонентами React, что создаёт мощный инструмент для документирования и построения интерфейсов. Навигация с клавиатуры — ключевой аспект доступности и удобства использования приложений на основе MDX, особенно если контент содержит интерактивные компоненты.
Для управления фокусом в MDX-компонентах используется стандартный подход React:
import { useRef, useEffect } from 'react';
function FocusableButton() {
const buttonRef = useRef(null);
useEffect(() => {
buttonRef.current.focus();
}, []);
return ;
}
Ключевые моменты:
useRef создаёт ссылку на DOM-элемент.useEffect позволяет автоматически устанавливать фокус
после рендеринга.Для обработки нажатий клавиш используется событие
onKeyDown или onKeyUp. Это позволяет
реализовать кастомное поведение при использовании стрелок, Enter, Tab и
других клавиш.
function KeyNavigator() {
const handleKeyDown = (e) => {
switch (e.key) {
case 'ArrowDown':
console.log('Перемещаемся вниз');
break;
case 'ArrowUp':
console.log('Перемещаемся вверх');
break;
case 'Enter':
console.log('Активируем элемент');
break;
}
};
return Навигация с клавиатуры;
}
Особенности:
tabIndex={0} делает div фокусируемым.tabIndexНавигация по MDX-контенту зависит от правильного использования
атрибута tabIndex:
tabIndex="0" — элемент включается в
естественный порядок табуляции.tabIndex="-1" — элемент можно
сфокусировать программно, но не через Tab.tabIndex="1,2,...n" — явная
последовательность фокуса (редко рекомендуется).Пример:
Пункт 1
Пункт 2
Пункт 3
Такой подход обеспечивает предсказуемый порядок навигации по интерактивным элементам.
MDX часто используется для документации компонентов UI. Навигация в списках требует управления фокусом и состояния выделенного элемента:
import { useState } from 'react';
function Menu() {
const [activeIndex, setActiveIndex] = useState(0);
const items = ['Пункт A', 'Пункт B', 'Пункт C'];
const handleKeyDown = (e) => {
if (e.key === 'ArrowDown') {
setActiveIndex((prev) => (prev + 1) % items.length);
} else if (e.key === 'ArrowUp') {
setActiveIndex((prev) => (prev - 1 + items.length) % items.length);
}
};
return (
{items.map((item, index) => (
-
{item}
))}
);
}
Особенности:
useState для хранения активного
индекса.MDX позволяет вставлять любые React-компоненты. При создании интерактивных элементов необходимо соблюдать следующие принципы:
onKeyDown для реализации логики навигации.role, aria-selected,
aria-expanded и другие.Пример для вкладок:
function Tabs({ tabs }) {
const [active, setActive] = useState(0);
const handleKeyDown = (e) => {
if (e.key === 'ArrowRight') setActive((prev) => (prev + 1) % tabs.length);
if (e.key === 'ArrowLeft') setActive((prev) => (prev - 1 + tabs.length) % tabs.length);
};
return (
{tabs.map((tab, index) => (
))}
{tabs[active].content}
);
}
Принципы:
role и aria-* делает вкладки
доступными для скринридеров.tabIndex обеспечивает правильный порядок
навигации.MDX-документы часто содержат смешанный контент: текст, списки, таблицы, формы. Важно учитывать:
Заголовок 1
Заголовок 2
Ячейка A1
Ячейка A2
Ячейка B1
Ячейка B2