@redis-ui/components 43.0.2 → 43.2.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/dist/HighlightedIcon/HighlightedIcon.cjs +26 -0
- package/dist/HighlightedIcon/HighlightedIcon.d.ts +3 -0
- package/dist/HighlightedIcon/HighlightedIcon.js +26 -0
- package/dist/HighlightedIcon/HighlightedIcon.style.cjs +49 -0
- package/dist/HighlightedIcon/HighlightedIcon.style.d.ts +5 -0
- package/dist/HighlightedIcon/HighlightedIcon.style.js +47 -0
- package/dist/HighlightedIcon/HighlightedIcon.types.d.ts +8 -0
- package/dist/HighlightedIcon/index.d.ts +3 -0
- package/dist/Stepper/Stepper.cjs +14 -5
- package/dist/Stepper/Stepper.d.ts +2 -0
- package/dist/Stepper/Stepper.js +14 -5
- package/dist/Stepper/Stepper.utils.cjs +12 -0
- package/dist/Stepper/Stepper.utils.d.ts +2 -0
- package/dist/Stepper/Stepper.utils.js +12 -0
- package/dist/Stepper/components/Compose/Compose.d.ts +1 -0
- package/dist/Stepper/components/Step/Step.cjs +2 -0
- package/dist/Stepper/components/Step/Step.d.ts +1 -0
- package/dist/Stepper/components/Step/Step.js +2 -0
- package/dist/Stepper/components/Step/components/Compose/Compose.cjs +2 -9
- package/dist/Stepper/components/Step/components/Compose/Compose.js +2 -9
- package/dist/Stepper/components/Step/components/Separator/Separator.cjs +15 -0
- package/dist/Stepper/components/Step/components/Separator/Separator.d.ts +3 -0
- package/dist/Stepper/components/Step/components/Separator/Separator.js +15 -0
- package/dist/Stepper/components/Step/components/Separator/Separator.style.cjs +24 -0
- package/dist/Stepper/components/Step/components/Separator/Separator.style.d.ts +1 -0
- package/dist/Stepper/components/Step/components/Separator/Separator.style.js +22 -0
- package/dist/Stepper/components/Step/components/Separator/Separator.types.d.ts +5 -0
- package/dist/index.cjs +4 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +74 -70
- package/package.json +2 -2
- package/skills/redis-ui-components/SKILL.md +0 -2
- package/skills/redis-ui-components/references/ActionIconButton.md +96 -0
- package/skills/redis-ui-components/references/AppBar.md +161 -0
- package/skills/redis-ui-components/references/AppSelectionMenu.md +184 -0
- package/skills/redis-ui-components/references/AutoCompleteSelect.md +193 -0
- package/skills/redis-ui-components/references/Badge.md +77 -0
- package/skills/redis-ui-components/references/Banner.md +563 -0
- package/skills/redis-ui-components/references/BoxSelectionGroup.md +487 -0
- package/skills/redis-ui-components/references/Breadcrumbs.md +214 -0
- package/skills/redis-ui-components/references/ButtonGroup.md +126 -0
- package/skills/redis-ui-components/references/Card.md +56 -0
- package/skills/redis-ui-components/references/Checkbox.md +171 -0
- package/skills/redis-ui-components/references/Chip.md +154 -0
- package/skills/redis-ui-components/references/ChipList.md +307 -0
- package/skills/redis-ui-components/references/CopyToClipboardButton.md +47 -0
- package/skills/redis-ui-components/references/CountryFlag.md +57 -0
- package/skills/redis-ui-components/references/Drawer.md +298 -0
- package/skills/redis-ui-components/references/Filters.md +162 -0
- package/skills/redis-ui-components/references/FormField.md +678 -0
- package/skills/redis-ui-components/references/IconButton.md +63 -0
- package/skills/redis-ui-components/references/Input.md +295 -0
- package/skills/redis-ui-components/references/KeyValueList.md +501 -0
- package/skills/redis-ui-components/references/Label.md +238 -0
- package/skills/redis-ui-components/references/Link.md +402 -0
- package/skills/redis-ui-components/references/Loader.md +100 -0
- package/skills/redis-ui-components/references/Menu.md +988 -0
- package/skills/redis-ui-components/references/MidBar.md +358 -0
- package/skills/redis-ui-components/references/Modal.md +525 -0
- package/skills/redis-ui-components/references/MoreInfoIcon.md +119 -0
- package/skills/redis-ui-components/references/MultiSelect.md +558 -0
- package/skills/redis-ui-components/references/NumericInput.md +322 -0
- package/skills/redis-ui-components/references/Overflow.md +127 -0
- package/skills/redis-ui-components/references/Pagination.md +151 -0
- package/skills/redis-ui-components/references/PasswordInput.md +262 -0
- package/skills/redis-ui-components/references/Popover.md +868 -0
- package/skills/redis-ui-components/references/ProfileIcon.md +65 -0
- package/skills/redis-ui-components/references/ProgressBar.md +103 -0
- package/skills/redis-ui-components/references/QuantityCounter.md +555 -0
- package/skills/redis-ui-components/references/RadioGroup.md +265 -0
- package/skills/redis-ui-components/references/ScreenReaderAnnounce.md +147 -0
- package/skills/redis-ui-components/references/SearchBar.md +242 -0
- package/skills/redis-ui-components/references/SearchInput.md +213 -0
- package/skills/redis-ui-components/references/Section.md +349 -0
- package/skills/redis-ui-components/references/SideBar.md +468 -0
- package/skills/redis-ui-components/references/Slider.md +398 -0
- package/skills/redis-ui-components/references/Stepper.md +288 -0
- package/skills/redis-ui-components/references/Switch.md +193 -0
- package/skills/redis-ui-components/references/Tabs.md +383 -0
- package/skills/redis-ui-components/references/TextArea.md +139 -0
- package/skills/redis-ui-components/references/TextButton.md +217 -0
- package/skills/redis-ui-components/references/Toast.md +399 -0
- package/skills/redis-ui-components/references/ToggleButton.md +163 -0
- package/skills/redis-ui-components/references/Tooltip.md +636 -0
- package/skills/redis-ui-components/references/Typography.md +323 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# Switch
|
|
2
|
+
|
|
3
|
+
A boolean switch component with controlled and uncontrolled state, disabled/read-only behavior, and a composition API for custom switcher and title layouts.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Switch } from '@redislabsdev/redis-ui-components';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
|------|------|---------|-------------|
|
|
15
|
+
| `checked` | `boolean` | - | Controlled checked state. |
|
|
16
|
+
| `defaultChecked` | `boolean` | `false` | Uncontrolled initial checked state. |
|
|
17
|
+
| `disabled` | `boolean` | `false` | Disables interaction and propagates to the switcher. |
|
|
18
|
+
| `readOnly` | `boolean` | `false` | Renders the switch as read-only while preserving its value. |
|
|
19
|
+
| `onCheckedChange` | `(checked: boolean) => void` | - | Called when the checked state changes. |
|
|
20
|
+
| `titleOn` | `ReactNode` | - | Content shown when the switch is checked. |
|
|
21
|
+
| `titleOff` | `ReactNode` | - | Content shown when the switch is unchecked. |
|
|
22
|
+
| `className` | `string` | - | Applied to the composed root element. |
|
|
23
|
+
| `style` | `CSSProperties` | - | Applied to the composed root element. |
|
|
24
|
+
| `id` | `string` | - | Shared id used for label association with the switcher. |
|
|
25
|
+
| `other button attributes` | `HTMLAttributes<HTMLButtonElement>` | - | Any other button attributes are forwarded to `Switch.Switcher`. |
|
|
26
|
+
|
|
27
|
+
The component also accepts the rest of `HTMLAttributes<HTMLButtonElement>`, which are merged onto the switcher part.
|
|
28
|
+
|
|
29
|
+
## Sub-components
|
|
30
|
+
|
|
31
|
+
- `Switch.Compose` - Composition root that provides checked state and field context.
|
|
32
|
+
- `Switch.Switcher` - Interactive switch button/track rendered inside the composition.
|
|
33
|
+
- `Switch.Switcher.Compose` - Low-level switcher root used for advanced custom layouts.
|
|
34
|
+
- `Switch.Switcher.Knob` - Thumb element rendered inside the switcher.
|
|
35
|
+
- `Switch.Title` - Text label that reflects the current checked state.
|
|
36
|
+
|
|
37
|
+
### Switch.Compose Props
|
|
38
|
+
|
|
39
|
+
| Prop | Type | Default | Description |
|
|
40
|
+
|------|------|---------|-------------|
|
|
41
|
+
| `disabled` | `boolean` | `false` | Disables interaction for the composed switch. |
|
|
42
|
+
| `readOnly` | `boolean` | `false` | Marks the composed switch as read-only. |
|
|
43
|
+
| `checked` | `boolean` | - | Controlled checked state. |
|
|
44
|
+
| `defaultChecked` | `boolean` | `false` | Uncontrolled initial checked state. |
|
|
45
|
+
| `onCheckedChange` | `(checked: boolean) => void` | - | Called when the checked state changes. |
|
|
46
|
+
| `children` | `ReactNode` | - | Composed switch parts, typically `Switch.Switcher` and `Switch.Title`. |
|
|
47
|
+
|
|
48
|
+
`Switch.Compose` also accepts the standard `ComposeElementProps<HTMLElement>` props, including `className`, `style`, `data-*` attributes, and event handlers.
|
|
49
|
+
|
|
50
|
+
### Switch.Switcher Props
|
|
51
|
+
|
|
52
|
+
| Prop | Type | Default | Description |
|
|
53
|
+
|------|------|---------|-------------|
|
|
54
|
+
| `id` | `string` | - | Shared id for label association and test targeting. |
|
|
55
|
+
| `other button attributes` | `HTMLAttributes<HTMLButtonElement>` | - | Remaining button props are merged onto the switcher element. |
|
|
56
|
+
|
|
57
|
+
`Switch.Switcher` accepts the rest of `HTMLAttributes<HTMLButtonElement>` and combines its own pointer, keyboard, and mouse handlers with any handlers passed in.
|
|
58
|
+
|
|
59
|
+
### Switch.Title Props
|
|
60
|
+
|
|
61
|
+
| Prop | Type | Default | Description |
|
|
62
|
+
|------|------|---------|-------------|
|
|
63
|
+
| `titleOn` | `ReactNode` | - | Content shown when the switch is checked. |
|
|
64
|
+
| `titleOff` | `ReactNode` | - | Content shown when the switch is unchecked. |
|
|
65
|
+
|
|
66
|
+
`Switch.Title` also extends `ChildFree<TypographyBodyProps>`, so typography body props can be passed through without `children`.
|
|
67
|
+
|
|
68
|
+
## Examples
|
|
69
|
+
|
|
70
|
+
### Playground
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
import { Switch } from '@redislabsdev/redis-ui-components';
|
|
74
|
+
|
|
75
|
+
<Switch {...args} checked={checked} onCheckedChange={handleClickSwitch} />
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Disabled
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
import { Switch } from '@redislabsdev/redis-ui-components';
|
|
82
|
+
|
|
83
|
+
<>
|
|
84
|
+
{[false, true].map((checked) => (
|
|
85
|
+
<Switch
|
|
86
|
+
key={`${checked}`}
|
|
87
|
+
disabled
|
|
88
|
+
defaultChecked={checked}
|
|
89
|
+
titleOn="titleOn"
|
|
90
|
+
titleOff="titleOff"
|
|
91
|
+
/>
|
|
92
|
+
))}
|
|
93
|
+
</>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Readonly
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
import { Switch } from '@redislabsdev/redis-ui-components';
|
|
100
|
+
|
|
101
|
+
<>
|
|
102
|
+
{[false, true].map((checked) => (
|
|
103
|
+
<Switch
|
|
104
|
+
key={`${checked}`}
|
|
105
|
+
readOnly
|
|
106
|
+
defaultChecked={checked}
|
|
107
|
+
titleOn="titleOn"
|
|
108
|
+
titleOff="titleOff"
|
|
109
|
+
/>
|
|
110
|
+
))}
|
|
111
|
+
</>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### WithinFormField
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
import { FormField, Switch } from '@redislabsdev/redis-ui-components';
|
|
118
|
+
|
|
119
|
+
<>
|
|
120
|
+
<FormField label="Normal" additionalText="Switch in FormField">
|
|
121
|
+
<Switch checked={state} titleOn="titleOn" titleOff="titleOff" onCheckedChange={setState} />
|
|
122
|
+
</FormField>
|
|
123
|
+
<FormField label="Readonly" additionalText="Switch in FormField">
|
|
124
|
+
<Switch
|
|
125
|
+
checked={state}
|
|
126
|
+
readOnly
|
|
127
|
+
titleOn="titleOn"
|
|
128
|
+
titleOff="titleOff"
|
|
129
|
+
onCheckedChange={setState}
|
|
130
|
+
/>
|
|
131
|
+
</FormField>
|
|
132
|
+
<FormField label="Disabled" additionalText="Switch in FormField">
|
|
133
|
+
<Switch
|
|
134
|
+
checked={state}
|
|
135
|
+
disabled
|
|
136
|
+
titleOn="titleOn"
|
|
137
|
+
titleOff="titleOff"
|
|
138
|
+
onCheckedChange={setState}
|
|
139
|
+
/>
|
|
140
|
+
</FormField>
|
|
141
|
+
</>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### BasicComposition
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
import { Switch } from '@redislabsdev/redis-ui-components';
|
|
148
|
+
|
|
149
|
+
<Switch.Compose checked={state} onCheckedChange={setState}>
|
|
150
|
+
<Switch.Switcher />
|
|
151
|
+
<Switch.Title titleOn="On" titleOff="Off" />
|
|
152
|
+
</Switch.Compose>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### BothSideText
|
|
156
|
+
|
|
157
|
+
```tsx
|
|
158
|
+
import { Switch } from '@redislabsdev/redis-ui-components';
|
|
159
|
+
|
|
160
|
+
<Switch.Compose checked={state} onCheckedChange={setState}>
|
|
161
|
+
<Switch.Title titleOn="On" titleOff="Off" />
|
|
162
|
+
<Switch.Switcher />
|
|
163
|
+
<Switch.Title titleOn="Off" titleOff="On" />
|
|
164
|
+
</Switch.Compose>
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### StyledComposition
|
|
168
|
+
|
|
169
|
+
> Custom styling can be added to all components in a composition.
|
|
170
|
+
> Styles can be state-consistent.
|
|
171
|
+
|
|
172
|
+
```tsx
|
|
173
|
+
import { FormField, Switch } from '@redislabsdev/redis-ui-components';
|
|
174
|
+
import * as S from './SwitchStory.style';
|
|
175
|
+
|
|
176
|
+
<FormField label={<S.CustomTitle checked={state}>Fancy Switch</S.CustomTitle>}>
|
|
177
|
+
<Switch.Compose checked={state}>
|
|
178
|
+
<S.CustomSwitcherCompose data-testid="switcher" checked={state} onCheckedChange={setState}>
|
|
179
|
+
<S.CustomKnob $on={state} />
|
|
180
|
+
</S.CustomSwitcherCompose>
|
|
181
|
+
<S.CustomText checked={state} titleOn="On" titleOff="Off" />
|
|
182
|
+
</Switch.Compose>
|
|
183
|
+
</FormField>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Notes
|
|
187
|
+
|
|
188
|
+
- `titleOn` and `titleOff` accept any `ReactNode`, not just strings.
|
|
189
|
+
- `Switch.Title` only renders when at least one of `titleOn` or `titleOff` is provided.
|
|
190
|
+
- When used without composition, all HTML button attributes other than `className` and `style` are redirected to the switcher part.
|
|
191
|
+
- The switcher root exposes `data-role="switch-root"` and the title exposes `data-role="switch-title"`.
|
|
192
|
+
- In tests, locate the interactive element by its `role="switch"`, use `userEvent.click` to toggle it, and assert disabled/read-only state on the switcher.
|
|
193
|
+
- `Switch.Switcher.Compose` and `Switch.Switcher.Knob` are intended for advanced custom styling and layout.
|
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
# Tabs
|
|
2
|
+
|
|
3
|
+
Tabs renders a tab bar and matching content panes from a shared tab list. It supports controlled and uncontrolled state, keyboard activation behavior, variant styling, and a compound composition API for fully custom layouts.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Tabs } from '@redislabsdev/redis-ui-components';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
|------|------|---------|-------------|
|
|
15
|
+
| tabs | `TTab[]` | required | Tabs to render. Each item combines trigger and content data. |
|
|
16
|
+
| defaultValue | `NoInfer<TValue>` | - | Initial active tab when using uncontrolled state. |
|
|
17
|
+
| value | `NoInfer<TValue>` | - | Controlled active tab value. |
|
|
18
|
+
| onChange | `(newValue: TValue) => void` | - | Called when the active tab changes. |
|
|
19
|
+
| activateOnFocus | `boolean` | `false` | Activates a tab as soon as it receives focus instead of waiting for Enter or Space. |
|
|
20
|
+
| variant | `'default' \| 'sub'` | `'default'` | Tab bar styling variant. |
|
|
21
|
+
|
|
22
|
+
The root `Tabs` component also accepts native compose element props, excluding `children` and `dir`.
|
|
23
|
+
|
|
24
|
+
### Related Types
|
|
25
|
+
|
|
26
|
+
- `TabInfo<TValue = string>` - Combined trigger and content data for a single tab.
|
|
27
|
+
- `TabTriggerInfo<TValue = string>` - Trigger metadata with `value`, optional `label`, and optional `disabled`.
|
|
28
|
+
- `TabContentInfo<TValue = string>` - Content metadata with `value` and `content`.
|
|
29
|
+
- `TabsVariant` - `'default' | 'sub'`.
|
|
30
|
+
|
|
31
|
+
## Sub-components
|
|
32
|
+
|
|
33
|
+
- `Tabs.Compose` - Shared state wrapper for fully custom tab layouts.
|
|
34
|
+
- `Tabs.TabBar` - Default tab trigger renderer built from a `tabs` array.
|
|
35
|
+
- `Tabs.TabBar.Compose` - Composition wrapper for custom trigger layouts.
|
|
36
|
+
- `Tabs.TabBar.Trigger` - Default trigger renderer for a single tab.
|
|
37
|
+
- `Tabs.TabBar.Trigger.Compose` - Radix trigger wrapper for custom trigger content.
|
|
38
|
+
- `Tabs.TabBar.Trigger.Tab` - Tab label container; string children are wrapped in `Typography.Body`.
|
|
39
|
+
- `Tabs.TabBar.Trigger.Marker` - Active, hover, focus, and disabled indicator rendered inside a trigger.
|
|
40
|
+
- `Tabs.ContentPane` - Default content renderer built from a `tabs` array.
|
|
41
|
+
- `Tabs.ContentPane.Compose` - Composition wrapper for custom content layouts.
|
|
42
|
+
- `Tabs.ContentPane.Content` - Individual content panel linked by `value`.
|
|
43
|
+
|
|
44
|
+
### Tabs.Compose Props
|
|
45
|
+
|
|
46
|
+
| Prop | Type | Default | Description |
|
|
47
|
+
|------|------|---------|-------------|
|
|
48
|
+
| defaultValue | `NoInfer<TValue>` | - | Initial active tab when using uncontrolled state. |
|
|
49
|
+
| value | `NoInfer<TValue>` | - | Controlled active tab value. |
|
|
50
|
+
| onChange | `(newValue: TValue) => void` | - | Called when the active tab changes. |
|
|
51
|
+
| activateOnFocus | `boolean` | `false` | Activates a tab as soon as it receives focus instead of waiting for Enter or Space. |
|
|
52
|
+
| children | `React.ReactNode` | required | Custom tab bar and content pane layout. |
|
|
53
|
+
|
|
54
|
+
Tabs.Compose also accepts native compose element props, excluding `dir`.
|
|
55
|
+
|
|
56
|
+
### Tabs.TabBar Props
|
|
57
|
+
|
|
58
|
+
| Prop | Type | Default | Description |
|
|
59
|
+
|------|------|---------|-------------|
|
|
60
|
+
| tabs | `TabTriggerInfo[]` | required | Tabs to render in the bar. |
|
|
61
|
+
| variant | `TabsVariant` | `'default'` | Tab bar styling variant. |
|
|
62
|
+
|
|
63
|
+
Tabs.TabBar also accepts native compose element props, excluding `children`.
|
|
64
|
+
|
|
65
|
+
### Tabs.TabBar.Compose Props
|
|
66
|
+
|
|
67
|
+
| Prop | Type | Default | Description |
|
|
68
|
+
|------|------|---------|-------------|
|
|
69
|
+
| variant | `TabsVariant` | `'default'` | Tab bar styling variant. |
|
|
70
|
+
| children | `React.ReactNode` | required | Custom trigger elements. |
|
|
71
|
+
|
|
72
|
+
Tabs.TabBar.Compose also accepts native compose element props.
|
|
73
|
+
|
|
74
|
+
### Tabs.TabBar.Trigger Props
|
|
75
|
+
|
|
76
|
+
| Prop | Type | Default | Description |
|
|
77
|
+
|------|------|---------|-------------|
|
|
78
|
+
| value | `string` | required | Active value for the trigger. |
|
|
79
|
+
| disabled | `boolean` | `false` | Disables the trigger. |
|
|
80
|
+
| children | `React.ReactNode` | required | Trigger label or custom trigger content. |
|
|
81
|
+
|
|
82
|
+
Tabs.TabBar.Trigger also accepts the same native button compose props as `Tabs.TabBar.Trigger.Compose`.
|
|
83
|
+
|
|
84
|
+
### Tabs.TabBar.Trigger.Compose Props
|
|
85
|
+
|
|
86
|
+
| Prop | Type | Default | Description |
|
|
87
|
+
|------|------|---------|-------------|
|
|
88
|
+
| value | `string` | required | Active value for the trigger. |
|
|
89
|
+
| disabled | `boolean` | `false` | Disables the trigger. |
|
|
90
|
+
| children | `React.ReactNode` | required | Custom trigger content. |
|
|
91
|
+
|
|
92
|
+
Tabs.TabBar.Trigger.Compose also accepts native button compose props.
|
|
93
|
+
|
|
94
|
+
### Tabs.TabBar.Trigger.Tab Props
|
|
95
|
+
|
|
96
|
+
| Prop | Type | Default | Description |
|
|
97
|
+
|------|------|---------|-------------|
|
|
98
|
+
| children | `React.ReactNode` | required | Tab label content. |
|
|
99
|
+
|
|
100
|
+
Tabs.TabBar.Trigger.Tab also accepts native compose element props.
|
|
101
|
+
|
|
102
|
+
### Tabs.TabBar.Trigger.Marker Props
|
|
103
|
+
|
|
104
|
+
Tabs.TabBar.Trigger.Marker does not define custom props. It accepts native `HTMLAttributes<HTMLDivElement>` without `children`.
|
|
105
|
+
|
|
106
|
+
### Tabs.ContentPane Props
|
|
107
|
+
|
|
108
|
+
| Prop | Type | Default | Description |
|
|
109
|
+
|------|------|---------|-------------|
|
|
110
|
+
| tabs | `TabContentInfo[]` | required | Tab content panels to render. |
|
|
111
|
+
|
|
112
|
+
Tabs.ContentPane also accepts native compose element props, excluding `children`.
|
|
113
|
+
|
|
114
|
+
### Tabs.ContentPane.Compose Props
|
|
115
|
+
|
|
116
|
+
| Prop | Type | Default | Description |
|
|
117
|
+
|------|------|---------|-------------|
|
|
118
|
+
| children | `React.ReactNode` | required | Custom content panel layout. |
|
|
119
|
+
|
|
120
|
+
Tabs.ContentPane.Compose also accepts native compose element props.
|
|
121
|
+
|
|
122
|
+
### Tabs.ContentPane.Content Props
|
|
123
|
+
|
|
124
|
+
| Prop | Type | Default | Description |
|
|
125
|
+
|------|------|---------|-------------|
|
|
126
|
+
| value | `string` | required | Value that links the panel to a tab trigger. |
|
|
127
|
+
| children | `React.ReactNode` | required | Panel content. |
|
|
128
|
+
|
|
129
|
+
Tabs.ContentPane.Content also accepts native content compose props.
|
|
130
|
+
|
|
131
|
+
## Examples
|
|
132
|
+
|
|
133
|
+
### Basic Usage
|
|
134
|
+
|
|
135
|
+
> Playground story
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
import { Tabs } from '@redislabsdev/redis-ui-components';
|
|
139
|
+
|
|
140
|
+
const tabs = [
|
|
141
|
+
{ value: 'tab1', label: 'First Tab', content: 'First Tab Content' },
|
|
142
|
+
{ value: 'tab2', label: 'Second Tab', content: 'Second Tab Content' },
|
|
143
|
+
{ value: 'tab3', label: 'Third Tab (disabled)', content: 'Third Tab Content', disabled: true }
|
|
144
|
+
];
|
|
145
|
+
|
|
146
|
+
<Tabs tabs={tabs} defaultValue={tabs[0].value} />
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### ControlledMode
|
|
150
|
+
|
|
151
|
+
> Set `value` and `onChange` props to use controlled mode
|
|
152
|
+
|
|
153
|
+
```tsx
|
|
154
|
+
import { useState } from 'react';
|
|
155
|
+
import { Tabs } from '@redislabsdev/redis-ui-components';
|
|
156
|
+
|
|
157
|
+
const tabs = [
|
|
158
|
+
{ value: 'tab1', label: 'First Tab', content: 'First Tab Content' },
|
|
159
|
+
{ value: 'tab2', label: 'Second Tab', content: 'Second Tab Content' },
|
|
160
|
+
{ value: 'tab3', label: 'Third Tab (disabled)', content: 'Third Tab Content', disabled: true }
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
function Example() {
|
|
164
|
+
const [selectedTab, setSelectedTab] = useState(tabs[0].value);
|
|
165
|
+
|
|
166
|
+
return <Tabs tabs={tabs} value={selectedTab} onChange={setSelectedTab} />;
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Variants
|
|
171
|
+
|
|
172
|
+
> 2 variants are supported, `default` and `sub`. Use `variant` prop to set it.
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
import { Tabs } from '@redislabsdev/redis-ui-components';
|
|
176
|
+
|
|
177
|
+
const tabs = [
|
|
178
|
+
{ value: 'tab1', label: 'First Tab', content: 'First Tab Content' },
|
|
179
|
+
{ value: 'tab2', label: 'Second Tab', content: 'Second Tab Content' },
|
|
180
|
+
{ value: 'tab3', label: 'Third Tab (disabled)', content: 'Third Tab Content', disabled: true }
|
|
181
|
+
];
|
|
182
|
+
|
|
183
|
+
<>
|
|
184
|
+
<Tabs tabs={tabs} defaultValue={tabs[0].value} />
|
|
185
|
+
<Tabs tabs={tabs} defaultValue={tabs[0].value} variant="sub" />
|
|
186
|
+
</>
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### ActivateTabOnFocus
|
|
190
|
+
|
|
191
|
+
> When navigating between tabs using the keyboard, the tab will only be focused by the arrow keys, but activated when Enter or Space is pressed.
|
|
192
|
+
> To change this behavior, set the `activateOnFocus` prop to true, and the tab will be activated by the arrow keys.
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
import { Tabs } from '@redislabsdev/redis-ui-components';
|
|
196
|
+
|
|
197
|
+
const tabs = [
|
|
198
|
+
{ value: 'tab1', label: 'First Tab', content: 'First Tab Content' },
|
|
199
|
+
{ value: 'tab2', label: 'Second Tab', content: 'Second Tab Content' },
|
|
200
|
+
{ value: 'tab3', label: 'Third Tab (disabled)', content: 'Third Tab Content', disabled: true }
|
|
201
|
+
];
|
|
202
|
+
|
|
203
|
+
<Tabs tabs={tabs} defaultValue={tabs[0].value} activateOnFocus />
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### HeaderAndContent
|
|
207
|
+
|
|
208
|
+
> Tabs component can be shallow composed using 2 main parts:
|
|
209
|
+
> - `Tabs.TabBar` for rendering header
|
|
210
|
+
> - `Tabs.ContentPane` for rendering content
|
|
211
|
+
>
|
|
212
|
+
> Each part receives tabs list as `tabs` prop.
|
|
213
|
+
> Same tabs list can be used for both parts and for `Tabs` component
|
|
214
|
+
>
|
|
215
|
+
> State management props should be passed to `Tabs.Compose`
|
|
216
|
+
>
|
|
217
|
+
> All parts can have custom styling
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
import { Tabs } from '@redislabsdev/redis-ui-components';
|
|
221
|
+
import styled from 'styled-components';
|
|
222
|
+
import { useTheme } from '@redislabsdev/redis-ui-styles';
|
|
223
|
+
|
|
224
|
+
const tabs = [
|
|
225
|
+
{ value: 'tab1', label: 'First Tab', content: 'First Tab Content' },
|
|
226
|
+
{ value: 'tab2', label: 'Second Tab', content: 'Second Tab Content' },
|
|
227
|
+
{ value: 'tab3', label: 'Third Tab (disabled)', content: 'Third Tab Content', disabled: true }
|
|
228
|
+
];
|
|
229
|
+
|
|
230
|
+
function Example() {
|
|
231
|
+
return (
|
|
232
|
+
<Tabs.Compose defaultValue={tabs[1].value}>
|
|
233
|
+
<Tabs.TabBar
|
|
234
|
+
tabs={tabs}
|
|
235
|
+
style={{ background: useTheme().semantic.color.background.notice100 }}
|
|
236
|
+
/>
|
|
237
|
+
<Tabs.ContentPane
|
|
238
|
+
tabs={tabs}
|
|
239
|
+
style={{ background: useTheme().semantic.color.background.success100 }}
|
|
240
|
+
/>
|
|
241
|
+
</Tabs.Compose>
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### TabBarOnly
|
|
247
|
+
|
|
248
|
+
> Tabs component can be used without `Tabs.ContentPane`.
|
|
249
|
+
> e.g. when using tabs with router, router Switch can be used instead of tab content (controlled mode is required to manage tabs state)
|
|
250
|
+
|
|
251
|
+
```tsx
|
|
252
|
+
import { useState } from 'react';
|
|
253
|
+
import { Tabs } from '@redislabsdev/redis-ui-components';
|
|
254
|
+
|
|
255
|
+
const tabs = [
|
|
256
|
+
{ value: 'tab1', label: 'First Tab', content: 'First Tab Content' },
|
|
257
|
+
{ value: 'tab2', label: 'Second Tab', content: 'Second Tab Content' },
|
|
258
|
+
{ value: 'tab3', label: 'Third Tab (disabled)', content: 'Third Tab Content', disabled: true }
|
|
259
|
+
];
|
|
260
|
+
|
|
261
|
+
function Example() {
|
|
262
|
+
const [selectedTab, setSelectedTab] = useState(tabs[0].value);
|
|
263
|
+
|
|
264
|
+
return (
|
|
265
|
+
<Tabs.Compose value={selectedTab} onChange={setSelectedTab}>
|
|
266
|
+
<Tabs.TabBar tabs={tabs} />
|
|
267
|
+
</Tabs.Compose>
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### HeaderComposition
|
|
273
|
+
|
|
274
|
+
> The `Tabs.TabBar` can be composed and all parts can be customized including the tab trigger content and marker
|
|
275
|
+
>
|
|
276
|
+
> Styled components should be defined outside the render function.
|
|
277
|
+
|
|
278
|
+
```tsx
|
|
279
|
+
import { Tabs } from '@redislabsdev/redis-ui-components';
|
|
280
|
+
import styled from 'styled-components';
|
|
281
|
+
import { useTheme } from '@redislabsdev/redis-ui-styles';
|
|
282
|
+
|
|
283
|
+
const tabs = [
|
|
284
|
+
{ value: 'tab1', label: 'First Tab', content: 'First Tab Content' },
|
|
285
|
+
{ value: 'tab2', label: 'Second Tab', content: 'Second Tab Content' },
|
|
286
|
+
{ value: 'tab3', label: 'Third Tab (disabled)', content: 'Third Tab Content', disabled: true }
|
|
287
|
+
];
|
|
288
|
+
|
|
289
|
+
const CustomTabsTabBarTriggerCompose = styled(Tabs.TabBar.Trigger.Compose)``;
|
|
290
|
+
|
|
291
|
+
const CustomTabsTriggerContent = styled(Tabs.TabBar.Trigger.Tab)`
|
|
292
|
+
&& {
|
|
293
|
+
padding: 5px;
|
|
294
|
+
border-radius: 6px 6px 0 0;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
${CustomTabsTabBarTriggerCompose}:hover && {
|
|
298
|
+
background-color: ${useTheme().semantic.color.background.neutral500};
|
|
299
|
+
}
|
|
300
|
+
${CustomTabsTabBarTriggerCompose}[data-state='active'] && {
|
|
301
|
+
background-color: ${useTheme().semantic.color.background.neutral800};
|
|
302
|
+
color: ${useTheme().semantic.color.background.neutral100};
|
|
303
|
+
}
|
|
304
|
+
${CustomTabsTabBarTriggerCompose}[data-disabled] && {
|
|
305
|
+
background: none;
|
|
306
|
+
border: solid ${useTheme().semantic.color.background.neutral300};
|
|
307
|
+
border-width: 1px 1px 0 1px;
|
|
308
|
+
}
|
|
309
|
+
`;
|
|
310
|
+
|
|
311
|
+
const CustomTabsTriggerMarker = styled(Tabs.TabBar.Trigger.Marker)`
|
|
312
|
+
${CustomTabsTabBarTriggerCompose}[data-state='active'] && {
|
|
313
|
+
background-color: ${useTheme().semantic.color.background.danger500};
|
|
314
|
+
height: 5px;
|
|
315
|
+
}
|
|
316
|
+
`;
|
|
317
|
+
|
|
318
|
+
function Example() {
|
|
319
|
+
return (
|
|
320
|
+
<Tabs.Compose defaultValue="tab1">
|
|
321
|
+
<Tabs.TabBar.Compose>
|
|
322
|
+
{tabs.map(({ value, label, disabled }) => (
|
|
323
|
+
<CustomTabsTabBarTriggerCompose key={value} value={value} disabled={disabled}>
|
|
324
|
+
<CustomTabsTriggerContent>{label ?? value}</CustomTabsTriggerContent>
|
|
325
|
+
<CustomTabsTriggerMarker />
|
|
326
|
+
</CustomTabsTabBarTriggerCompose>
|
|
327
|
+
))}
|
|
328
|
+
</Tabs.TabBar.Compose>
|
|
329
|
+
<Tabs.ContentPane tabs={tabs} />
|
|
330
|
+
</Tabs.Compose>
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### ContentComposition
|
|
336
|
+
|
|
337
|
+
> The `Tabs.ContentPane` can be composed and customized using a container for each tab (`Tabs.ContentPane.Content`) and a main container (`Tabs.ContentPane.Compose`).
|
|
338
|
+
|
|
339
|
+
```tsx
|
|
340
|
+
import { Tabs } from '@redislabsdev/redis-ui-components';
|
|
341
|
+
import styled from 'styled-components';
|
|
342
|
+
import { useTheme } from '@redislabsdev/redis-ui-styles';
|
|
343
|
+
|
|
344
|
+
const tabs = [
|
|
345
|
+
{ value: 'tab1', label: 'First Tab', content: 'First Tab Content' },
|
|
346
|
+
{ value: 'tab2', label: 'Second Tab', content: 'Second Tab Content' },
|
|
347
|
+
{ value: 'tab3', label: 'Third Tab (disabled)', content: 'Third Tab Content', disabled: true }
|
|
348
|
+
];
|
|
349
|
+
|
|
350
|
+
const CustomTabsContentPaneContent = styled(Tabs.ContentPane.Content)`
|
|
351
|
+
background-color: ${useTheme().semantic.color.background.success100};
|
|
352
|
+
padding: 10px;
|
|
353
|
+
border: 1px solid ${({ theme }) => theme.components.tabs.variants.default?.tabsLine.color};
|
|
354
|
+
border-top: none;
|
|
355
|
+
`;
|
|
356
|
+
|
|
357
|
+
function Example() {
|
|
358
|
+
return (
|
|
359
|
+
<Tabs.Compose defaultValue="tab1">
|
|
360
|
+
<Tabs.TabBar tabs={tabs} />
|
|
361
|
+
<Tabs.ContentPane.Compose>
|
|
362
|
+
<CustomTabsContentPaneContent value="tab1">
|
|
363
|
+
<strong>First Tab Content</strong>
|
|
364
|
+
</CustomTabsContentPaneContent>
|
|
365
|
+
<CustomTabsContentPaneContent value="tab2">
|
|
366
|
+
<em>Second Tab Content</em>
|
|
367
|
+
</CustomTabsContentPaneContent>
|
|
368
|
+
</Tabs.ContentPane.Compose>
|
|
369
|
+
</Tabs.Compose>
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
## Notes
|
|
375
|
+
|
|
376
|
+
- Use `value` and `onChange` together for controlled mode.
|
|
377
|
+
- `Tabs` supports `default` and `sub` variants.
|
|
378
|
+
- Keyboard navigation activates on Enter or Space by default; set `activateOnFocus` to activate the tab when focus moves with the arrow keys.
|
|
379
|
+
- `Tabs.TabBar` and `Tabs.ContentPane` can be used together as shallow composition building blocks.
|
|
380
|
+
- Pass the same `tabs` array to `Tabs.TabBar` and `Tabs.ContentPane` when composing them separately.
|
|
381
|
+
- `Tabs.Compose` should receive the shared state props when building custom layouts.
|
|
382
|
+
- `Tabs` can be used without `Tabs.ContentPane` when a router or other external content switch handles the panel rendering.
|
|
383
|
+
- Define styled components outside the render function when composing `Tabs.TabBar` or `Tabs.ContentPane`.
|