You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(core): TabList can speak the ARIA tabs pattern
The strip could only be a nav landmark with aria-current, so a consumer with real panels below it had to reimplement the strip to get role=tablist, aria-selected and aria-controls.
mode="tablist" gives them the tabs pattern; nav stays the default and is untouched. A tab does not navigate, so href is ignored there, and a tablist owns only tabs, so anything else in the strip warns in dev — detected from the rendered DOM rather than from children, which misses a conditional, a map, or a consumer's own wrapper.
[feat] TabList: a new `mode` prop chooses which ARIA pattern the strip speaks. `nav` stays the default and is unchanged — a navigation landmark whose current item is marked with `aria-current`. `mode="tablist"` implements the WAI-ARIA tabs pattern instead: `role="tablist"` on the strip, `role="tab"` and `aria-selected` on the tabs, and `aria-controls` pointing at the panel each tab opens, taken from a new `panelId` prop on `Tab`. The keyboard behaviour the pattern asks for was already there — arrows move between tabs, Tab leaves the strip. Because a tab swaps a panel in place rather than navigating, an `href` is ignored in this mode and the tab stays a button, and because a tablist owns only tabs, anything else rendered inside the strip produces a development warning naming what it found. Both warnings are development-only.
Copy file name to clipboardExpand all lines: packages/core/src/TabList/Tab.doc.mjs
+12Lines changed: 12 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -42,6 +42,12 @@ export const docs = {
42
42
description:
43
43
'URL to navigate to; when provided, the tab renders as an anchor element.',
44
44
},
45
+
{
46
+
name: 'panelId',
47
+
type: 'string',
48
+
description:
49
+
'Id of the panel this tab controls, wired up as aria-controls in a tablist-mode TabList. Put the same id on the panel element. No effect in nav mode.',
50
+
},
45
51
{
46
52
name: 'as',
47
53
type: 'LinkComponentType',
@@ -138,6 +144,12 @@ export const docsZh = {
138
144
type: 'string',
139
145
description: '要导航到的 URL;提供时,标签渲染为锚点元素。',
140
146
},
147
+
{
148
+
name: 'panelId',
149
+
type: 'string',
150
+
description:
151
+
'Id of the panel this tab controls, wired up as aria-controls in a tablist-mode TabList. Put the same id on the panel element. No effect in nav mode.',
Copy file name to clipboardExpand all lines: packages/core/src/TabList/TabList.doc.mjs
+6Lines changed: 6 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -60,6 +60,12 @@ export const docs = {
60
60
description: 'Whether to show a bottom border divider under the tab list.',
61
61
default: 'false',
62
62
},
63
+
{
64
+
name: 'mode',
65
+
type: "'nav' | 'tablist'",
66
+
description: "Which ARIA pattern the strip implements. 'nav' (the default) is a navigation landmark whose current item is marked with aria-current. 'tablist' is the WAI-ARIA tabs pattern: role=\"tablist\" / role=\"tab\" and aria-selected, with each tab pointing at the panel it controls via its panelId. Only tabs may live in a tablist strip, and an href on a tab is ignored there.",
0 commit comments