@commercetools/nimbus-mcp 3.5.1 → 3.6.0
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/data/docs/route-manifest.json +275 -9
- package/data/docs/routes/components-buttons-toggle-button-group.json +143 -18
- package/data/docs/routes/components-buttons-toggle-button.json +72 -15
- package/data/docs/routes/components-chat.json +36 -0
- package/data/docs/routes/components-content.json +36 -0
- package/data/docs/routes/components-data-display-data-table.json +1 -1
- package/data/docs/routes/components-feedback-popover.json +643 -0
- package/data/docs/routes/components-inputs-combo-box.json +33 -11
- package/data/docs/routes/components-inputs-search-input.json +29 -7
- package/data/docs/routes/components-inputs-select-input.json +23 -1
- package/data/docs/routes/components-layout-stack.json +1 -1
- package/data/docs/routes/components-navigation-toolbar.json +1 -1
- package/data/docs/routes/components-navigation-tree.json +2 -2
- package/data/docs/routes/home-contribute.json +29 -8
- package/data/docs/routes/home-getting-started-collaboration.json +657 -0
- package/data/docs/search-index.json +1 -1
- package/data/docs/types/AccordionContent.json +12 -12
- package/data/docs/types/AccordionHeader.json +46 -46
- package/data/docs/types/AccordionItem.json +20 -20
- package/data/docs/types/AccordionRoot.json +12 -12
- package/data/docs/types/ActivityIndicator.json +3 -2
- package/data/docs/types/AlertDismissButton.json +42 -42
- package/data/docs/types/Button.json +47 -46
- package/data/docs/types/Calendar.json +43 -42
- package/data/docs/types/Checkbox.json +30 -29
- package/data/docs/types/Code.json +2 -1
- package/data/docs/types/ComboBoxListBox.json +34 -34
- package/data/docs/types/ComboBoxOption.json +20 -20
- package/data/docs/types/ComboBoxPopover.json +67 -86
- package/data/docs/types/ComboBoxRoot.json +15 -0
- package/data/docs/types/ComboBoxSection.json +14 -14
- package/data/docs/types/DataTableBody.json +10 -10
- package/data/docs/types/DataTableCell.json +18 -18
- package/data/docs/types/DataTableColumn.json +28 -28
- package/data/docs/types/DataTableHeader.json +10 -10
- package/data/docs/types/DataTableManager.json +3 -5
- package/data/docs/types/DataTableRow.json +24 -24
- package/data/docs/types/DateInput.json +33 -32
- package/data/docs/types/DatePicker.json +32 -32
- package/data/docs/types/DateRangePicker.json +46 -46
- package/data/docs/types/DateRangePickerField.json +46 -46
- package/data/docs/types/DialogCloseTrigger.json +42 -42
- package/data/docs/types/DraggableListField.json +28 -28
- package/data/docs/types/DraggableListItem.json +18 -18
- package/data/docs/types/DraggableListRoot.json +30 -30
- package/data/docs/types/DrawerCloseTrigger.json +42 -42
- package/data/docs/types/DropZone.json +14 -14
- package/data/docs/types/FloatingActionButton.json +44 -44
- package/data/docs/types/Group.json +9 -7
- package/data/docs/types/Heading.json +3 -2
- package/data/docs/types/Icon.json +3 -2
- package/data/docs/types/IconButton.json +47 -46
- package/data/docs/types/IconToggleButton.json +71 -35
- package/data/docs/types/Link.json +3 -2
- package/data/docs/types/LoadingSpinner.json +3 -2
- package/data/docs/types/LocalizedField.json +3 -2
- package/data/docs/types/MakeElementFocusable.json +2 -2
- package/data/docs/types/MenuItem.json +22 -22
- package/data/docs/types/MenuRoot.json +31 -31
- package/data/docs/types/MenuSection.json +16 -16
- package/data/docs/types/MenuSubmenuTrigger.json +4 -4
- package/data/docs/types/MenuTrigger.json +46 -46
- package/data/docs/types/MoneyInput.json +4 -2
- package/data/docs/types/MultilineTextInput.json +27 -26
- package/data/docs/types/MultilineTextInputField.json +27 -26
- package/data/docs/types/NumberInput.json +14 -12
- package/data/docs/types/NumberInputField.json +10 -10
- package/data/docs/types/PasswordInput.json +24 -24
- package/data/docs/types/PasswordInputField.json +24 -24
- package/data/docs/types/Popover.json +13 -0
- package/data/docs/types/PopoverContent.json +42 -0
- package/data/docs/types/PopoverRoot.json +651 -0
- package/data/docs/types/PopoverTrigger.json +914 -0
- package/data/docs/types/ProgressBar.json +17 -15
- package/data/docs/types/RadioInputOption.json +17 -17
- package/data/docs/types/RadioInputRoot.json +10 -10
- package/data/docs/types/RangeCalendar.json +42 -42
- package/data/docs/types/RangeSlider.json +14 -14
- package/data/docs/types/Region.json +3 -2
- package/data/docs/types/RichTextInput.json +4 -2
- package/data/docs/types/SearchInput.json +60 -28
- package/data/docs/types/SearchInputField.json +60 -28
- package/data/docs/types/SelectOption.json +20 -20
- package/data/docs/types/SelectOptionGroup.json +14 -14
- package/data/docs/types/SelectOptions.json +34 -34
- package/data/docs/types/SelectRoot.json +67 -52
- package/data/docs/types/Separator.json +4 -2
- package/data/docs/types/Slider.json +18 -16
- package/data/docs/types/SplitButton.json +12 -10
- package/data/docs/types/Switch.json +11 -10
- package/data/docs/types/TagGroupRoot.json +12 -12
- package/data/docs/types/TagGroupTag.json +16 -16
- package/data/docs/types/TagGroupTagList.json +12 -12
- package/data/docs/types/TextInput.json +27 -26
- package/data/docs/types/TextInputField.json +27 -26
- package/data/docs/types/TimeInput.json +30 -28
- package/data/docs/types/ToastOutlet.json +4 -2
- package/data/docs/types/ToggleButton.json +74 -37
- package/data/docs/types/ToggleButtonGroup.json +4 -2
- package/data/docs/types/ToggleButtonGroupButton.json +547 -55
- package/data/docs/types/ToggleButtonGroupRoot.json +48 -16
- package/data/docs/types/Toolbar.json +11 -9
- package/data/docs/types/Tooltip.json +3 -2
- package/data/docs/types/TooltipContent.json +26 -26
- package/data/docs/types/TooltipRoot.json +16 -16
- package/data/docs/types/TreeIndicator.json +40 -40
- package/data/docs/types/TreeItem.json +20 -20
- package/data/docs/types/TreeRoot.json +26 -26
- package/data/docs/types/VisuallyHidden.json +4 -4
- package/data/docs/types/createItemsFromCsvDrop.json +2 -2
- package/data/docs/types/createItemsFromDirectoryDrop.json +2 -2
- package/data/docs/types/createItemsFromFileDrop.json +2 -2
- package/data/docs/types/createItemsFromImageDrop.json +2 -2
- package/data/docs/types/createItemsFromJsonDrop.json +2 -2
- package/data/docs/types/manifest.json +4 -0
- package/data/docs/types/useTree.json +8 -8
- package/data/style-props-summary.json +408 -0
- package/dist/index.js +156 -43
- package/package.json +8 -8
|
@@ -87,6 +87,52 @@
|
|
|
87
87
|
],
|
|
88
88
|
"parent": "root"
|
|
89
89
|
},
|
|
90
|
+
{
|
|
91
|
+
"value": "Variant",
|
|
92
|
+
"href": "#variant",
|
|
93
|
+
"depth": 3,
|
|
94
|
+
"numbering": [
|
|
95
|
+
1,
|
|
96
|
+
2,
|
|
97
|
+
2
|
|
98
|
+
],
|
|
99
|
+
"parent": "root"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"value": "Outline (default)",
|
|
103
|
+
"href": "#outline-default",
|
|
104
|
+
"depth": 4,
|
|
105
|
+
"numbering": [
|
|
106
|
+
1,
|
|
107
|
+
2,
|
|
108
|
+
2,
|
|
109
|
+
1
|
|
110
|
+
],
|
|
111
|
+
"parent": "root"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"value": "Subtle",
|
|
115
|
+
"href": "#subtle",
|
|
116
|
+
"depth": 4,
|
|
117
|
+
"numbering": [
|
|
118
|
+
1,
|
|
119
|
+
2,
|
|
120
|
+
2,
|
|
121
|
+
2
|
|
122
|
+
],
|
|
123
|
+
"parent": "root"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"value": "Active fill",
|
|
127
|
+
"href": "#active-fill",
|
|
128
|
+
"depth": 3,
|
|
129
|
+
"numbering": [
|
|
130
|
+
1,
|
|
131
|
+
2,
|
|
132
|
+
3
|
|
133
|
+
],
|
|
134
|
+
"parent": "root"
|
|
135
|
+
},
|
|
90
136
|
{
|
|
91
137
|
"value": "Visual options",
|
|
92
138
|
"href": "#visual-options",
|
|
@@ -94,7 +140,7 @@
|
|
|
94
140
|
"numbering": [
|
|
95
141
|
1,
|
|
96
142
|
2,
|
|
97
|
-
|
|
143
|
+
4
|
|
98
144
|
],
|
|
99
145
|
"parent": "root"
|
|
100
146
|
},
|
|
@@ -105,7 +151,7 @@
|
|
|
105
151
|
"numbering": [
|
|
106
152
|
1,
|
|
107
153
|
2,
|
|
108
|
-
|
|
154
|
+
4,
|
|
109
155
|
1
|
|
110
156
|
],
|
|
111
157
|
"parent": "root"
|
|
@@ -117,7 +163,7 @@
|
|
|
117
163
|
"numbering": [
|
|
118
164
|
1,
|
|
119
165
|
2,
|
|
120
|
-
|
|
166
|
+
4,
|
|
121
167
|
2
|
|
122
168
|
],
|
|
123
169
|
"parent": "root"
|
|
@@ -129,7 +175,7 @@
|
|
|
129
175
|
"numbering": [
|
|
130
176
|
1,
|
|
131
177
|
2,
|
|
132
|
-
|
|
178
|
+
4,
|
|
133
179
|
3
|
|
134
180
|
],
|
|
135
181
|
"parent": "root"
|
|
@@ -160,10 +206,10 @@
|
|
|
160
206
|
}
|
|
161
207
|
]
|
|
162
208
|
},
|
|
163
|
-
"mdx": "\n## Overview\n\nButton groups can be used several ways, with and without icons, and spanning\nfrom two selections to several.\n\n### Resources\n\nDeep dive into implementation details and access the Nimbus design library.\n\n[Figma library](https://www.figma.com/design/AvtPX6g7OGGCRvNlatGOIY/NIMBUS-design-system?node-id=2693-2416&m=dev)\n\n[`ToggleButtonGroup` on `react-aria`](https://react-spectrum.adobe.com/react-aria/ToggleButtonGroup.html#togglebuttongroup)\n\n[Relevant W3C Aria pattern](https://www.w3.org/WAI/ARIA/apg/patterns/toolbar/)\n\n## Variables\n\nGet familiar with the features.\n\n### Size\n\nToggle Button Groups come in different sizes to fit various layout needs.\n\n#### Medium\n\nThis is the default size.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Medium size example (default)\" selectedKeys={[\"md-day\"]} colorPalette=\"primary\">\n <ToggleButtonGroup.Button id=\"md-day\"><Icons.ViewDay />Day</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"md-week\"><Icons.CalendarViewWeek />Week</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"md-month\"><Icons.CalendarViewMonth />Month</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n#### X-Small\n\nThis size is for compact placements.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root size=\"xs\" aria-label=\"X-Small size example\" selectedKeys={[\"xs-day\"]} colorPalette=\"primary\">\n <ToggleButtonGroup.Button id=\"xs-day\"><Icons.ViewDay />Day</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"xs-week\"><Icons.CalendarViewWeek />Week</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"xs-month\"><Icons.CalendarViewMonth />Month</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n### Visual options\n\nToggle Button Groups can be configured with labels, icons, or both.\n\n#### Labels and icons\n\nButton groups with icons and labels are used to present a set of related actions\nin a compact and visually clear way, where icons provide quick recognition and\nlabels offer explicit understanding of each option. This combination enhances\nuser efficiency by making common choices readily available and easily\nidentifiable.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Labels and icons example\" selectedKeys={[\"li-shipped\"]} colorPalette=\"primary\">\n <ToggleButtonGroup.Button id=\"li-processing\">\n <Icons.RotateRight /> Processing\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"li-shipped\">\n <Icons.LocalShipping /> Shipped\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"li-cancelled\">\n <Icons.Dangerous /> Cancelled\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"li-refunded\">\n <Icons.CurrencyExchange /> Refunded\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n#### Just labels\n\nButton groups with just labels provide explicit understanding of each option.\nThis approach prioritizes readability and ease of comprehension, making it\nsuitable for scenarios where icons might be ambiguous or when the actions are\nbest described through text.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Just labels example\" selectedKeys={[\"label-inactive\"]} colorPalette=\"primary\">\n <ToggleButtonGroup.Button id=\"label-active\">\n Active promotions\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"label-inactive\">\n Inactive promotions\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"label-draft\">\n Draft promotions\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n#### Just icons\n\nMessages potential problems or situations that require user attention to prevent\nissues. They require the user to take action to make needed corrections or\nconfirmation. Use tooltips for accessibility.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Just icons example\" selectedKeys={[\"icon-copy\"]} colorPalette=\"primary\">\n <Tooltip.Root delay={0} closeDelay={0}>\n <ToggleButtonGroup.Button id=\"icon-edit\" aria-label=\"Edit view\">\n <Icons.Edit />\n </ToggleButtonGroup.Button>\n <Tooltip.Content>Edit</Tooltip.Content>\n </Tooltip.Root>\n <Tooltip.Root delay={0} closeDelay={0}>\n <ToggleButtonGroup.Button id=\"icon-copy\" aria-label=\"Copy view\">\n <Icons.ContentCopy />\n </ToggleButtonGroup.Button>\n <Tooltip.Content>Copy</Tooltip.Content>\n </Tooltip.Root>\n <Tooltip.Root delay={0} closeDelay={0}>\n <ToggleButtonGroup.Button id=\"icon-delete\" aria-label=\"Delete view\">\n <Icons.Delete />\n </ToggleButtonGroup.Button>\n <Tooltip.Content>Delete</Tooltip.Content>\n </Tooltip.Root>\n </ToggleButtonGroup.Root>\n);\n```\n",
|
|
209
|
+
"mdx": "\n## Overview\n\nButton groups can be used several ways, with and without icons, and spanning\nfrom two selections to several.\n\n### Resources\n\nDeep dive into implementation details and access the Nimbus design library.\n\n[Figma library](https://www.figma.com/design/AvtPX6g7OGGCRvNlatGOIY/NIMBUS-design-system?node-id=2693-2416&m=dev)\n\n[`ToggleButtonGroup` on `react-aria`](https://react-spectrum.adobe.com/react-aria/ToggleButtonGroup.html#togglebuttongroup)\n\n[Relevant W3C Aria pattern](https://www.w3.org/WAI/ARIA/apg/patterns/toolbar/)\n\n## Variables\n\nGet familiar with the features.\n\n### Size\n\nToggle Button Groups come in different sizes to fit various layout needs.\n\n#### Medium\n\nThis is the default size.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Medium size example (default)\" selectedKeys={[\"md-day\"]} colorPalette=\"primary\">\n <ToggleButtonGroup.Button id=\"md-day\"><Icons.ViewDay />Day</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"md-week\"><Icons.CalendarViewWeek />Week</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"md-month\"><Icons.CalendarViewMonth />Month</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n#### X-Small\n\nThis size is for compact placements.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root size=\"xs\" aria-label=\"X-Small size example\" selectedKeys={[\"xs-day\"]} colorPalette=\"primary\">\n <ToggleButtonGroup.Button id=\"xs-day\"><Icons.ViewDay />Day</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"xs-week\"><Icons.CalendarViewWeek />Week</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"xs-month\"><Icons.CalendarViewMonth />Month</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n### Variant\n\nThe `variant` prop sets the resting chrome shared by the whole group. The group\nis always segmented; the variant only changes the resting fill.\n\n#### Outline (default)\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root variant=\"outline\" selectedKeys={[\"outline-center\"]} colorPalette=\"primary\" aria-label=\"Outline variant example\">\n <ToggleButtonGroup.Button id=\"outline-left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"outline-center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"outline-right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n#### Subtle\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root variant=\"subtle\" selectedKeys={[\"subtle-center\"]} colorPalette=\"primary\" aria-label=\"Subtle variant example\">\n <ToggleButtonGroup.Button id=\"subtle-left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"subtle-center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"subtle-right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n### Active fill\n\nThe `activeFillStyle` prop sets the weight of the selected segments. Its default\nfollows the selection mode: single selection defaults to `solid`, multiple to\n`tint`.\n\n```jsx live\nconst App = () => (\n <Stack gap=\"400\" direction=\"column\">\n <ToggleButtonGroup.Root activeFillStyle=\"solid\" selectedKeys={[\"solid-center\"]} colorPalette=\"primary\" aria-label=\"Solid fill example\">\n <ToggleButtonGroup.Button id=\"solid-left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"solid-center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"solid-right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n <ToggleButtonGroup.Root selectionMode=\"multiple\" activeFillStyle=\"tint\" selectedKeys={[\"tint-left\", \"tint-right\"]} colorPalette=\"primary\" aria-label=\"Tint fill example\">\n <ToggleButtonGroup.Button id=\"tint-left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"tint-center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"tint-right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n);\n```\n\n### Visual options\n\nToggle Button Groups can be configured with labels, icons, or both.\n\n#### Labels and icons\n\nButton groups with icons and labels are used to present a set of related actions\nin a compact and visually clear way, where icons provide quick recognition and\nlabels offer explicit understanding of each option. This combination enhances\nuser efficiency by making common choices readily available and easily\nidentifiable.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Labels and icons example\" selectedKeys={[\"li-shipped\"]} colorPalette=\"primary\">\n <ToggleButtonGroup.Button id=\"li-processing\">\n <Icons.RotateRight /> Processing\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"li-shipped\">\n <Icons.LocalShipping /> Shipped\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"li-cancelled\">\n <Icons.Dangerous /> Cancelled\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"li-refunded\">\n <Icons.CurrencyExchange /> Refunded\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n#### Just labels\n\nButton groups with just labels provide explicit understanding of each option.\nThis approach prioritizes readability and ease of comprehension, making it\nsuitable for scenarios where icons might be ambiguous or when the actions are\nbest described through text.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Just labels example\" selectedKeys={[\"label-inactive\"]} colorPalette=\"primary\">\n <ToggleButtonGroup.Button id=\"label-active\">\n Active promotions\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"label-inactive\">\n Inactive promotions\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"label-draft\">\n Draft promotions\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n#### Just icons\n\nMessages potential problems or situations that require user attention to prevent\nissues. They require the user to take action to make needed corrections or\nconfirmation. Use tooltips for accessibility.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Just icons example\" selectedKeys={[\"icon-copy\"]} colorPalette=\"primary\">\n <Tooltip.Root delay={0} closeDelay={0}>\n <ToggleButtonGroup.Button id=\"icon-edit\" aria-label=\"Edit view\">\n <Icons.Edit />\n </ToggleButtonGroup.Button>\n <Tooltip.Content>Edit</Tooltip.Content>\n </Tooltip.Root>\n <Tooltip.Root delay={0} closeDelay={0}>\n <ToggleButtonGroup.Button id=\"icon-copy\" aria-label=\"Copy view\">\n <Icons.ContentCopy />\n </ToggleButtonGroup.Button>\n <Tooltip.Content>Copy</Tooltip.Content>\n </Tooltip.Root>\n <Tooltip.Root delay={0} closeDelay={0}>\n <ToggleButtonGroup.Button id=\"icon-delete\" aria-label=\"Delete view\">\n <Icons.Delete />\n </ToggleButtonGroup.Button>\n <Tooltip.Content>Delete</Tooltip.Content>\n </Tooltip.Root>\n </ToggleButtonGroup.Root>\n);\n```\n",
|
|
164
210
|
"views": {
|
|
165
211
|
"overview": {
|
|
166
|
-
"mdx": "\n## Overview\n\nButton groups can be used several ways, with and without icons, and spanning\nfrom two selections to several.\n\n### Resources\n\nDeep dive into implementation details and access the Nimbus design library.\n\n[Figma library](https://www.figma.com/design/AvtPX6g7OGGCRvNlatGOIY/NIMBUS-design-system?node-id=2693-2416&m=dev)\n\n[`ToggleButtonGroup` on `react-aria`](https://react-spectrum.adobe.com/react-aria/ToggleButtonGroup.html#togglebuttongroup)\n\n[Relevant W3C Aria pattern](https://www.w3.org/WAI/ARIA/apg/patterns/toolbar/)\n\n## Variables\n\nGet familiar with the features.\n\n### Size\n\nToggle Button Groups come in different sizes to fit various layout needs.\n\n#### Medium\n\nThis is the default size.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Medium size example (default)\" selectedKeys={[\"md-day\"]} colorPalette=\"primary\">\n <ToggleButtonGroup.Button id=\"md-day\"><Icons.ViewDay />Day</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"md-week\"><Icons.CalendarViewWeek />Week</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"md-month\"><Icons.CalendarViewMonth />Month</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n#### X-Small\n\nThis size is for compact placements.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root size=\"xs\" aria-label=\"X-Small size example\" selectedKeys={[\"xs-day\"]} colorPalette=\"primary\">\n <ToggleButtonGroup.Button id=\"xs-day\"><Icons.ViewDay />Day</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"xs-week\"><Icons.CalendarViewWeek />Week</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"xs-month\"><Icons.CalendarViewMonth />Month</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n### Visual options\n\nToggle Button Groups can be configured with labels, icons, or both.\n\n#### Labels and icons\n\nButton groups with icons and labels are used to present a set of related actions\nin a compact and visually clear way, where icons provide quick recognition and\nlabels offer explicit understanding of each option. This combination enhances\nuser efficiency by making common choices readily available and easily\nidentifiable.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Labels and icons example\" selectedKeys={[\"li-shipped\"]} colorPalette=\"primary\">\n <ToggleButtonGroup.Button id=\"li-processing\">\n <Icons.RotateRight /> Processing\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"li-shipped\">\n <Icons.LocalShipping /> Shipped\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"li-cancelled\">\n <Icons.Dangerous /> Cancelled\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"li-refunded\">\n <Icons.CurrencyExchange /> Refunded\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n#### Just labels\n\nButton groups with just labels provide explicit understanding of each option.\nThis approach prioritizes readability and ease of comprehension, making it\nsuitable for scenarios where icons might be ambiguous or when the actions are\nbest described through text.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Just labels example\" selectedKeys={[\"label-inactive\"]} colorPalette=\"primary\">\n <ToggleButtonGroup.Button id=\"label-active\">\n Active promotions\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"label-inactive\">\n Inactive promotions\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"label-draft\">\n Draft promotions\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n#### Just icons\n\nMessages potential problems or situations that require user attention to prevent\nissues. They require the user to take action to make needed corrections or\nconfirmation. Use tooltips for accessibility.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Just icons example\" selectedKeys={[\"icon-copy\"]} colorPalette=\"primary\">\n <Tooltip.Root delay={0} closeDelay={0}>\n <ToggleButtonGroup.Button id=\"icon-edit\" aria-label=\"Edit view\">\n <Icons.Edit />\n </ToggleButtonGroup.Button>\n <Tooltip.Content>Edit</Tooltip.Content>\n </Tooltip.Root>\n <Tooltip.Root delay={0} closeDelay={0}>\n <ToggleButtonGroup.Button id=\"icon-copy\" aria-label=\"Copy view\">\n <Icons.ContentCopy />\n </ToggleButtonGroup.Button>\n <Tooltip.Content>Copy</Tooltip.Content>\n </Tooltip.Root>\n <Tooltip.Root delay={0} closeDelay={0}>\n <ToggleButtonGroup.Button id=\"icon-delete\" aria-label=\"Delete view\">\n <Icons.Delete />\n </ToggleButtonGroup.Button>\n <Tooltip.Content>Delete</Tooltip.Content>\n </Tooltip.Root>\n </ToggleButtonGroup.Root>\n);\n```\n",
|
|
212
|
+
"mdx": "\n## Overview\n\nButton groups can be used several ways, with and without icons, and spanning\nfrom two selections to several.\n\n### Resources\n\nDeep dive into implementation details and access the Nimbus design library.\n\n[Figma library](https://www.figma.com/design/AvtPX6g7OGGCRvNlatGOIY/NIMBUS-design-system?node-id=2693-2416&m=dev)\n\n[`ToggleButtonGroup` on `react-aria`](https://react-spectrum.adobe.com/react-aria/ToggleButtonGroup.html#togglebuttongroup)\n\n[Relevant W3C Aria pattern](https://www.w3.org/WAI/ARIA/apg/patterns/toolbar/)\n\n## Variables\n\nGet familiar with the features.\n\n### Size\n\nToggle Button Groups come in different sizes to fit various layout needs.\n\n#### Medium\n\nThis is the default size.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Medium size example (default)\" selectedKeys={[\"md-day\"]} colorPalette=\"primary\">\n <ToggleButtonGroup.Button id=\"md-day\"><Icons.ViewDay />Day</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"md-week\"><Icons.CalendarViewWeek />Week</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"md-month\"><Icons.CalendarViewMonth />Month</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n#### X-Small\n\nThis size is for compact placements.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root size=\"xs\" aria-label=\"X-Small size example\" selectedKeys={[\"xs-day\"]} colorPalette=\"primary\">\n <ToggleButtonGroup.Button id=\"xs-day\"><Icons.ViewDay />Day</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"xs-week\"><Icons.CalendarViewWeek />Week</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"xs-month\"><Icons.CalendarViewMonth />Month</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n### Variant\n\nThe `variant` prop sets the resting chrome shared by the whole group. The group\nis always segmented; the variant only changes the resting fill.\n\n#### Outline (default)\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root variant=\"outline\" selectedKeys={[\"outline-center\"]} colorPalette=\"primary\" aria-label=\"Outline variant example\">\n <ToggleButtonGroup.Button id=\"outline-left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"outline-center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"outline-right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n#### Subtle\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root variant=\"subtle\" selectedKeys={[\"subtle-center\"]} colorPalette=\"primary\" aria-label=\"Subtle variant example\">\n <ToggleButtonGroup.Button id=\"subtle-left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"subtle-center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"subtle-right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n### Active fill\n\nThe `activeFillStyle` prop sets the weight of the selected segments. Its default\nfollows the selection mode: single selection defaults to `solid`, multiple to\n`tint`.\n\n```jsx live\nconst App = () => (\n <Stack gap=\"400\" direction=\"column\">\n <ToggleButtonGroup.Root activeFillStyle=\"solid\" selectedKeys={[\"solid-center\"]} colorPalette=\"primary\" aria-label=\"Solid fill example\">\n <ToggleButtonGroup.Button id=\"solid-left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"solid-center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"solid-right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n <ToggleButtonGroup.Root selectionMode=\"multiple\" activeFillStyle=\"tint\" selectedKeys={[\"tint-left\", \"tint-right\"]} colorPalette=\"primary\" aria-label=\"Tint fill example\">\n <ToggleButtonGroup.Button id=\"tint-left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"tint-center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"tint-right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n);\n```\n\n### Visual options\n\nToggle Button Groups can be configured with labels, icons, or both.\n\n#### Labels and icons\n\nButton groups with icons and labels are used to present a set of related actions\nin a compact and visually clear way, where icons provide quick recognition and\nlabels offer explicit understanding of each option. This combination enhances\nuser efficiency by making common choices readily available and easily\nidentifiable.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Labels and icons example\" selectedKeys={[\"li-shipped\"]} colorPalette=\"primary\">\n <ToggleButtonGroup.Button id=\"li-processing\">\n <Icons.RotateRight /> Processing\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"li-shipped\">\n <Icons.LocalShipping /> Shipped\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"li-cancelled\">\n <Icons.Dangerous /> Cancelled\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"li-refunded\">\n <Icons.CurrencyExchange /> Refunded\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n#### Just labels\n\nButton groups with just labels provide explicit understanding of each option.\nThis approach prioritizes readability and ease of comprehension, making it\nsuitable for scenarios where icons might be ambiguous or when the actions are\nbest described through text.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Just labels example\" selectedKeys={[\"label-inactive\"]} colorPalette=\"primary\">\n <ToggleButtonGroup.Button id=\"label-active\">\n Active promotions\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"label-inactive\">\n Inactive promotions\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"label-draft\">\n Draft promotions\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n#### Just icons\n\nMessages potential problems or situations that require user attention to prevent\nissues. They require the user to take action to make needed corrections or\nconfirmation. Use tooltips for accessibility.\n\n```jsx live\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Just icons example\" selectedKeys={[\"icon-copy\"]} colorPalette=\"primary\">\n <Tooltip.Root delay={0} closeDelay={0}>\n <ToggleButtonGroup.Button id=\"icon-edit\" aria-label=\"Edit view\">\n <Icons.Edit />\n </ToggleButtonGroup.Button>\n <Tooltip.Content>Edit</Tooltip.Content>\n </Tooltip.Root>\n <Tooltip.Root delay={0} closeDelay={0}>\n <ToggleButtonGroup.Button id=\"icon-copy\" aria-label=\"Copy view\">\n <Icons.ContentCopy />\n </ToggleButtonGroup.Button>\n <Tooltip.Content>Copy</Tooltip.Content>\n </Tooltip.Root>\n <Tooltip.Root delay={0} closeDelay={0}>\n <ToggleButtonGroup.Button id=\"icon-delete\" aria-label=\"Delete view\">\n <Icons.Delete />\n </ToggleButtonGroup.Button>\n <Tooltip.Content>Delete</Tooltip.Content>\n </Tooltip.Root>\n </ToggleButtonGroup.Root>\n);\n```\n",
|
|
167
213
|
"toc": [
|
|
168
214
|
{
|
|
169
215
|
"value": "Overview",
|
|
@@ -231,6 +277,52 @@
|
|
|
231
277
|
],
|
|
232
278
|
"parent": "root"
|
|
233
279
|
},
|
|
280
|
+
{
|
|
281
|
+
"value": "Variant",
|
|
282
|
+
"href": "#variant",
|
|
283
|
+
"depth": 3,
|
|
284
|
+
"numbering": [
|
|
285
|
+
1,
|
|
286
|
+
2,
|
|
287
|
+
2
|
|
288
|
+
],
|
|
289
|
+
"parent": "root"
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"value": "Outline (default)",
|
|
293
|
+
"href": "#outline-default",
|
|
294
|
+
"depth": 4,
|
|
295
|
+
"numbering": [
|
|
296
|
+
1,
|
|
297
|
+
2,
|
|
298
|
+
2,
|
|
299
|
+
1
|
|
300
|
+
],
|
|
301
|
+
"parent": "root"
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
"value": "Subtle",
|
|
305
|
+
"href": "#subtle",
|
|
306
|
+
"depth": 4,
|
|
307
|
+
"numbering": [
|
|
308
|
+
1,
|
|
309
|
+
2,
|
|
310
|
+
2,
|
|
311
|
+
2
|
|
312
|
+
],
|
|
313
|
+
"parent": "root"
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
"value": "Active fill",
|
|
317
|
+
"href": "#active-fill",
|
|
318
|
+
"depth": 3,
|
|
319
|
+
"numbering": [
|
|
320
|
+
1,
|
|
321
|
+
2,
|
|
322
|
+
3
|
|
323
|
+
],
|
|
324
|
+
"parent": "root"
|
|
325
|
+
},
|
|
234
326
|
{
|
|
235
327
|
"value": "Visual options",
|
|
236
328
|
"href": "#visual-options",
|
|
@@ -238,7 +330,7 @@
|
|
|
238
330
|
"numbering": [
|
|
239
331
|
1,
|
|
240
332
|
2,
|
|
241
|
-
|
|
333
|
+
4
|
|
242
334
|
],
|
|
243
335
|
"parent": "root"
|
|
244
336
|
},
|
|
@@ -249,7 +341,7 @@
|
|
|
249
341
|
"numbering": [
|
|
250
342
|
1,
|
|
251
343
|
2,
|
|
252
|
-
|
|
344
|
+
4,
|
|
253
345
|
1
|
|
254
346
|
],
|
|
255
347
|
"parent": "root"
|
|
@@ -261,7 +353,7 @@
|
|
|
261
353
|
"numbering": [
|
|
262
354
|
1,
|
|
263
355
|
2,
|
|
264
|
-
|
|
356
|
+
4,
|
|
265
357
|
2
|
|
266
358
|
],
|
|
267
359
|
"parent": "root"
|
|
@@ -273,7 +365,7 @@
|
|
|
273
365
|
"numbering": [
|
|
274
366
|
1,
|
|
275
367
|
2,
|
|
276
|
-
|
|
368
|
+
4,
|
|
277
369
|
3
|
|
278
370
|
],
|
|
279
371
|
"parent": "root"
|
|
@@ -318,7 +410,7 @@
|
|
|
318
410
|
]
|
|
319
411
|
},
|
|
320
412
|
"dev": {
|
|
321
|
-
"mdx": "\n## Getting started\n\n### Import\n\n```tsx\nimport { ToggleButtonGroup, type ToggleButtonGroupProps } from '@commercetools/nimbus';\n```\n\n### Basic usage\n\nThe ToggleButtonGroup component groups multiple toggle buttons together, allowing users to select one or more options from a set of related choices. It uses a compound component structure with `Root` and `Button` sub-components:\n\n```jsx live-dev\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Text alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n)\n```\n\nBy default, the group operates in single-selection mode where only one button can be selected at a time. Each button must have a unique `id` prop that identifies it within the group.\n\n## Usage examples\n\n### Size options\n\nThe component supports two size variants to match your interface density:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <ToggleButtonGroup.Root size=\"md\" aria-label=\"Medium text alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <ToggleButtonGroup.Root size=\"xs\" aria-label=\"Small text alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n)\n```\n\n### Color palettes\n\nChoose from semantic color palettes to match your design context:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <ToggleButtonGroup.Root colorPalette=\"primary\" aria-label=\"Primary alignment\">\n <ToggleButtonGroup.Button id=\"left\">\n <Icons.FormatAlignLeft />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">\n <Icons.FormatAlignCenter />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">\n <Icons.FormatAlignRight />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <ToggleButtonGroup.Root colorPalette=\"critical\" aria-label=\"Critical actions\">\n <ToggleButtonGroup.Button id=\"delete\">\n <Icons.Delete />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"warning\">\n <Icons.Warning />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"block\">\n <Icons.Block />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <ToggleButtonGroup.Root colorPalette=\"neutral\" aria-label=\"Neutral formatting\">\n <ToggleButtonGroup.Button id=\"bold\">\n <Icons.FormatBold />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"italic\">\n <Icons.FormatItalic />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"underline\">\n <Icons.FormatUnderlined />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n)\n```\n\n### With icons\n\nIcons can be used alone or combined with text labels:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <ToggleButtonGroup.Root aria-label=\"Icon-only formatting\">\n <ToggleButtonGroup.Button id=\"bold\" aria-label=\"Bold\">\n <Icons.FormatBold />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"italic\" aria-label=\"Italic\">\n <Icons.FormatItalic />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"underline\" aria-label=\"Underline\">\n <Icons.FormatUnderlined />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <ToggleButtonGroup.Root aria-label=\"Text alignment with labels\">\n <ToggleButtonGroup.Button id=\"left\">\n <Icons.FormatAlignLeft /> Left\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">\n <Icons.FormatAlignCenter /> Center\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">\n <Icons.FormatAlignRight /> Right\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n)\n```\n\nWhen using icon-only buttons, always provide an `aria-label` on each button for screen reader accessibility.\n\n### Selection modes\n\nThe group supports both single-selection (default) and multi-selection modes:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <Stack direction=\"column\" gap=\"200\">\n <Text fontSize=\"350\" fontWeight=\"600\">Single selection (default)</Text>\n <ToggleButtonGroup.Root aria-label=\"Text alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n\n <Stack direction=\"column\" gap=\"200\">\n <Text fontSize=\"350\" fontWeight=\"600\">Multiple selection</Text>\n <ToggleButtonGroup.Root selectionMode=\"multiple\" aria-label=\"Text formatting\">\n <ToggleButtonGroup.Button id=\"bold\" aria-label=\"Bold\">\n <Icons.FormatBold />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"italic\" aria-label=\"Italic\">\n <Icons.FormatItalic />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"underline\" aria-label=\"Underline\">\n <Icons.FormatUnderlined />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n </Stack>\n)\n```\n\nIn single-selection mode, selecting a button automatically deselects any previously selected button. In multi-selection mode, users can select multiple buttons independently.\n\n### Disabled state\n\nDisable the entire group or individual buttons:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <Stack direction=\"column\" gap=\"200\">\n <Text fontSize=\"350\" fontWeight=\"600\">Disabled group</Text>\n <ToggleButtonGroup.Root isDisabled aria-label=\"Disabled alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n\n <Stack direction=\"column\" gap=\"200\">\n <Text fontSize=\"350\" fontWeight=\"600\">Individual disabled buttons</Text>\n <ToggleButtonGroup.Root aria-label=\"Partial alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\" isDisabled>Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n </Stack>\n)\n```\n\n### Uncontrolled mode\n\nUse `defaultSelectedKeys` to set initial selection without managing state:\n\n```jsx live-dev\nconst App = () => {\n const handleSelectionChange = (keys) => {\n console.log('Selection changed:', Array.from(keys));\n };\n\n return (\n <ToggleButtonGroup.Root\n defaultSelectedKeys={['center']}\n onSelectionChange={handleSelectionChange}\n aria-label=\"Text alignment\"\n >\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n );\n}\n```\n\n### Controlled mode\n\nFor full control over selection state, use `selectedKeys` with `onSelectionChange`:\n\n```jsx live-dev\nconst App = () => {\n const [selectedKeys, setSelectedKeys] = React.useState(new Set(['left']));\n\n return (\n <Stack direction=\"column\" gap=\"300\">\n <ToggleButtonGroup.Root\n selectedKeys={selectedKeys}\n onSelectionChange={setSelectedKeys}\n aria-label=\"Text alignment\"\n >\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <Text fontSize=\"350\">\n Selected: {Array.from(selectedKeys).join(', ') || 'none'}\n </Text>\n </Stack>\n );\n}\n```\n\nIn controlled mode, the component's selection state is fully managed by your application. The `selectedKeys` prop accepts a `Set` containing the IDs of selected buttons.\n\n### Multi-selection with controlled state\n\nCombine `selectionMode=\"multiple\"` with controlled state for complex selection logic:\n\n```jsx live-dev\nconst App = () => {\n const [selectedFormats, setSelectedFormats] = React.useState(new Set([]));\n\n const formatNames = {\n bold: 'Bold',\n italic: 'Italic',\n underline: 'Underline'\n };\n\n const selectedList = Array.from(selectedFormats)\n .map(key => formatNames[key])\n .join(', ');\n\n return (\n <Stack direction=\"column\" gap=\"300\">\n <ToggleButtonGroup.Root\n selectionMode=\"multiple\"\n selectedKeys={selectedFormats}\n onSelectionChange={setSelectedFormats}\n aria-label=\"Text formatting\"\n >\n <ToggleButtonGroup.Button id=\"bold\" aria-label=\"Bold\">\n <Icons.FormatBold />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"italic\" aria-label=\"Italic\">\n <Icons.FormatItalic />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"underline\" aria-label=\"Underline\">\n <Icons.FormatUnderlined />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <Text fontSize=\"350\">\n Active formats: {selectedList || 'none'}\n </Text>\n </Stack>\n );\n}\n```\n\n## Component requirements\n\n## Accessibility\n\nThe ToggleButtonGroup component follows WCAG 2.1 AA guidelines and uses React Aria for robust accessibility support.\n\n#### Role\n\n- **Single-selection mode (default)**:\n - Root element has `role=\"radiogroup\"`\n - Each button has `role=\"radio\"`\n- **Multi-selection mode**:\n - Root element has `role=\"toolbar\"`\n - Each button has `role=\"button\"` with `aria-pressed` attribute\n\n#### Labeling\n\n- **Group label required**: Always provide an `aria-label` or `aria-labelledby` on the Root component\n- **Button labels**: Each button must have accessible text content or an `aria-label`\n- **Icon-only buttons**: Must include an `aria-label` on each button\n\n```jsx live-dev\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Text formatting options\">\n <ToggleButtonGroup.Button id=\"bold\" aria-label=\"Toggle bold\">\n <Icons.FormatBold />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"italic\" aria-label=\"Toggle italic\">\n <Icons.FormatItalic />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n)\n```\n\n#### Keyboard navigation\n\n| Key | Action |\n|-----|--------|\n| `Tab` | Move focus into/out of the button group |\n| `Arrow Left/Up` | Move focus to the previous button |\n| `Arrow Right/Down` | Move focus to the next button |\n| `Space` | Toggle the focused button's selection state |\n| `Home` | Move focus to the first button |\n| `End` | Move focus to the last button |\n\n#### Persistent ID\n\nIf your use case requires tracking and analytics for this component, it is good practice to add a **persistent**, **unique** id to the component:\n\n```tsx\nconst PERSISTENT_ID = \"text-alignment-toggle-group\";\n\nexport const Example = () => (\n <ToggleButtonGroup.Root id={PERSISTENT_ID} aria-label=\"Text alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n## API reference\n\n<PropsTable id=\"ToggleButtonGroup\" />\n\n## Common patterns\n\n### Text editor toolbar\n\nCombine multiple toggle button groups to create a rich text formatting toolbar:\n\n```jsx live-dev\nconst App = () => {\n const [alignment, setAlignment] = React.useState(new Set(['left']));\n const [formats, setFormats] = React.useState(new Set([]));\n\n return (\n <Stack direction=\"row\" gap=\"400\" alignItems=\"center\">\n <ToggleButtonGroup.Root\n selectionMode=\"multiple\"\n selectedKeys={formats}\n onSelectionChange={setFormats}\n size=\"xs\"\n aria-label=\"Text formatting\"\n >\n <ToggleButtonGroup.Button id=\"bold\" aria-label=\"Bold\">\n <Icons.FormatBold />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"italic\" aria-label=\"Italic\">\n <Icons.FormatItalic />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"underline\" aria-label=\"Underline\">\n <Icons.FormatUnderlined />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <Separator orientation=\"vertical\" height=\"6\" />\n\n <ToggleButtonGroup.Root\n selectedKeys={alignment}\n onSelectionChange={setAlignment}\n size=\"xs\"\n aria-label=\"Text alignment\"\n >\n <ToggleButtonGroup.Button id=\"left\" aria-label=\"Align left\">\n <Icons.FormatAlignLeft />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\" aria-label=\"Align center\">\n <Icons.FormatAlignCenter />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\" aria-label=\"Align right\">\n <Icons.FormatAlignRight />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n );\n}\n```\n\n### View mode selector\n\nUse toggle button groups to switch between different view modes:\n\n```jsx live-dev\nconst App = () => {\n const [viewMode, setViewMode] = React.useState(new Set(['grid']));\n\n const selectedMode = Array.from(viewMode)[0] || 'grid';\n\n return (\n <Stack direction=\"column\" gap=\"300\">\n <ToggleButtonGroup.Root\n selectedKeys={viewMode}\n onSelectionChange={setViewMode}\n aria-label=\"View mode\"\n >\n <ToggleButtonGroup.Button id=\"grid\" aria-label=\"Grid view\">\n <Icons.GridView />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"list\" aria-label=\"List view\">\n <Icons.ViewList />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"column\" aria-label=\"Column view\">\n <Icons.ViewColumn />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <Text fontSize=\"350\">Current view: {selectedMode}</Text>\n </Stack>\n );\n}\n```\n\n## Testing your implementation\n\nThese examples demonstrate how to test your implementation when using ToggleButtonGroup within your application. As the component's internal functionality is already tested by Nimbus, these patterns help you verify your integration and application-specific logic.\n\n### Basic Rendering Tests\n\nVerify the toggle button group renders with expected structure and accessibility attributes\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, within } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { ToggleButtonGroup, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"ToggleButtonGroup - Basic rendering\", () => {\n it(\"renders toggle button group with buttons\", () => {\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root aria-label=\"Text alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">\n Center\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const group = screen.getByRole(\"radiogroup\", { name: /text alignment/i });\n expect(group).toBeInTheDocument();\n\n const buttons = within(group).getAllByRole(\"radio\");\n expect(buttons).toHaveLength(3);\n expect(buttons[0]).toHaveTextContent(\"Left\");\n expect(buttons[1]).toHaveTextContent(\"Center\");\n expect(buttons[2]).toHaveTextContent(\"Right\");\n });\n\n it(\"renders with correct accessibility attributes\", () => {\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root aria-label=\"Formatting options\">\n <ToggleButtonGroup.Button id=\"bold\">Bold</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"italic\">\n Italic\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const group = screen.getByRole(\"radiogroup\", {\n name: /formatting options/i,\n });\n expect(group).toHaveAttribute(\"aria-label\", \"Formatting options\");\n });\n});\n```\n\n### Single Selection Tests\n\nTest single-selection mode behavior (default mode)\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, within } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { ToggleButtonGroup, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"ToggleButtonGroup - Single selection mode\", () => {\n it(\"allows selecting one button at a time\", async () => {\n const user = userEvent.setup();\n const handleChange = vi.fn();\n\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n onSelectionChange={handleChange}\n aria-label=\"Text alignment\"\n >\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">\n Center\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const buttons = screen.getAllByRole(\"radio\");\n const [leftButton, centerButton] = buttons;\n\n // Initially no buttons selected\n expect(leftButton).toHaveAttribute(\"aria-checked\", \"false\");\n expect(centerButton).toHaveAttribute(\"aria-checked\", \"false\");\n\n // Click first button\n await user.click(leftButton);\n expect(handleChange).toHaveBeenCalledWith(new Set([\"left\"]));\n\n // Click second button - should deselect first\n await user.click(centerButton);\n expect(handleChange).toHaveBeenCalledWith(new Set([\"center\"]));\n });\n\n it(\"supports toggling selection by clicking same button\", async () => {\n const user = userEvent.setup();\n const handleChange = vi.fn();\n\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n onSelectionChange={handleChange}\n aria-label=\"Options\"\n >\n <ToggleButtonGroup.Button id=\"option1\">\n Option 1\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const button = screen.getByRole(\"radio\");\n\n // Select\n await user.click(button);\n expect(handleChange).toHaveBeenCalledWith(new Set([\"option1\"]));\n\n // Deselect\n await user.click(button);\n expect(handleChange).toHaveBeenCalledWith(new Set());\n });\n});\n```\n\n### Multiple Selection Tests\n\nTest multi-selection mode behavior with selectionMode=\"multiple\"\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, within } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { ToggleButtonGroup, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"ToggleButtonGroup - Multiple selection mode\", () => {\n it(\"allows selecting multiple buttons independently\", async () => {\n const user = userEvent.setup();\n const handleChange = vi.fn();\n\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n selectionMode=\"multiple\"\n onSelectionChange={handleChange}\n aria-label=\"Text formatting\"\n >\n <ToggleButtonGroup.Button id=\"bold\">Bold</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"italic\">\n Italic\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"underline\">\n Underline\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const toolbar = screen.getByRole(\"toolbar\", { name: /text formatting/i });\n const buttons = within(toolbar).getAllByRole(\"button\");\n const [boldButton, italicButton] = buttons;\n\n // Select first button\n await user.click(boldButton);\n expect(handleChange).toHaveBeenCalledWith(new Set([\"bold\"]));\n\n handleChange.mockClear();\n\n // Select second button - first should remain selected\n await user.click(italicButton);\n expect(handleChange).toHaveBeenCalledWith(new Set([\"bold\", \"italic\"]));\n });\n});\n```\n\n### Keyboard Navigation Tests\n\nTest keyboard interactions and focus management\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, within } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { ToggleButtonGroup, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"ToggleButtonGroup - Keyboard navigation\", () => {\n it(\"supports arrow key navigation between buttons\", async () => {\n const user = userEvent.setup();\n\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root aria-label=\"Navigation\">\n <ToggleButtonGroup.Button id=\"first\">First</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"second\">\n Second\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"third\">Third</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const buttons = screen.getAllByRole(\"radio\");\n const [firstButton, secondButton, thirdButton] = buttons;\n\n // Tab to focus first button\n await user.tab();\n expect(firstButton).toHaveFocus();\n\n // Arrow right to second button\n await user.keyboard(\"{ArrowRight}\");\n expect(secondButton).toHaveFocus();\n\n // Arrow right to third button\n await user.keyboard(\"{ArrowRight}\");\n expect(thirdButton).toHaveFocus();\n\n // Arrow left back to second button\n await user.keyboard(\"{ArrowLeft}\");\n expect(secondButton).toHaveFocus();\n });\n\n it(\"supports Space key for toggling selection\", async () => {\n const user = userEvent.setup();\n const handleChange = vi.fn();\n\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n onSelectionChange={handleChange}\n aria-label=\"Options\"\n >\n <ToggleButtonGroup.Button id=\"option1\">\n Option 1\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"option2\">\n Option 2\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n // Tab to focus first button\n await user.tab();\n\n // Press Space to select\n await user.keyboard(\" \");\n expect(handleChange).toHaveBeenCalledWith(new Set([\"option1\"]));\n\n handleChange.mockClear();\n\n // Navigate to second button\n await user.keyboard(\"{ArrowRight}\");\n\n // Press Space to select second\n await user.keyboard(\" \");\n expect(handleChange).toHaveBeenCalledWith(new Set([\"option2\"]));\n });\n});\n```\n\n### Disabled State Tests\n\nTest behavior when group or individual buttons are disabled\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, within } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { ToggleButtonGroup, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"ToggleButtonGroup - Disabled state\", () => {\n it(\"disables entire group when isDisabled is true\", async () => {\n const user = userEvent.setup();\n const handleChange = vi.fn();\n\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n isDisabled\n onSelectionChange={handleChange}\n aria-label=\"Disabled group\"\n >\n <ToggleButtonGroup.Button id=\"option1\">\n Option 1\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"option2\">\n Option 2\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const buttons = screen.getAllByRole(\"radio\");\n\n // All buttons should be disabled\n buttons.forEach((button) => {\n expect(button).toBeDisabled();\n });\n\n // Clicking disabled button should not trigger change\n await user.click(buttons[0]);\n expect(handleChange).not.toHaveBeenCalled();\n });\n\n it(\"disables individual buttons\", async () => {\n const user = userEvent.setup();\n const handleChange = vi.fn();\n\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n onSelectionChange={handleChange}\n aria-label=\"Partial disabled\"\n >\n <ToggleButtonGroup.Button id=\"enabled\">\n Enabled\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"disabled\" isDisabled>\n Disabled\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const buttons = screen.getAllByRole(\"radio\");\n const [enabledButton, disabledButton] = buttons;\n\n expect(enabledButton).not.toBeDisabled();\n expect(disabledButton).toBeDisabled();\n\n // Click enabled button works\n await user.click(enabledButton);\n expect(handleChange).toHaveBeenCalledWith(new Set([\"enabled\"]));\n\n handleChange.mockClear();\n\n // Click disabled button does not work\n await user.click(disabledButton);\n expect(handleChange).not.toHaveBeenCalled();\n });\n});\n```\n\n### Controlled Mode Tests\n\nTest controlled selection state with selectedKeys prop\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, within } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { ToggleButtonGroup, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"ToggleButtonGroup - Controlled mode\", () => {\n it(\"respects controlled selectedKeys prop\", () => {\n const { rerender } = render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n selectedKeys={new Set([\"center\"])}\n aria-label=\"Controlled\"\n >\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">\n Center\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const buttons = screen.getAllByRole(\"radio\");\n const [leftButton, centerButton, rightButton] = buttons;\n\n // Center button should be selected\n expect(leftButton).toHaveAttribute(\"aria-checked\", \"false\");\n expect(centerButton).toHaveAttribute(\"aria-checked\", \"true\");\n expect(rightButton).toHaveAttribute(\"aria-checked\", \"false\");\n\n // Update selection externally\n rerender(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n selectedKeys={new Set([\"right\"])}\n aria-label=\"Controlled\"\n >\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">\n Center\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n // Right button should now be selected\n expect(leftButton).toHaveAttribute(\"aria-checked\", \"false\");\n expect(centerButton).toHaveAttribute(\"aria-checked\", \"false\");\n expect(rightButton).toHaveAttribute(\"aria-checked\", \"true\");\n });\n\n it(\"calls onSelectionChange with updated selection\", async () => {\n const user = userEvent.setup();\n const handleChange = vi.fn();\n\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n selectedKeys={new Set([\"left\"])}\n onSelectionChange={handleChange}\n aria-label=\"Controlled with callback\"\n >\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">\n Center\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const buttons = screen.getAllByRole(\"radio\");\n const centerButton = buttons[1];\n\n await user.click(centerButton);\n expect(handleChange).toHaveBeenCalledWith(new Set([\"center\"]));\n });\n});\n```\n\n### Uncontrolled Mode Tests\n\nTest uncontrolled selection with defaultSelectedKeys prop\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, within } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { ToggleButtonGroup, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"ToggleButtonGroup - Uncontrolled mode\", () => {\n it(\"respects defaultSelectedKeys for initial selection\", () => {\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n defaultSelectedKeys={[\"center\"]}\n aria-label=\"Uncontrolled\"\n >\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">\n Center\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const buttons = screen.getAllByRole(\"radio\");\n const [leftButton, centerButton, rightButton] = buttons;\n\n expect(leftButton).toHaveAttribute(\"aria-checked\", \"false\");\n expect(centerButton).toHaveAttribute(\"aria-checked\", \"true\");\n expect(rightButton).toHaveAttribute(\"aria-checked\", \"false\");\n });\n\n it(\"manages selection state internally\", async () => {\n const user = userEvent.setup();\n const handleChange = vi.fn();\n\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n defaultSelectedKeys={[\"left\"]}\n onSelectionChange={handleChange}\n aria-label=\"Uncontrolled internal\"\n >\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">\n Center\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const buttons = screen.getAllByRole(\"radio\");\n const centerButton = buttons[1];\n\n // Click center button\n await user.click(centerButton);\n\n // Callback should be called with new selection\n expect(handleChange).toHaveBeenCalledWith(new Set([\"center\"]));\n\n // Component should update its own internal state\n expect(centerButton).toHaveAttribute(\"aria-checked\", \"true\");\n });\n});\n```\n\n\n## Resources\n\n- [Storybook](https://nimbus-storybook.vercel.app/?path=/docs/components-buttons-togglebuttongroup--docs)\n- [React Aria ToggleButton](https://react-spectrum.adobe.com/react-aria/ToggleButton.html)\n- [ARIA: radio role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/radio_role)\n",
|
|
413
|
+
"mdx": "\n## Getting started\n\n### Import\n\n```tsx\nimport { ToggleButtonGroup, type ToggleButtonGroupProps } from '@commercetools/nimbus';\n```\n\n### Basic usage\n\nThe ToggleButtonGroup component groups multiple toggle buttons together, allowing users to select one or more options from a set of related choices. It uses a compound component structure with `Root` and `Button` sub-components:\n\n```jsx live-dev\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Text alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n)\n```\n\nBy default, the group operates in single-selection mode where only one button can be selected at a time. Each button must have a unique `id` prop that identifies it within the group.\n\n`ToggleButtonGroup.Button` is the standard [`ToggleButton`](/components/buttons/togglebutton) exposed under the compound name. It inherits the group's `variant`, `activeFillStyle`, `size`, and `colorPalette`, and you can override any of them on a single button (see [Overriding individual buttons](#overriding-individual-buttons)).\n\n## Usage examples\n\n### Size options\n\nThe component supports five size variants (`2xs`, `xs`, `sm`, `md`, `xl`) to\nmatch your interface density — the same scale as `Button` and `ToggleButton`:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <ToggleButtonGroup.Root size=\"2xs\" aria-label=\"2x small text alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <ToggleButtonGroup.Root size=\"xs\" aria-label=\"Extra small text alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <ToggleButtonGroup.Root size=\"sm\" aria-label=\"Small text alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <ToggleButtonGroup.Root size=\"md\" aria-label=\"Medium text alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <ToggleButtonGroup.Root size=\"xl\" aria-label=\"Extra large text alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n)\n```\n\n### Variant\n\n`variant` sets the resting chrome shared by every button in the group. The group\nrenders segmented (buttons sit flush with shared borders) regardless of variant.\n\n- `outline` (default): a neutral segmented bar.\n- `subtle`: filled neutral segments.\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <ToggleButtonGroup.Root variant=\"outline\" defaultSelectedKeys={[\"center\"]} aria-label=\"Outline alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <ToggleButtonGroup.Root variant=\"subtle\" defaultSelectedKeys={[\"center\"]} aria-label=\"Subtle alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n)\n```\n\n### Active fill style\n\n`activeFillStyle` sets the weight of the selected fill for the buttons. Its\ndefault follows `selectionMode`: **single** selection defaults to `solid` (one\nchoice stands out), **multiple** selection defaults to `tint` (several can be on\nat once). Set it explicitly to override that default.\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <Stack direction=\"column\" gap=\"200\">\n <Text fontSize=\"350\" fontWeight=\"600\">Single selection → solid (default)</Text>\n <ToggleButtonGroup.Root colorPalette=\"primary\" defaultSelectedKeys={[\"center\"]} aria-label=\"Solid alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n\n <Stack direction=\"column\" gap=\"200\">\n <Text fontSize=\"350\" fontWeight=\"600\">Multiple selection → tint (default)</Text>\n <ToggleButtonGroup.Root selectionMode=\"multiple\" colorPalette=\"primary\" defaultSelectedKeys={[\"bold\", \"italic\"]} aria-label=\"Tint formatting\">\n <ToggleButtonGroup.Button id=\"bold\">Bold</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"italic\">Italic</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"underline\">Underline</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n </Stack>\n)\n```\n\n### Color palettes\n\nChoose from semantic color palettes to match your design context. As with a\nstandalone toggle button, the resting group is neutral — `colorPalette` tints the\nactive (selected) segments:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <ToggleButtonGroup.Root colorPalette=\"primary\" aria-label=\"Primary alignment\">\n <ToggleButtonGroup.Button id=\"left\">\n <Icons.FormatAlignLeft />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">\n <Icons.FormatAlignCenter />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">\n <Icons.FormatAlignRight />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <ToggleButtonGroup.Root colorPalette=\"critical\" aria-label=\"Critical actions\">\n <ToggleButtonGroup.Button id=\"delete\">\n <Icons.Delete />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"warning\">\n <Icons.Warning />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"block\">\n <Icons.Block />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <ToggleButtonGroup.Root colorPalette=\"neutral\" aria-label=\"Neutral formatting\">\n <ToggleButtonGroup.Button id=\"bold\">\n <Icons.FormatBold />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"italic\">\n <Icons.FormatItalic />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"underline\">\n <Icons.FormatUnderlined />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n)\n```\n\n### Overriding individual buttons\n\nBecause each `ToggleButtonGroup.Button` is a full `ToggleButton`, any prop set on\na single button overrides the value inherited from the group. This is useful for\ndrawing attention to a destructive or primary option within an otherwise uniform\ngroup:\n\n```jsx live-dev\nconst App = () => (\n <ToggleButtonGroup.Root colorPalette=\"primary\" defaultSelectedKeys={[\"keep\"]} aria-label=\"Row action\">\n <ToggleButtonGroup.Button id=\"keep\">Keep</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"archive\">Archive</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"delete\" colorPalette=\"critical\">\n Delete\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n)\n```\n\n### With icons\n\nIcons can be used alone or combined with text labels:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <ToggleButtonGroup.Root aria-label=\"Icon-only formatting\">\n <ToggleButtonGroup.Button id=\"bold\" aria-label=\"Bold\">\n <Icons.FormatBold />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"italic\" aria-label=\"Italic\">\n <Icons.FormatItalic />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"underline\" aria-label=\"Underline\">\n <Icons.FormatUnderlined />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <ToggleButtonGroup.Root aria-label=\"Text alignment with labels\">\n <ToggleButtonGroup.Button id=\"left\">\n <Icons.FormatAlignLeft /> Left\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">\n <Icons.FormatAlignCenter /> Center\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">\n <Icons.FormatAlignRight /> Right\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n)\n```\n\nWhen using icon-only buttons, always provide an `aria-label` on each button for screen reader accessibility.\n\n### Selection modes\n\nThe group supports both single-selection (default) and multi-selection modes:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <Stack direction=\"column\" gap=\"200\">\n <Text fontSize=\"350\" fontWeight=\"600\">Single selection (default)</Text>\n <ToggleButtonGroup.Root aria-label=\"Text alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n\n <Stack direction=\"column\" gap=\"200\">\n <Text fontSize=\"350\" fontWeight=\"600\">Multiple selection</Text>\n <ToggleButtonGroup.Root selectionMode=\"multiple\" aria-label=\"Text formatting\">\n <ToggleButtonGroup.Button id=\"bold\" aria-label=\"Bold\">\n <Icons.FormatBold />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"italic\" aria-label=\"Italic\">\n <Icons.FormatItalic />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"underline\" aria-label=\"Underline\">\n <Icons.FormatUnderlined />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n </Stack>\n)\n```\n\nIn single-selection mode, selecting a button automatically deselects any previously selected button. In multi-selection mode, users can select multiple buttons independently.\n\n### Disabled state\n\nDisable the entire group or individual buttons:\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <Stack direction=\"column\" gap=\"200\">\n <Text fontSize=\"350\" fontWeight=\"600\">Disabled group</Text>\n <ToggleButtonGroup.Root isDisabled aria-label=\"Disabled alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n\n <Stack direction=\"column\" gap=\"200\">\n <Text fontSize=\"350\" fontWeight=\"600\">Individual disabled buttons</Text>\n <ToggleButtonGroup.Root aria-label=\"Partial alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\" isDisabled>Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n </Stack>\n)\n```\n\n### Uncontrolled mode\n\nUse `defaultSelectedKeys` to set initial selection without managing state:\n\n```jsx live-dev\nconst App = () => {\n const handleSelectionChange = (keys) => {\n console.log('Selection changed:', Array.from(keys));\n };\n\n return (\n <ToggleButtonGroup.Root\n defaultSelectedKeys={['center']}\n onSelectionChange={handleSelectionChange}\n aria-label=\"Text alignment\"\n >\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n );\n}\n```\n\n### Controlled mode\n\nFor full control over selection state, use `selectedKeys` with `onSelectionChange`:\n\n```jsx live-dev\nconst App = () => {\n const [selectedKeys, setSelectedKeys] = React.useState(new Set(['left']));\n\n return (\n <Stack direction=\"column\" gap=\"300\">\n <ToggleButtonGroup.Root\n selectedKeys={selectedKeys}\n onSelectionChange={setSelectedKeys}\n aria-label=\"Text alignment\"\n >\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <Text fontSize=\"350\">\n Selected: {Array.from(selectedKeys).join(', ') || 'none'}\n </Text>\n </Stack>\n );\n}\n```\n\nIn controlled mode, the component's selection state is fully managed by your application. The `selectedKeys` prop accepts a `Set` containing the IDs of selected buttons.\n\n### Multi-selection with controlled state\n\nCombine `selectionMode=\"multiple\"` with controlled state for complex selection logic:\n\n```jsx live-dev\nconst App = () => {\n const [selectedFormats, setSelectedFormats] = React.useState(new Set([]));\n\n const formatNames = {\n bold: 'Bold',\n italic: 'Italic',\n underline: 'Underline'\n };\n\n const selectedList = Array.from(selectedFormats)\n .map(key => formatNames[key])\n .join(', ');\n\n return (\n <Stack direction=\"column\" gap=\"300\">\n <ToggleButtonGroup.Root\n selectionMode=\"multiple\"\n selectedKeys={selectedFormats}\n onSelectionChange={setSelectedFormats}\n aria-label=\"Text formatting\"\n >\n <ToggleButtonGroup.Button id=\"bold\" aria-label=\"Bold\">\n <Icons.FormatBold />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"italic\" aria-label=\"Italic\">\n <Icons.FormatItalic />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"underline\" aria-label=\"Underline\">\n <Icons.FormatUnderlined />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <Text fontSize=\"350\">\n Active formats: {selectedList || 'none'}\n </Text>\n </Stack>\n );\n}\n```\n\n## Component requirements\n\n## Accessibility\n\nThe ToggleButtonGroup component follows WCAG 2.1 AA guidelines and uses React Aria for robust accessibility support.\n\n#### Role\n\n- **Single-selection mode (default)**:\n - Root element has `role=\"radiogroup\"`\n - Each button has `role=\"radio\"`\n- **Multi-selection mode**:\n - Root element has `role=\"toolbar\"`\n - Each button has `role=\"button\"` with `aria-pressed` attribute\n\n#### Labeling\n\n- **Group label required**: Always provide an `aria-label` or `aria-labelledby` on the Root component\n- **Button labels**: Each button must have accessible text content or an `aria-label`\n- **Icon-only buttons**: Must include an `aria-label` on each button\n\n```jsx live-dev\nconst App = () => (\n <ToggleButtonGroup.Root aria-label=\"Text formatting options\">\n <ToggleButtonGroup.Button id=\"bold\" aria-label=\"Toggle bold\">\n <Icons.FormatBold />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"italic\" aria-label=\"Toggle italic\">\n <Icons.FormatItalic />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n)\n```\n\n#### Keyboard navigation\n\n| Key | Action |\n|-----|--------|\n| `Tab` | Move focus into/out of the button group |\n| `Arrow Left/Up` | Move focus to the previous button |\n| `Arrow Right/Down` | Move focus to the next button |\n| `Space` | Toggle the focused button's selection state |\n| `Home` | Move focus to the first button |\n| `End` | Move focus to the last button |\n\n#### Persistent ID\n\nIf your use case requires tracking and analytics for this component, it is good practice to add a **persistent**, **unique** id to the component:\n\n```tsx\nconst PERSISTENT_ID = \"text-alignment-toggle-group\";\n\nexport const Example = () => (\n <ToggleButtonGroup.Root id={PERSISTENT_ID} aria-label=\"Text alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">Center</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n);\n```\n\n## API reference\n\n<PropsTable id=\"ToggleButtonGroup\" />\n\n## Common patterns\n\n### Text editor toolbar\n\nCombine multiple toggle button groups to create a rich text formatting toolbar:\n\n```jsx live-dev\nconst App = () => {\n const [alignment, setAlignment] = React.useState(new Set(['left']));\n const [formats, setFormats] = React.useState(new Set([]));\n\n return (\n <Stack direction=\"row\" gap=\"400\" alignItems=\"center\">\n <ToggleButtonGroup.Root\n selectionMode=\"multiple\"\n selectedKeys={formats}\n onSelectionChange={setFormats}\n size=\"xs\"\n aria-label=\"Text formatting\"\n >\n <ToggleButtonGroup.Button id=\"bold\" aria-label=\"Bold\">\n <Icons.FormatBold />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"italic\" aria-label=\"Italic\">\n <Icons.FormatItalic />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"underline\" aria-label=\"Underline\">\n <Icons.FormatUnderlined />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <Separator orientation=\"vertical\" height=\"6\" />\n\n <ToggleButtonGroup.Root\n selectedKeys={alignment}\n onSelectionChange={setAlignment}\n size=\"xs\"\n aria-label=\"Text alignment\"\n >\n <ToggleButtonGroup.Button id=\"left\" aria-label=\"Align left\">\n <Icons.FormatAlignLeft />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\" aria-label=\"Align center\">\n <Icons.FormatAlignCenter />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\" aria-label=\"Align right\">\n <Icons.FormatAlignRight />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </Stack>\n );\n}\n```\n\n### View mode selector\n\nUse toggle button groups to switch between different view modes:\n\n```jsx live-dev\nconst App = () => {\n const [viewMode, setViewMode] = React.useState(new Set(['grid']));\n\n const selectedMode = Array.from(viewMode)[0] || 'grid';\n\n return (\n <Stack direction=\"column\" gap=\"300\">\n <ToggleButtonGroup.Root\n selectedKeys={viewMode}\n onSelectionChange={setViewMode}\n aria-label=\"View mode\"\n >\n <ToggleButtonGroup.Button id=\"grid\" aria-label=\"Grid view\">\n <Icons.GridView />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"list\" aria-label=\"List view\">\n <Icons.ViewList />\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"column\" aria-label=\"Column view\">\n <Icons.ViewColumn />\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n\n <Text fontSize=\"350\">Current view: {selectedMode}</Text>\n </Stack>\n );\n}\n```\n\n## Testing your implementation\n\nThese examples demonstrate how to test your implementation when using ToggleButtonGroup within your application. As the component's internal functionality is already tested by Nimbus, these patterns help you verify your integration and application-specific logic.\n\n### Basic Rendering Tests\n\nVerify the toggle button group renders with expected structure and accessibility attributes\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, within } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { ToggleButtonGroup, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"ToggleButtonGroup - Basic rendering\", () => {\n it(\"renders toggle button group with buttons\", () => {\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root aria-label=\"Text alignment\">\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">\n Center\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const group = screen.getByRole(\"radiogroup\", { name: /text alignment/i });\n expect(group).toBeInTheDocument();\n\n const buttons = within(group).getAllByRole(\"radio\");\n expect(buttons).toHaveLength(3);\n expect(buttons[0]).toHaveTextContent(\"Left\");\n expect(buttons[1]).toHaveTextContent(\"Center\");\n expect(buttons[2]).toHaveTextContent(\"Right\");\n });\n\n it(\"renders with correct accessibility attributes\", () => {\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root aria-label=\"Formatting options\">\n <ToggleButtonGroup.Button id=\"bold\">Bold</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"italic\">\n Italic\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const group = screen.getByRole(\"radiogroup\", {\n name: /formatting options/i,\n });\n expect(group).toHaveAttribute(\"aria-label\", \"Formatting options\");\n });\n});\n```\n\n### Single Selection Tests\n\nTest single-selection mode behavior (default mode)\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, within } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { ToggleButtonGroup, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"ToggleButtonGroup - Single selection mode\", () => {\n it(\"allows selecting one button at a time\", async () => {\n const user = userEvent.setup();\n const handleChange = vi.fn();\n\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n onSelectionChange={handleChange}\n aria-label=\"Text alignment\"\n >\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">\n Center\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const buttons = screen.getAllByRole(\"radio\");\n const [leftButton, centerButton] = buttons;\n\n // Initially no buttons selected\n expect(leftButton).toHaveAttribute(\"aria-checked\", \"false\");\n expect(centerButton).toHaveAttribute(\"aria-checked\", \"false\");\n\n // Click first button\n await user.click(leftButton);\n expect(handleChange).toHaveBeenCalledWith(new Set([\"left\"]));\n\n // Click second button - should deselect first\n await user.click(centerButton);\n expect(handleChange).toHaveBeenCalledWith(new Set([\"center\"]));\n });\n\n it(\"supports toggling selection by clicking same button\", async () => {\n const user = userEvent.setup();\n const handleChange = vi.fn();\n\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n onSelectionChange={handleChange}\n aria-label=\"Options\"\n >\n <ToggleButtonGroup.Button id=\"option1\">\n Option 1\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const button = screen.getByRole(\"radio\");\n\n // Select\n await user.click(button);\n expect(handleChange).toHaveBeenCalledWith(new Set([\"option1\"]));\n\n // Deselect\n await user.click(button);\n expect(handleChange).toHaveBeenCalledWith(new Set());\n });\n});\n```\n\n### Multiple Selection Tests\n\nTest multi-selection mode behavior with selectionMode=\"multiple\"\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, within } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { ToggleButtonGroup, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"ToggleButtonGroup - Multiple selection mode\", () => {\n it(\"allows selecting multiple buttons independently\", async () => {\n const user = userEvent.setup();\n const handleChange = vi.fn();\n\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n selectionMode=\"multiple\"\n onSelectionChange={handleChange}\n aria-label=\"Text formatting\"\n >\n <ToggleButtonGroup.Button id=\"bold\">Bold</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"italic\">\n Italic\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"underline\">\n Underline\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const toolbar = screen.getByRole(\"toolbar\", { name: /text formatting/i });\n const buttons = within(toolbar).getAllByRole(\"button\");\n const [boldButton, italicButton] = buttons;\n\n // Select first button\n await user.click(boldButton);\n expect(handleChange).toHaveBeenCalledWith(new Set([\"bold\"]));\n\n handleChange.mockClear();\n\n // Select second button - first should remain selected\n await user.click(italicButton);\n expect(handleChange).toHaveBeenCalledWith(new Set([\"bold\", \"italic\"]));\n });\n});\n```\n\n### Keyboard Navigation Tests\n\nTest keyboard interactions and focus management\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, within } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { ToggleButtonGroup, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"ToggleButtonGroup - Keyboard navigation\", () => {\n it(\"supports arrow key navigation between buttons\", async () => {\n const user = userEvent.setup();\n\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root aria-label=\"Navigation\">\n <ToggleButtonGroup.Button id=\"first\">First</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"second\">\n Second\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"third\">Third</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const buttons = screen.getAllByRole(\"radio\");\n const [firstButton, secondButton, thirdButton] = buttons;\n\n // Tab to focus first button\n await user.tab();\n expect(firstButton).toHaveFocus();\n\n // Arrow right to second button\n await user.keyboard(\"{ArrowRight}\");\n expect(secondButton).toHaveFocus();\n\n // Arrow right to third button\n await user.keyboard(\"{ArrowRight}\");\n expect(thirdButton).toHaveFocus();\n\n // Arrow left back to second button\n await user.keyboard(\"{ArrowLeft}\");\n expect(secondButton).toHaveFocus();\n });\n\n it(\"supports Space key for toggling selection\", async () => {\n const user = userEvent.setup();\n const handleChange = vi.fn();\n\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n onSelectionChange={handleChange}\n aria-label=\"Options\"\n >\n <ToggleButtonGroup.Button id=\"option1\">\n Option 1\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"option2\">\n Option 2\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n // Tab to focus first button\n await user.tab();\n\n // Press Space to select\n await user.keyboard(\" \");\n expect(handleChange).toHaveBeenCalledWith(new Set([\"option1\"]));\n\n handleChange.mockClear();\n\n // Navigate to second button\n await user.keyboard(\"{ArrowRight}\");\n\n // Press Space to select second\n await user.keyboard(\" \");\n expect(handleChange).toHaveBeenCalledWith(new Set([\"option2\"]));\n });\n});\n```\n\n### Disabled State Tests\n\nTest behavior when group or individual buttons are disabled\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, within } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { ToggleButtonGroup, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"ToggleButtonGroup - Disabled state\", () => {\n it(\"disables entire group when isDisabled is true\", async () => {\n const user = userEvent.setup();\n const handleChange = vi.fn();\n\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n isDisabled\n onSelectionChange={handleChange}\n aria-label=\"Disabled group\"\n >\n <ToggleButtonGroup.Button id=\"option1\">\n Option 1\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"option2\">\n Option 2\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const buttons = screen.getAllByRole(\"radio\");\n\n // All buttons should be disabled\n buttons.forEach((button) => {\n expect(button).toBeDisabled();\n });\n\n // Clicking disabled button should not trigger change\n await user.click(buttons[0]);\n expect(handleChange).not.toHaveBeenCalled();\n });\n\n it(\"disables individual buttons\", async () => {\n const user = userEvent.setup();\n const handleChange = vi.fn();\n\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n onSelectionChange={handleChange}\n aria-label=\"Partial disabled\"\n >\n <ToggleButtonGroup.Button id=\"enabled\">\n Enabled\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"disabled\" isDisabled>\n Disabled\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const buttons = screen.getAllByRole(\"radio\");\n const [enabledButton, disabledButton] = buttons;\n\n expect(enabledButton).not.toBeDisabled();\n expect(disabledButton).toBeDisabled();\n\n // Click enabled button works\n await user.click(enabledButton);\n expect(handleChange).toHaveBeenCalledWith(new Set([\"enabled\"]));\n\n handleChange.mockClear();\n\n // Click disabled button does not work\n await user.click(disabledButton);\n expect(handleChange).not.toHaveBeenCalled();\n });\n});\n```\n\n### Controlled Mode Tests\n\nTest controlled selection state with selectedKeys prop\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, within } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { ToggleButtonGroup, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"ToggleButtonGroup - Controlled mode\", () => {\n it(\"respects controlled selectedKeys prop\", () => {\n const { rerender } = render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n selectedKeys={new Set([\"center\"])}\n aria-label=\"Controlled\"\n >\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">\n Center\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const buttons = screen.getAllByRole(\"radio\");\n const [leftButton, centerButton, rightButton] = buttons;\n\n // Center button should be selected\n expect(leftButton).toHaveAttribute(\"aria-checked\", \"false\");\n expect(centerButton).toHaveAttribute(\"aria-checked\", \"true\");\n expect(rightButton).toHaveAttribute(\"aria-checked\", \"false\");\n\n // Update selection externally\n rerender(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n selectedKeys={new Set([\"right\"])}\n aria-label=\"Controlled\"\n >\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">\n Center\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n // Right button should now be selected\n expect(leftButton).toHaveAttribute(\"aria-checked\", \"false\");\n expect(centerButton).toHaveAttribute(\"aria-checked\", \"false\");\n expect(rightButton).toHaveAttribute(\"aria-checked\", \"true\");\n });\n\n it(\"calls onSelectionChange with updated selection\", async () => {\n const user = userEvent.setup();\n const handleChange = vi.fn();\n\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n selectedKeys={new Set([\"left\"])}\n onSelectionChange={handleChange}\n aria-label=\"Controlled with callback\"\n >\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">\n Center\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const buttons = screen.getAllByRole(\"radio\");\n const centerButton = buttons[1];\n\n await user.click(centerButton);\n expect(handleChange).toHaveBeenCalledWith(new Set([\"center\"]));\n });\n});\n```\n\n### Uncontrolled Mode Tests\n\nTest uncontrolled selection with defaultSelectedKeys prop\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, within } from \"@testing-library/react\";\nimport userEvent from \"@testing-library/user-event\";\nimport { ToggleButtonGroup, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"ToggleButtonGroup - Uncontrolled mode\", () => {\n it(\"respects defaultSelectedKeys for initial selection\", () => {\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n defaultSelectedKeys={[\"center\"]}\n aria-label=\"Uncontrolled\"\n >\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">\n Center\n </ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"right\">Right</ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const buttons = screen.getAllByRole(\"radio\");\n const [leftButton, centerButton, rightButton] = buttons;\n\n expect(leftButton).toHaveAttribute(\"aria-checked\", \"false\");\n expect(centerButton).toHaveAttribute(\"aria-checked\", \"true\");\n expect(rightButton).toHaveAttribute(\"aria-checked\", \"false\");\n });\n\n it(\"manages selection state internally\", async () => {\n const user = userEvent.setup();\n const handleChange = vi.fn();\n\n render(\n <NimbusProvider>\n <ToggleButtonGroup.Root\n defaultSelectedKeys={[\"left\"]}\n onSelectionChange={handleChange}\n aria-label=\"Uncontrolled internal\"\n >\n <ToggleButtonGroup.Button id=\"left\">Left</ToggleButtonGroup.Button>\n <ToggleButtonGroup.Button id=\"center\">\n Center\n </ToggleButtonGroup.Button>\n </ToggleButtonGroup.Root>\n </NimbusProvider>\n );\n\n const buttons = screen.getAllByRole(\"radio\");\n const centerButton = buttons[1];\n\n // Click center button\n await user.click(centerButton);\n\n // Callback should be called with new selection\n expect(handleChange).toHaveBeenCalledWith(new Set([\"center\"]));\n\n // Component should update its own internal state\n expect(centerButton).toHaveAttribute(\"aria-checked\", \"true\");\n });\n});\n```\n\n\n## Resources\n\n- [Storybook](https://nimbus-storybook.vercel.app/?path=/docs/components-buttons-togglebuttongroup--docs)\n- [React Aria ToggleButton](https://react-spectrum.adobe.com/react-aria/ToggleButton.html)\n- [ARIA: radio role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/radio_role)\n",
|
|
322
414
|
"toc": [
|
|
323
415
|
{
|
|
324
416
|
"value": "Getting started",
|
|
@@ -373,6 +465,28 @@
|
|
|
373
465
|
],
|
|
374
466
|
"parent": "root"
|
|
375
467
|
},
|
|
468
|
+
{
|
|
469
|
+
"value": "Variant",
|
|
470
|
+
"href": "#variant",
|
|
471
|
+
"depth": 3,
|
|
472
|
+
"numbering": [
|
|
473
|
+
1,
|
|
474
|
+
2,
|
|
475
|
+
2
|
|
476
|
+
],
|
|
477
|
+
"parent": "root"
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
"value": "Active fill style",
|
|
481
|
+
"href": "#active-fill-style",
|
|
482
|
+
"depth": 3,
|
|
483
|
+
"numbering": [
|
|
484
|
+
1,
|
|
485
|
+
2,
|
|
486
|
+
3
|
|
487
|
+
],
|
|
488
|
+
"parent": "root"
|
|
489
|
+
},
|
|
376
490
|
{
|
|
377
491
|
"value": "Color palettes",
|
|
378
492
|
"href": "#color-palettes",
|
|
@@ -380,7 +494,18 @@
|
|
|
380
494
|
"numbering": [
|
|
381
495
|
1,
|
|
382
496
|
2,
|
|
383
|
-
|
|
497
|
+
4
|
|
498
|
+
],
|
|
499
|
+
"parent": "root"
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
"value": "Overriding individual buttons",
|
|
503
|
+
"href": "#overriding-individual-buttons",
|
|
504
|
+
"depth": 3,
|
|
505
|
+
"numbering": [
|
|
506
|
+
1,
|
|
507
|
+
2,
|
|
508
|
+
5
|
|
384
509
|
],
|
|
385
510
|
"parent": "root"
|
|
386
511
|
},
|
|
@@ -391,7 +516,7 @@
|
|
|
391
516
|
"numbering": [
|
|
392
517
|
1,
|
|
393
518
|
2,
|
|
394
|
-
|
|
519
|
+
6
|
|
395
520
|
],
|
|
396
521
|
"parent": "root"
|
|
397
522
|
},
|
|
@@ -402,7 +527,7 @@
|
|
|
402
527
|
"numbering": [
|
|
403
528
|
1,
|
|
404
529
|
2,
|
|
405
|
-
|
|
530
|
+
7
|
|
406
531
|
],
|
|
407
532
|
"parent": "root"
|
|
408
533
|
},
|
|
@@ -413,7 +538,7 @@
|
|
|
413
538
|
"numbering": [
|
|
414
539
|
1,
|
|
415
540
|
2,
|
|
416
|
-
|
|
541
|
+
8
|
|
417
542
|
],
|
|
418
543
|
"parent": "root"
|
|
419
544
|
},
|
|
@@ -424,7 +549,7 @@
|
|
|
424
549
|
"numbering": [
|
|
425
550
|
1,
|
|
426
551
|
2,
|
|
427
|
-
|
|
552
|
+
9
|
|
428
553
|
],
|
|
429
554
|
"parent": "root"
|
|
430
555
|
},
|
|
@@ -435,7 +560,7 @@
|
|
|
435
560
|
"numbering": [
|
|
436
561
|
1,
|
|
437
562
|
2,
|
|
438
|
-
|
|
563
|
+
10
|
|
439
564
|
],
|
|
440
565
|
"parent": "root"
|
|
441
566
|
},
|
|
@@ -446,7 +571,7 @@
|
|
|
446
571
|
"numbering": [
|
|
447
572
|
1,
|
|
448
573
|
2,
|
|
449
|
-
|
|
574
|
+
11
|
|
450
575
|
],
|
|
451
576
|
"parent": "root"
|
|
452
577
|
},
|