@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.
Files changed (85) hide show
  1. package/dist/HighlightedIcon/HighlightedIcon.cjs +26 -0
  2. package/dist/HighlightedIcon/HighlightedIcon.d.ts +3 -0
  3. package/dist/HighlightedIcon/HighlightedIcon.js +26 -0
  4. package/dist/HighlightedIcon/HighlightedIcon.style.cjs +49 -0
  5. package/dist/HighlightedIcon/HighlightedIcon.style.d.ts +5 -0
  6. package/dist/HighlightedIcon/HighlightedIcon.style.js +47 -0
  7. package/dist/HighlightedIcon/HighlightedIcon.types.d.ts +8 -0
  8. package/dist/HighlightedIcon/index.d.ts +3 -0
  9. package/dist/Stepper/Stepper.cjs +14 -5
  10. package/dist/Stepper/Stepper.d.ts +2 -0
  11. package/dist/Stepper/Stepper.js +14 -5
  12. package/dist/Stepper/Stepper.utils.cjs +12 -0
  13. package/dist/Stepper/Stepper.utils.d.ts +2 -0
  14. package/dist/Stepper/Stepper.utils.js +12 -0
  15. package/dist/Stepper/components/Compose/Compose.d.ts +1 -0
  16. package/dist/Stepper/components/Step/Step.cjs +2 -0
  17. package/dist/Stepper/components/Step/Step.d.ts +1 -0
  18. package/dist/Stepper/components/Step/Step.js +2 -0
  19. package/dist/Stepper/components/Step/components/Compose/Compose.cjs +2 -9
  20. package/dist/Stepper/components/Step/components/Compose/Compose.js +2 -9
  21. package/dist/Stepper/components/Step/components/Separator/Separator.cjs +15 -0
  22. package/dist/Stepper/components/Step/components/Separator/Separator.d.ts +3 -0
  23. package/dist/Stepper/components/Step/components/Separator/Separator.js +15 -0
  24. package/dist/Stepper/components/Step/components/Separator/Separator.style.cjs +24 -0
  25. package/dist/Stepper/components/Step/components/Separator/Separator.style.d.ts +1 -0
  26. package/dist/Stepper/components/Step/components/Separator/Separator.style.js +22 -0
  27. package/dist/Stepper/components/Step/components/Separator/Separator.types.d.ts +5 -0
  28. package/dist/index.cjs +4 -0
  29. package/dist/index.d.ts +1 -0
  30. package/dist/index.js +74 -70
  31. package/package.json +2 -2
  32. package/skills/redis-ui-components/SKILL.md +0 -2
  33. package/skills/redis-ui-components/references/ActionIconButton.md +96 -0
  34. package/skills/redis-ui-components/references/AppBar.md +161 -0
  35. package/skills/redis-ui-components/references/AppSelectionMenu.md +184 -0
  36. package/skills/redis-ui-components/references/AutoCompleteSelect.md +193 -0
  37. package/skills/redis-ui-components/references/Badge.md +77 -0
  38. package/skills/redis-ui-components/references/Banner.md +563 -0
  39. package/skills/redis-ui-components/references/BoxSelectionGroup.md +487 -0
  40. package/skills/redis-ui-components/references/Breadcrumbs.md +214 -0
  41. package/skills/redis-ui-components/references/ButtonGroup.md +126 -0
  42. package/skills/redis-ui-components/references/Card.md +56 -0
  43. package/skills/redis-ui-components/references/Checkbox.md +171 -0
  44. package/skills/redis-ui-components/references/Chip.md +154 -0
  45. package/skills/redis-ui-components/references/ChipList.md +307 -0
  46. package/skills/redis-ui-components/references/CopyToClipboardButton.md +47 -0
  47. package/skills/redis-ui-components/references/CountryFlag.md +57 -0
  48. package/skills/redis-ui-components/references/Drawer.md +298 -0
  49. package/skills/redis-ui-components/references/Filters.md +162 -0
  50. package/skills/redis-ui-components/references/FormField.md +678 -0
  51. package/skills/redis-ui-components/references/IconButton.md +63 -0
  52. package/skills/redis-ui-components/references/Input.md +295 -0
  53. package/skills/redis-ui-components/references/KeyValueList.md +501 -0
  54. package/skills/redis-ui-components/references/Label.md +238 -0
  55. package/skills/redis-ui-components/references/Link.md +402 -0
  56. package/skills/redis-ui-components/references/Loader.md +100 -0
  57. package/skills/redis-ui-components/references/Menu.md +988 -0
  58. package/skills/redis-ui-components/references/MidBar.md +358 -0
  59. package/skills/redis-ui-components/references/Modal.md +525 -0
  60. package/skills/redis-ui-components/references/MoreInfoIcon.md +119 -0
  61. package/skills/redis-ui-components/references/MultiSelect.md +558 -0
  62. package/skills/redis-ui-components/references/NumericInput.md +322 -0
  63. package/skills/redis-ui-components/references/Overflow.md +127 -0
  64. package/skills/redis-ui-components/references/Pagination.md +151 -0
  65. package/skills/redis-ui-components/references/PasswordInput.md +262 -0
  66. package/skills/redis-ui-components/references/Popover.md +868 -0
  67. package/skills/redis-ui-components/references/ProfileIcon.md +65 -0
  68. package/skills/redis-ui-components/references/ProgressBar.md +103 -0
  69. package/skills/redis-ui-components/references/QuantityCounter.md +555 -0
  70. package/skills/redis-ui-components/references/RadioGroup.md +265 -0
  71. package/skills/redis-ui-components/references/ScreenReaderAnnounce.md +147 -0
  72. package/skills/redis-ui-components/references/SearchBar.md +242 -0
  73. package/skills/redis-ui-components/references/SearchInput.md +213 -0
  74. package/skills/redis-ui-components/references/Section.md +349 -0
  75. package/skills/redis-ui-components/references/SideBar.md +468 -0
  76. package/skills/redis-ui-components/references/Slider.md +398 -0
  77. package/skills/redis-ui-components/references/Stepper.md +288 -0
  78. package/skills/redis-ui-components/references/Switch.md +193 -0
  79. package/skills/redis-ui-components/references/Tabs.md +383 -0
  80. package/skills/redis-ui-components/references/TextArea.md +139 -0
  81. package/skills/redis-ui-components/references/TextButton.md +217 -0
  82. package/skills/redis-ui-components/references/Toast.md +399 -0
  83. package/skills/redis-ui-components/references/ToggleButton.md +163 -0
  84. package/skills/redis-ui-components/references/Tooltip.md +636 -0
  85. 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`.