Tabs, Toolbar, Menubar и Tree используют общую модель клавиатуры: одна основная остановка Tab, стрелки внутри и зеркальное направление для письма справа налево. Breadcrumbs и NavigationTree сохраняют нативную навигацию по ссылкам и кнопкам. Mercury выводит настоящие ссылки и не выполняет маршрутизацию приложения за вас.
Одна остановка Tab, стрелки внутри
- Одна остановка: Tabs, Toolbar, Menubar и Tree включают в порядок Tab ровно один элемент — тот, на котором фокус был в последний раз. Поэтому Tab позволяет выйти за пределы виджета целиком.
- Стрелки внутри: стрелки перемещают фокус между элементами виджета; Home и End ведут к началу и концу.
- Зеркальное направление: в контексте письма справа налево Left и Right меняются местами. Каждый виджет принимает свойство
dir; без него Tabs читает вычисленное направление, а Tree, Toolbar и Menubar — окружение UI, заданное черезDirectionProvider. - Фокус не равен выбору: перемещение фокуса не подтверждает выбор, если компонент явно этого не предусматривает (автоматические Tabs,
selectionFollowsFocusу Tree).
Tabs
Tabs — фасад: передайте tabs и выбранное value; при выборе вкладки он вызовет onChange(value).
- Вкладка —
{ label, value, disabled?, content?, panelId? }. При наличииcontentTabs выводит панель вкладки; при наличииpanelIdвкладка управляет панелью, которую вы выводите в другом месте. activationMode:automatic(по умолчанию) выбирает вкладку, получившую фокус;manualлишь перемещает фокус, а выбор происходит по Enter, Space или щелчку.orientation:horizontal(по умолчанию) использует Left и Right;vertical— Up и Down.loop: стрелки замыкают переход с последней вкладки на первую; по умолчаниюtrue.keepMounted: сохраняет содержимое невыбранных панелей смонтированным, но скрытым. По умолчанию содержимое невыбранной панели не выводится.variant:underline(по умолчанию) либоpills.
Части Tabs
Для раскладки, которой нет у фасада, соберите TabsRoot › TabsList › TabsTrigger и по одному TabsPanel на каждый trigger, сопоставляя их по value. Корень принимает value либо defaultValue и onValueChange — запрос, который владелец управляемого состояния может отклонить, — а также те же orientation, dir, activationMode, loop и keepMounted, что и фасад. TabsList принимает variant.
Breadcrumbs
Breadcrumbs показывает путь к текущей странице: ориентир nav, по умолчанию с именем «Breadcrumbs», содержит упорядоченный список нативных ссылок. Его дочерние элементы — Breadcrumb.
- Текущий элемент ровно один, с
aria-current="page": последний, если ни один элемент явно не задаётcurrent. - Элемент
disabled— удалённый либо недоступный предок: выводится текстом, не ссылкой; рядом можно показатьdisabledReason. maxItemsсворачивает середину: остаются первый элемент, кнопка скрытых пунктов и последниеmaxItems - 2элемента; минимум — 3. Кнопка открывает немодальную панель со скрытыми ссылками в исходном порядке.renderLinkвыводит каждого предка через ссылку вашего маршрутизатора, которая обязана создавать<a href>.- Также:
separator(по умолчанию шеврон, зеркальный при письме справа налево),truncateдля длинных имён, а такжеoverflowLabelиoverflowPanelLabelдля имён частей раскрытия.
Mercury не выполняет переход, не отменяет щелчок и не меняет историю: ссылки остаются ссылками.
Tree
Tree — управляемая иерархия сущностей, дерево WAI-ARIA. Четыре состояния разделены: фокус (активный узел), выбор, раскрытие и загрузка.
- Узлы: каждый
TreeNodeDataсодержитid,label,children,disabledиkind:leaf,branchлибоlazyдля ещё не загруженных владельцем данных потомков. Ошибка загрузки не превращает ленивый узел в лист. - Раскрытие:
expandedIdsуправляется извне;onExpandedChange(ids, change)запрашивает изменение. Ленивый узел сначала вызываетloadChildren(id); при отклонении загрузки узел остаётся раскрываемым с возможностью повторной попытки. - Выбор:
selectionModeпо умолчанию равенnone, также доступныsingleиmultiple, сselectedIdsиonSelectionChange.selectionFollowsFocusсвязывает клавиатурный фокус с выбором в одиночном режиме. - Клавиши: Up, Down, Home и End перемещают фокус; Right раскрывает узел, затем переходит к первому потомку; Left сворачивает, затем переходит к родителю; Space выбирает; Enter вызывает
onActivate(id), который открывает узел и отделён как от раскрытия, так и от выбора. - Фокус:
activeId,defaultActiveIdиonActiveChange. Если владелец удаляет узел с фокусом, фокус переходит к сохранившемуся родителю, иначе — к соседу. - Для каждого узла:
renderLabelиrenderActions.TreeItemAction(переименование, удаление) попадает в порядок Tab лишь пока его узел активен; стрелки и Enter на узле не нажимают это действие.
NavigationTree — дерево ссылок
NavigationTree отличается от Tree: его узлы — маршруты, а значение — текущее местоположение читателя, а не выбор.
- Каждый узел —
{ id, label, href?, target?, rel?, download?, children? }. Узел сhref— настоящая ссылка; без него — заголовок для потомков. - У каждой ветви есть отдельная кнопка раскрытия с именем из «Toggle» и подписи узла, с
aria-expanded. Кнопка только раскрывает; ссылка только выполняет переход. currentIdотмечает текущий маршрут черезaria-current="page". По умолчанию предки текущего маршрута изначально раскрыты, поэтому маршрут виден при открытии страницы;expandedIdsлибоdefaultExpandedIdsиonExpandedChangeпозволяют управлять этим.labelобязателен и задаёт имя ориентираnav.onNavigate(href, event)позволяет клиентскому маршрутизатору обработать обычный щелчок основной кнопкой с переходом в той же вкладке. Приложение само выполняет маршрутизацию и вызываетevent.preventDefault(). Щелчки с модификаторами, другие вкладки и скачивания сохраняют нативное поведение.
Menubar
Menubar — строка меню в стиле настольного приложения. Фасад принимает menus, каждый элемент — { label, icon?, items }, а также accent и dir. У пункта есть type: item (по умолчанию), check, radio, label либо separator. Строки принимают label, shortcut, icon, onSelect и disabled; строке check нужен id; строки radio объединяются по group, каждая имеет value; checked задаёт начальное состояние.
В исходнике описано управление клавишами: Left и Right перемещают между кнопками меню, а внутри открытого меню открывают соседнее. Enter, Space и ArrowDown открывают меню на первой строке, ArrowUp — на последней. Escape, выбор строки и Tab закрывают меню с возвратом фокуса на его кнопку.
Составная форма — MenubarRoot с одним MenubarMenuRoot на меню, внутри которого находятся MenubarTrigger и MenubarContent. Содержимое принимает те же части, что и Dropdown: MenubarItem, MenubarCheckboxItem, MenubarRadioGroup, MenubarRadioItem, MenubarItemIndicator, MenubarGroup, MenubarLabel, MenubarSeparator, а также MenubarSub с MenubarSubTrigger и MenubarSubContent.
Toolbar
Toolbar — одна точка входа с клавиатуры в строку или столбец элементов управления. Tab входит в панель и выходит из неё; стрелки перемещают между элементами, Home и End — к началу и концу. Вложенные input, textarea или select сохраняют свои клавиши редактирования. Toolbar внутри другого Toolbar выводится как group, фокусом управляет внешняя панель.
- Свойства:
orientation(horizontalлибоvertical),dir,loop(по умолчаниюtrue),size(smлибоmd),variant(surfaceрисует панель,plainтолько располагает элементы). - Недоступные элементы: при
focusableWhenDisabledотключённая часть сохраняет возможность фокуса и получаетaria-disabled, чтобы объясняющая причину подсказка оставалась доступной. Собственная настройка части имеет приоритет. - Части:
ToolbarButton(по умолчаниюtype="button"),ToolbarLink,ToolbarGroup,ToolbarSeparator, а такжеToolbarToggleGroupс элементамиToolbarToggleItem. Группа сtype="single"задаёт единственный выбор —radiogroupсо значениемstring; сtype="multiple"— группу независимых нажатых кнопок со значениемstring[].
Компонент Mercury Toggle тоже входит в набор Toolbar: он читает контекст панели.
Заголовок страницы
import { useState } from "@fiberfx/hyperscript/hooks";
import { Breadcrumb, Breadcrumbs, Tabs } from "@fiberfx/ui";
type View = "lesson" | "companion";
export function LessonHeader() {
const [view, setView] = useState<View>("lesson");
return (
<header>
<Breadcrumbs>
<Breadcrumb href="/">Mercury</Breadcrumb>
<Breadcrumb href="/ui">UI</Breadcrumb>
<Breadcrumb href="/ui/navigation">Navigation</Breadcrumb>
</Breadcrumbs>
<Tabs<View>
value={view}
onChange={setView}
tabs={[
{ label: "Lesson", value: "lesson", content: <p>The page.</p> },
{ label: "For agents", value: "companion", content: <p>The companion.</p> },
]}
/>
</header>
);
}
Последняя хлебная крошка становится текущей страницей без явного указания. Вкладки выводят собственные панели; смонтировано содержимое только выбранной.
Остальные компоненты семейства
| Компонент | Назначение |
|---|---|
Accordion |
последовательность раскрываемых секций |
NavigationMenu |
навигация сайта с панелями ссылок |
Pagination |
пошаговое переключение страниц |
TabNav |
навигационные вкладки в виде ссылок |
TreeDestinationPicker |
сценарий «Переместить в…» по дереву |