Примитивы
33
Tabs
Полоса вкладок и её панели. SegmentedControl выглядит похоже и устроен иначе: это радиогруппа на настоящих инпутах, поэтому исключающий выбор, стрелки и переходящий tabindex браузер даёт даром. У вкладки нативного элемента нет, поэтому клавиатура написана вручную — она лежит в @ilomee/aura-core/listbox, рядом с курсором, общим у полосы вкладок, листбокса и меню.
чистая разметка — библиотеки на странице нет
отрендерил aura-react
отрендерил aura-vue
отрендерил aura-svelte
собрано из классов самого aura-angular
What it is, and when to reach for it.
What it is, and when to reach for it.
What it is, and when to reach for it.
What it is, and when to reach for it.
What it is, and when to reach for it.
Код
index.html
<div class="aura-tabs">
<div class="aura-tabs__list" role="tablist" aria-orientation="horizontal">
<button id="t-tab-0" type="button" role="tab" class="aura-tabs__tab" aria-selected="true" aria-controls="t-panel-0" tabindex="0">Overview</button>
<button id="t-tab-1" type="button" role="tab" class="aura-tabs__tab" aria-selected="false" aria-controls="t-panel-1" tabindex="-1">API</button>
<button id="t-tab-2" type="button" role="tab" class="aura-tabs__tab" aria-selected="false" aria-controls="t-panel-2" tabindex="-1" disabled>Recipes</button>
</div>
<div id="t-panel-0" class="aura-tabs__panel" role="tabpanel" aria-labelledby="t-tab-0" tabindex="0">What it is, and when to reach for it.</div>
</div>Demo.tsx
import { Tabs } from '@ilomee/aura-react';
const ITEMS = [
{ id: 'overview', label: 'Overview', content: 'What it is, and when to reach for it.' },
{ id: 'api', label: 'API', content: 'Every prop, with its default.' },
{ id: 'soon', label: 'Recipes', content: 'Not yet.', disabled: true },
];
/**
* Пройдитесь по списку стрелками. Выбор следует за фокусом — так рекомендует WAI-ARIA, и этого же
* ждёт читатель, перебирающий недорогие панели; `manual` нужен там, где отрисовка панели стоит
* того, чего у вас не просили. Выключенная вкладка перешагивается, а не останавливает на себе.
*/
export default function Demo() {
return <Tabs items={ITEMS} />;
}Demo.vue
<script setup lang="ts">
import { Tabs } from '@ilomee/aura-vue';
const ITEMS = [
{ id: 'overview', label: 'Overview', content: 'What it is.' },
{ id: 'api', label: 'API', content: 'Every prop.' },
];
</script>
<template>
<Tabs :items="ITEMS" />
</template>Demo.svelte
<script lang="ts">
import { Tabs } from '@ilomee/aura-svelte';
const ITEMS = [
{ id: 'overview', label: 'Overview', content: 'What it is.' },
{ id: 'api', label: 'API', content: 'Every prop.' },
];
</script>
<Tabs items={ITEMS} />Используется как aura-tabs.
demo.component.ts
<aura-tabs [items]="ITEMS" [(value)]="active" />Пропсы
У чистой разметки нет пропсов — классы ниже и есть весь API. Четыре пакета не делают ничего сверх того, что проставляют вам те же самые классы.
| Имя | Тип | По умолчанию | Примечания |
|---|---|---|---|
| renderPanel | (tab: AuraTab, index: number) => ReactNode | — | Отрисуйте активную панель сами — форму, таблицу, всё, чем строка быть не может. |
| items | AuraTab[] | null | — | |
| valueдвусторонний | string | — | |
| defaultValue | string | — | |
| onValueChangeсобытие | (value: string) => void | — | |
| orientation | 'horizontal' | 'vertical' | 'horizontal' | Какие стрелки принадлежат списку. Другая ось остаётся странице: WAI-ARIA прямо говорит, что Down внутри горизонтальной полосы вкладок — не наш. |
| manual | boolean | false | Двигать курсор, не выбирая; выбор по Enter или Space. По умолчанию выключено, поскольку выбор вслед за фокусом — рекомендация WAI-ARIA. Включайте, когда отрисовка панели стоит того, чего читатель не просил тратить. |
| Имя | Тип | По умолчанию | Примечания |
|---|---|---|---|
| panelслот | { tab: AuraTab; index: number } | — | |
| items | AuraTab[] | null | — | |
| modelValueдвусторонний | string | — | |
| update:modelValueсобытие | (value: string) => void | — | |
| orientation | 'horizontal' | 'vertical' | 'horizontal' | |
| manual | boolean | false |
| Имя | Тип | По умолчанию | Примечания |
|---|---|---|---|
| panelслот | Snippet<[AuraTab, number]> | — | |
| items | AuraTab[] | null | — | |
| valueдвусторонний | string | — | |
| orientation | 'horizontal' | 'vertical' | 'horizontal' | |
| manual | boolean | false |
| Имя | Тип | По умолчанию | Примечания |
|---|---|---|---|
| panelTemplate | TemplateRef<{ $implicit: AuraTab; index: number }> | — | |
| items | AuraTab[] | null | — | |
| valueдвусторонний | string | — | |
| valueChangeсобытие | (value: string) => void | — | |
| orientation | 'horizontal' | 'vertical' | 'horizontal' | |
| manual | boolean | false | |
| id | string | — | Закрепляет префикс идентификаторов. Если не задан, выводится из первой вкладки, а не из внедрённого сервиса: компонент остаётся создаваемым через new, чтобы до него дотягивались тесты чистой логики. |
Какие классы отдаёт
Все фреймворки отдают одни и те же классы — именно поэтому четыре библиотеки выглядят одинаково. Их можно использовать напрямую, вообще без библиотеки компонентов.
| Класс | Роль | Примечания |
|---|---|---|
| .aura-tabs | база | Обязательный. Без него модификатор не работает. |
| .aura-tabs__list | элемент | |
| .aura-tabs__tab | элемент | |
| .aura-tabs__panel | элемент | |
| .aura-tabs--vertical | модификатор |
Токены и правила
components.css- маркер
- a border on the tab itself — one fewer node than a sliding indicator
- линия
- var(--bw-1) solid var(--border), with the tab overlapping it
- выбрана
- var(--accent) on the marker, var(--text) on the label