aidos-ui 4.0.0 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +14 -1
- package/CLAUDE.md +72 -0
- package/dist/BaseButton.js.map +1 -1
- package/dist/BaseLink.js.map +1 -1
- package/dist/BaseListItem.d.ts +1 -1
- package/dist/Calendar.d.ts +2 -2
- package/dist/DarkMode.js.map +1 -1
- package/dist/DatePicker.js.map +1 -1
- package/dist/Dialog.d.ts +3 -3
- package/dist/Dialog.js.map +1 -1
- package/dist/Dropdown.js.map +1 -1
- package/dist/Icon.d.ts +3 -3
- package/dist/Icon.js +2 -21
- package/dist/Icon.js.map +1 -1
- package/dist/Interactable.js.map +1 -1
- package/dist/NextJSRouterState.js.map +1 -1
- package/dist/OnVisible.d.ts +1 -1
- package/dist/OnVisible.js.map +1 -1
- package/dist/Popover.d.ts +3 -3
- package/dist/Popover.js.map +1 -1
- package/dist/Providers.d.ts +2 -2
- package/dist/RangeInput.d.ts +1 -1
- package/dist/RootView.js.map +1 -1
- package/dist/Select.d.ts +0 -1
- package/dist/Storage.d.ts +2 -1
- package/dist/Storage.js.map +1 -1
- package/dist/Stream.js.map +1 -1
- package/dist/Text.js.map +1 -1
- package/dist/TextInput.d.ts +3 -2
- package/dist/TextInput.js +13 -4
- package/dist/TextInput.js.map +1 -1
- package/dist/TextPairing.js.map +1 -1
- package/dist/Tooltip.d.ts +2 -2
- package/dist/Tooltip.js.map +1 -1
- package/dist/aria.js.map +1 -1
- package/dist/hash.js.map +1 -1
- package/dist/jss.d.ts +6 -6
- package/dist/jss.js +2 -2
- package/dist/jss.js.map +1 -1
- package/dist/numberToBase.js.map +1 -1
- package/dist/stateMachineContextFactory.js.map +1 -1
- package/dist/useCookie.js.map +1 -1
- package/dist/useKeyboard.js.map +1 -1
- package/dist/useNavigation.js.map +1 -1
- package/dist/useRefEffect.js.map +1 -1
- package/next-env.d.ts +2 -1
- package/next.config.js +2 -1
- package/package.json +27 -20
- package/src/BaseListItem.tsx +1 -1
- package/src/Calendar.tsx +2 -2
- package/src/Dialog.tsx +3 -3
- package/src/Icon.tsx +4 -30
- package/src/Popover.tsx +3 -3
- package/src/Providers.tsx +1 -1
- package/src/RangeInput.tsx +1 -1
- package/src/Storage.tsx +1 -1
- package/src/TextInput.tsx +17 -5
- package/src/Tooltip.tsx +2 -2
- package/src/docs/mdx.tsx +40 -0
- package/src/docs/searchIndex.ts +1 -1
- package/src/jss.tsx +3 -3
- package/src/pages/Badge.mdx +136 -14
- package/src/pages/Button.mdx +121 -63
- package/src/pages/Calendar.mdx +196 -2
- package/src/pages/Card.mdx +123 -47
- package/src/pages/Checkbox.mdx +103 -28
- package/src/pages/Dialog.mdx +172 -7
- package/src/pages/FlexLayout.mdx +185 -51
- package/src/pages/Hashing.mdx +199 -8
- package/src/pages/Icon.mdx +150 -42
- package/src/pages/IconButton.mdx +127 -116
- package/src/pages/Link.mdx +118 -47
- package/src/pages/List.mdx +167 -283
- package/src/pages/ListHeader.mdx +157 -27
- package/src/pages/Popover.mdx +177 -55
- package/src/pages/ProgressBar.mdx +186 -6
- package/src/pages/ProgressCircle.mdx +196 -13
- package/src/pages/RangeInput.mdx +189 -61
- package/src/pages/Tabs.mdx +202 -346
- package/src/pages/Text.mdx +102 -81
- package/src/pages/TextInput.mdx +169 -44
- package/src/pages/TextPairing.mdx +164 -115
- package/src/pages/TimeInput.mdx +142 -37
- package/src/pages/Tooltip.mdx +99 -12
- package/src/pages/_app.tsx +13 -3
- package/src/pages/css-in-js.mdx +196 -83
- package/src/pages/navigation.mdx +122 -20
- package/src/pages/useCookie.mdx +168 -7
- package/src/pages/useKeyboard.mdx +242 -5
- package/src/pages/useNavigation.mdx +244 -16
- package/src/pages/usePromise.mdx +271 -6
- package/src/pages/useRefEffect.mdx +230 -28
- package/tsconfig.json +13 -4
package/src/pages/Tabs.mdx
CHANGED
|
@@ -1,425 +1,281 @@
|
|
|
1
1
|
import { Column } from "../Column";
|
|
2
|
+
import { Row } from "../Row";
|
|
2
3
|
import { Tabs } from "../Tabs";
|
|
3
4
|
import { Badge } from "../Badge";
|
|
5
|
+
import { Span } from "../Text";
|
|
4
6
|
import { cssVar } from "../jss";
|
|
5
7
|
|
|
6
8
|
# Tabs
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
A horizontal tab navigation component with full keyboard support and ARIA compliance. Tabs can render as links or buttons and support custom styling, add-ons, and label rendering.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Props
|
|
15
|
+
|
|
16
|
+
### Tabs
|
|
17
|
+
|
|
18
|
+
| Prop | Type | Default | Description |
|
|
19
|
+
|------|------|---------|-------------|
|
|
20
|
+
| `aria-controls` | `string` | Required | ID of the content panel this tab controls |
|
|
21
|
+
| `tabs` | `Tab[]` | Required | Array of tab configurations |
|
|
22
|
+
| `labelSize` | `Size` | `"large"` | Text size for tab labels |
|
|
23
|
+
| `tabPadding` | `Padding` | `"medium"` | Padding inside each tab |
|
|
24
|
+
| `gap` | `Gap` | `"none"` | Space between tabs |
|
|
25
|
+
| `jssTab` | `JSS \| (data) => JSS` | - | Custom styles for tabs (can be conditional on selected state) |
|
|
26
|
+
| `labelRenderer` | `(label: string) => ReactNode` | - | Custom label rendering function |
|
|
27
|
+
|
|
28
|
+
### Tab object
|
|
29
|
+
|
|
30
|
+
| Property | Type | Default | Description |
|
|
31
|
+
|----------|------|---------|-------------|
|
|
32
|
+
| `label` | `string` | Required | Tab display text |
|
|
33
|
+
| `href` | `string` | - | Link URL (renders as link if provided) |
|
|
34
|
+
| `onClick` | `() => void` | - | Click handler (renders as button if no href) |
|
|
35
|
+
| `selected` | `boolean` | `false` | Whether this tab is currently selected |
|
|
36
|
+
| `addOn` | `ReactNode` | - | Additional element (e.g., badge, icon) |
|
|
37
|
+
| `addOnPosition` | `"start" \| "end"` | `"start"` | Position of add-on relative to label |
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Basic usage
|
|
9
42
|
|
|
10
43
|
<Column gap="medium">
|
|
11
44
|
<Tabs
|
|
12
|
-
aria-controls="
|
|
45
|
+
aria-controls="panel-1"
|
|
13
46
|
tabs={[
|
|
14
|
-
{
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
label: "Tab 1",
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
href: "/Tabs",
|
|
21
|
-
selected: false,
|
|
22
|
-
label: "Tab 2",
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
href: "/Tabs",
|
|
26
|
-
selected: false,
|
|
27
|
-
label: "Tab 3",
|
|
28
|
-
},
|
|
29
|
-
]}
|
|
30
|
-
/>
|
|
31
|
-
<Tabs
|
|
32
|
-
aria-controls="foo"
|
|
33
|
-
tabs={[
|
|
34
|
-
{
|
|
35
|
-
href: "/Tabs",
|
|
36
|
-
selected: false,
|
|
37
|
-
label: "Tab 1",
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
href: "/Tabs",
|
|
41
|
-
selected: true,
|
|
42
|
-
label: "Tab 2",
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
href: "/Tabs",
|
|
46
|
-
addOn: (
|
|
47
|
-
<Badge
|
|
48
|
-
jss={{ margin: cssVar("--spacing-m") }}
|
|
49
|
-
color="highlight"
|
|
50
|
-
size="medium"
|
|
51
|
-
/>
|
|
52
|
-
),
|
|
53
|
-
selected: false,
|
|
54
|
-
label: "Tab 3",
|
|
55
|
-
},
|
|
56
|
-
]}
|
|
57
|
-
/>
|
|
58
|
-
<Tabs
|
|
59
|
-
aria-controls="foo"
|
|
60
|
-
tabs={[
|
|
61
|
-
{
|
|
62
|
-
href: "/Tabs",
|
|
63
|
-
selected: false,
|
|
64
|
-
label: "Tab 1",
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
href: "/Tabs",
|
|
68
|
-
selected: false,
|
|
69
|
-
label: "Tab 2",
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
href: "/Tabs",
|
|
73
|
-
addOn: (
|
|
74
|
-
<Badge
|
|
75
|
-
jss={{ margin: cssVar("--spacing-m") }}
|
|
76
|
-
color="highlight"
|
|
77
|
-
size="medium"
|
|
78
|
-
/>
|
|
79
|
-
),
|
|
80
|
-
addOnPosition: "end",
|
|
81
|
-
selected: true,
|
|
82
|
-
label: "Tab 3",
|
|
83
|
-
},
|
|
47
|
+
{ href: "/Tabs", selected: true, label: "Tab 1" },
|
|
48
|
+
{ href: "/Tabs", selected: false, label: "Tab 2" },
|
|
49
|
+
{ href: "/Tabs", selected: false, label: "Tab 3" },
|
|
84
50
|
]}
|
|
85
51
|
/>
|
|
86
52
|
</Column>
|
|
87
53
|
|
|
88
54
|
```js
|
|
55
|
+
<Tabs
|
|
56
|
+
aria-controls="panel-1"
|
|
57
|
+
tabs={[
|
|
58
|
+
{ href: "/Tabs", selected: true, label: "Tab 1" },
|
|
59
|
+
{ href: "/Tabs", selected: false, label: "Tab 2" },
|
|
60
|
+
{ href: "/Tabs", selected: false, label: "Tab 3" },
|
|
61
|
+
]}
|
|
62
|
+
/>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## With add-ons
|
|
68
|
+
|
|
69
|
+
Add badges, icons, or other elements to tabs:
|
|
70
|
+
|
|
89
71
|
<Column gap="medium">
|
|
90
72
|
<Tabs
|
|
91
|
-
aria-controls="
|
|
73
|
+
aria-controls="panel-2"
|
|
92
74
|
tabs={[
|
|
75
|
+
{ href: "/Tabs", selected: false, label: "Messages" },
|
|
93
76
|
{
|
|
94
77
|
href: "/Tabs",
|
|
95
78
|
selected: true,
|
|
96
|
-
label: "
|
|
97
|
-
|
|
98
|
-
{
|
|
99
|
-
href: "/Tabs",
|
|
100
|
-
selected: false,
|
|
101
|
-
label: "Tab 2",
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
href: "/Tabs",
|
|
105
|
-
selected: false,
|
|
106
|
-
label: "Tab 3",
|
|
79
|
+
label: "Notifications",
|
|
80
|
+
addOn: <Badge jss={{ margin: cssVar("--spacing-m") }} color="negative" size="small" />,
|
|
107
81
|
},
|
|
82
|
+
{ href: "/Tabs", selected: false, label: "Settings" },
|
|
108
83
|
]}
|
|
109
84
|
/>
|
|
110
85
|
<Tabs
|
|
111
|
-
aria-controls="
|
|
86
|
+
aria-controls="panel-3"
|
|
112
87
|
tabs={[
|
|
113
|
-
{
|
|
114
|
-
|
|
115
|
-
selected: false,
|
|
116
|
-
label: "Tab 1",
|
|
117
|
-
},
|
|
88
|
+
{ href: "/Tabs", selected: false, label: "Overview" },
|
|
89
|
+
{ href: "/Tabs", selected: false, label: "Analytics" },
|
|
118
90
|
{
|
|
119
91
|
href: "/Tabs",
|
|
120
92
|
selected: true,
|
|
121
|
-
label: "
|
|
122
|
-
|
|
123
|
-
{
|
|
124
|
-
href: "/Tabs",
|
|
125
|
-
addOn: (
|
|
126
|
-
<Badge
|
|
127
|
-
jss={{ margin: cssVar("--spacing-m") }}
|
|
128
|
-
color="highlight"
|
|
129
|
-
size="medium"
|
|
130
|
-
/>
|
|
131
|
-
),
|
|
132
|
-
selected: false,
|
|
133
|
-
label: "Tab 3",
|
|
134
|
-
},
|
|
135
|
-
]}
|
|
136
|
-
/>
|
|
137
|
-
<Tabs
|
|
138
|
-
aria-controls="foo"
|
|
139
|
-
tabs={[
|
|
140
|
-
{
|
|
141
|
-
href: "/Tabs",
|
|
142
|
-
selected: false,
|
|
143
|
-
label: "Tab 1",
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
href: "/Tabs",
|
|
147
|
-
selected: false,
|
|
148
|
-
label: "Tab 2",
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
href: "/Tabs",
|
|
152
|
-
addOn: (
|
|
153
|
-
<Badge
|
|
154
|
-
jss={{ margin: cssVar("--spacing-m") }}
|
|
155
|
-
color="highlight"
|
|
156
|
-
size="medium"
|
|
157
|
-
/>
|
|
158
|
-
),
|
|
93
|
+
label: "New",
|
|
94
|
+
addOn: <Badge jss={{ margin: cssVar("--spacing-m") }} color="highlight" size="medium" />,
|
|
159
95
|
addOnPosition: "end",
|
|
160
|
-
selected: true,
|
|
161
|
-
label: "Tab 3",
|
|
162
96
|
},
|
|
163
97
|
]}
|
|
164
98
|
/>
|
|
165
99
|
</Column>
|
|
100
|
+
|
|
101
|
+
```js
|
|
102
|
+
// Badge before label (default)
|
|
103
|
+
<Tabs
|
|
104
|
+
aria-controls="panel"
|
|
105
|
+
tabs={[
|
|
106
|
+
{ href: "/messages", selected: false, label: "Messages" },
|
|
107
|
+
{
|
|
108
|
+
href: "/notifications",
|
|
109
|
+
selected: true,
|
|
110
|
+
label: "Notifications",
|
|
111
|
+
addOn: <Badge color="negative" size="small" />,
|
|
112
|
+
},
|
|
113
|
+
]}
|
|
114
|
+
/>
|
|
115
|
+
|
|
116
|
+
// Badge after label
|
|
117
|
+
<Tabs
|
|
118
|
+
aria-controls="panel"
|
|
119
|
+
tabs={[
|
|
120
|
+
{
|
|
121
|
+
href: "/new",
|
|
122
|
+
selected: true,
|
|
123
|
+
label: "New",
|
|
124
|
+
addOn: <Badge color="highlight" size="medium" />,
|
|
125
|
+
addOnPosition: "end",
|
|
126
|
+
},
|
|
127
|
+
]}
|
|
128
|
+
/>
|
|
166
129
|
```
|
|
167
130
|
|
|
168
131
|
---
|
|
169
132
|
|
|
170
133
|
## Tabs as buttons
|
|
171
134
|
|
|
172
|
-
|
|
135
|
+
Omit `href` to render tabs as buttons. Useful for in-page tab switching:
|
|
173
136
|
|
|
174
137
|
<Column gap="medium">
|
|
175
138
|
<Tabs
|
|
176
|
-
aria-controls="
|
|
177
|
-
tabs={[
|
|
178
|
-
{
|
|
179
|
-
selected: true,
|
|
180
|
-
label: "Tab 1",
|
|
181
|
-
},
|
|
182
|
-
{
|
|
183
|
-
selected: false,
|
|
184
|
-
label: "Tab 2",
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
selected: false,
|
|
188
|
-
label: "Tab 3",
|
|
189
|
-
},
|
|
190
|
-
]}
|
|
191
|
-
/>
|
|
192
|
-
<Tabs
|
|
193
|
-
aria-controls="foo"
|
|
139
|
+
aria-controls="panel-4"
|
|
194
140
|
tabs={[
|
|
195
|
-
{
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
selected: true,
|
|
201
|
-
label: "Tab 2",
|
|
202
|
-
},
|
|
203
|
-
{
|
|
204
|
-
addOn: (
|
|
205
|
-
<Badge
|
|
206
|
-
jss={{ margin: cssVar("--spacing-m") }}
|
|
207
|
-
color="highlight"
|
|
208
|
-
size="medium"
|
|
209
|
-
/>
|
|
210
|
-
),
|
|
211
|
-
selected: false,
|
|
212
|
-
label: "Tab 3",
|
|
213
|
-
},
|
|
214
|
-
]}
|
|
215
|
-
/>
|
|
216
|
-
<Tabs
|
|
217
|
-
aria-controls="foo"
|
|
218
|
-
tabs={[
|
|
219
|
-
{
|
|
220
|
-
selected: false,
|
|
221
|
-
label: "Tab 1",
|
|
222
|
-
},
|
|
223
|
-
{
|
|
224
|
-
selected: false,
|
|
225
|
-
label: "Tab 2",
|
|
226
|
-
},
|
|
227
|
-
{
|
|
228
|
-
addOn: (
|
|
229
|
-
<Badge
|
|
230
|
-
jss={{ margin: cssVar("--spacing-m") }}
|
|
231
|
-
color="highlight"
|
|
232
|
-
size="medium"
|
|
233
|
-
/>
|
|
234
|
-
),
|
|
235
|
-
addOnPosition: "end",
|
|
236
|
-
selected: true,
|
|
237
|
-
label: "Tab 3",
|
|
238
|
-
},
|
|
141
|
+
{ selected: true, label: "Details" },
|
|
142
|
+
{ selected: false, label: "Reviews" },
|
|
143
|
+
{ selected: false, label: "Related" },
|
|
239
144
|
]}
|
|
240
145
|
/>
|
|
241
146
|
</Column>
|
|
242
147
|
|
|
243
148
|
```js
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
selected: false,
|
|
267
|
-
label: "Tab 1",
|
|
268
|
-
},
|
|
269
|
-
{
|
|
270
|
-
selected: true,
|
|
271
|
-
label: "Tab 2",
|
|
272
|
-
},
|
|
273
|
-
{
|
|
274
|
-
addOn: (
|
|
275
|
-
<Badge
|
|
276
|
-
jss={{ margin: cssVar("--spacing-m") }}
|
|
277
|
-
color="highlight"
|
|
278
|
-
size="medium"
|
|
279
|
-
/>
|
|
280
|
-
),
|
|
281
|
-
selected: false,
|
|
282
|
-
label: "Tab 3",
|
|
283
|
-
},
|
|
284
|
-
]}
|
|
285
|
-
/>
|
|
286
|
-
<Tabs
|
|
287
|
-
aria-controls="foo"
|
|
288
|
-
tabs={[
|
|
289
|
-
{
|
|
290
|
-
selected: false,
|
|
291
|
-
label: "Tab 1",
|
|
292
|
-
},
|
|
293
|
-
{
|
|
294
|
-
selected: false,
|
|
295
|
-
label: "Tab 2",
|
|
296
|
-
},
|
|
297
|
-
{
|
|
298
|
-
addOn: (
|
|
299
|
-
<Badge
|
|
300
|
-
jss={{ margin: cssVar("--spacing-m") }}
|
|
301
|
-
color="highlight"
|
|
302
|
-
size="medium"
|
|
303
|
-
/>
|
|
304
|
-
),
|
|
305
|
-
addOnPosition: "end",
|
|
306
|
-
selected: true,
|
|
307
|
-
label: "Tab 3",
|
|
308
|
-
},
|
|
309
|
-
]}
|
|
310
|
-
/>
|
|
311
|
-
</Column>
|
|
149
|
+
const [activeTab, setActiveTab] = useState("details");
|
|
150
|
+
|
|
151
|
+
<Tabs
|
|
152
|
+
aria-controls="content-panel"
|
|
153
|
+
tabs={[
|
|
154
|
+
{
|
|
155
|
+
selected: activeTab === "details",
|
|
156
|
+
label: "Details",
|
|
157
|
+
onClick: () => setActiveTab("details"),
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
selected: activeTab === "reviews",
|
|
161
|
+
label: "Reviews",
|
|
162
|
+
onClick: () => setActiveTab("reviews"),
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
selected: activeTab === "related",
|
|
166
|
+
label: "Related",
|
|
167
|
+
onClick: () => setActiveTab("related"),
|
|
168
|
+
},
|
|
169
|
+
]}
|
|
170
|
+
/>
|
|
312
171
|
```
|
|
313
172
|
|
|
314
|
-
|
|
173
|
+
---
|
|
315
174
|
|
|
316
|
-
|
|
175
|
+
## Custom label rendering
|
|
176
|
+
|
|
177
|
+
Use `labelRenderer` to customize how tab labels are displayed:
|
|
317
178
|
|
|
318
179
|
<Column>
|
|
319
180
|
<Tabs
|
|
320
|
-
aria-controls="
|
|
181
|
+
aria-controls="panel-5"
|
|
321
182
|
labelRenderer={(value) => value.split(" ").map((word, index) => index % 2 === 0 ? <strong key={index}>{word} </strong> : word + " ")}
|
|
322
183
|
tabs={[
|
|
323
|
-
{
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
label: "Bold Tab 1",
|
|
327
|
-
},
|
|
328
|
-
{
|
|
329
|
-
href: "/Tabs",
|
|
330
|
-
selected: false,
|
|
331
|
-
label: "Bold Tab 2",
|
|
332
|
-
},
|
|
333
|
-
{
|
|
334
|
-
href: "/Tabs",
|
|
335
|
-
selected: false,
|
|
336
|
-
label: "Bold Tab 3",
|
|
337
|
-
},
|
|
184
|
+
{ href: "/Tabs", selected: true, label: "Bold Tab 1" },
|
|
185
|
+
{ href: "/Tabs", selected: false, label: "Bold Tab 2" },
|
|
186
|
+
{ href: "/Tabs", selected: false, label: "Bold Tab 3" },
|
|
338
187
|
]}
|
|
339
188
|
/>
|
|
340
189
|
</Column>
|
|
341
190
|
|
|
342
191
|
```js
|
|
343
|
-
<
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
{
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
label: "Bold Tab 2",
|
|
357
|
-
},
|
|
358
|
-
{
|
|
359
|
-
href: "/Tabs",
|
|
360
|
-
selected: false,
|
|
361
|
-
label: "Bold Tab 3",
|
|
362
|
-
},
|
|
363
|
-
]}
|
|
364
|
-
/>
|
|
365
|
-
</Column>
|
|
192
|
+
<Tabs
|
|
193
|
+
aria-controls="panel"
|
|
194
|
+
labelRenderer={(label) => (
|
|
195
|
+
<>
|
|
196
|
+
<Icon icon="fa-star" size="small" />
|
|
197
|
+
{label}
|
|
198
|
+
</>
|
|
199
|
+
)}
|
|
200
|
+
tabs={[
|
|
201
|
+
{ href: "/featured", selected: true, label: "Featured" },
|
|
202
|
+
{ href: "/popular", selected: false, label: "Popular" },
|
|
203
|
+
]}
|
|
204
|
+
/>
|
|
366
205
|
```
|
|
367
206
|
|
|
207
|
+
---
|
|
368
208
|
|
|
369
209
|
## Custom tab styles
|
|
370
210
|
|
|
371
|
-
|
|
211
|
+
Use `jssTab` for custom styling. It can be a static style object or a function that receives the tab's selected state:
|
|
372
212
|
|
|
373
213
|
<Column>
|
|
374
214
|
<Tabs
|
|
375
|
-
aria-controls="
|
|
376
|
-
|
|
215
|
+
aria-controls="panel-6"
|
|
216
|
+
jssTab={(data) => ({
|
|
377
217
|
borderBottom: data.selected ? "2px solid cyan" : "2px solid magenta",
|
|
378
218
|
})}
|
|
379
219
|
tabs={[
|
|
380
|
-
{
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
label: "Styled Tab 1",
|
|
384
|
-
},
|
|
385
|
-
{
|
|
386
|
-
href: "/Tabs",
|
|
387
|
-
selected: false,
|
|
388
|
-
label: "Styled Tab 2",
|
|
389
|
-
},
|
|
390
|
-
{
|
|
391
|
-
href: "/Tabs",
|
|
392
|
-
selected: false,
|
|
393
|
-
label: "Styled Tab 3",
|
|
394
|
-
},
|
|
220
|
+
{ href: "/Tabs", selected: true, label: "Styled Tab 1" },
|
|
221
|
+
{ href: "/Tabs", selected: false, label: "Styled Tab 2" },
|
|
222
|
+
{ href: "/Tabs", selected: false, label: "Styled Tab 3" },
|
|
395
223
|
]}
|
|
396
224
|
/>
|
|
397
225
|
</Column>
|
|
398
226
|
|
|
399
227
|
```js
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
228
|
+
// Conditional styling based on selection
|
|
229
|
+
<Tabs
|
|
230
|
+
aria-controls="panel"
|
|
231
|
+
jssTab={(data) => ({
|
|
232
|
+
borderBottom: data.selected
|
|
233
|
+
? "3px solid var(--highlight)"
|
|
234
|
+
: "3px solid transparent",
|
|
235
|
+
backgroundColor: data.selected
|
|
236
|
+
? "var(--light-highlight)"
|
|
237
|
+
: "transparent",
|
|
238
|
+
})}
|
|
239
|
+
tabs={tabs}
|
|
240
|
+
/>
|
|
241
|
+
|
|
242
|
+
// Static styling for all tabs
|
|
243
|
+
<Tabs
|
|
244
|
+
aria-controls="panel"
|
|
245
|
+
jssTab={{ borderRadius: 8 }}
|
|
246
|
+
tabs={tabs}
|
|
247
|
+
/>
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Keyboard navigation
|
|
253
|
+
|
|
254
|
+
Tabs support full keyboard navigation:
|
|
255
|
+
|
|
256
|
+
- **Arrow Left/Right**: Move focus between tabs
|
|
257
|
+
- **Enter/Space**: Activate the focused tab
|
|
258
|
+
- **Home**: Move to first tab
|
|
259
|
+
- **End**: Move to last tab
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Accessibility
|
|
264
|
+
|
|
265
|
+
The Tabs component follows WAI-ARIA tab patterns:
|
|
266
|
+
|
|
267
|
+
- Container has `role="tablist"`
|
|
268
|
+
- Each tab has `role="tab"` and `aria-controls` pointing to its panel
|
|
269
|
+
- Selected tab has `aria-selected="true"`
|
|
270
|
+
- Content panel should have `role="tabpanel"` and matching `id`
|
|
271
|
+
|
|
272
|
+
```js
|
|
273
|
+
<Tabs
|
|
274
|
+
aria-controls="settings-panel"
|
|
275
|
+
tabs={tabs}
|
|
276
|
+
/>
|
|
277
|
+
|
|
278
|
+
<div id="settings-panel" role="tabpanel">
|
|
279
|
+
{/* Panel content */}
|
|
280
|
+
</div>
|
|
281
|
+
```
|