@commercetools/nimbus-mcp 2.11.0 → 3.1.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 +1421 -605
- package/data/docs/routes/components-data-display-card.json +71 -5
- package/data/docs/routes/components-data-display-data-table.json +66 -34
- package/data/docs/routes/components-data-display-draggable-list.json +62 -7
- package/data/docs/routes/components-feedback-toast.json +1 -1
- package/data/docs/routes/components-inputs-checkbox.json +2 -2
- package/data/docs/routes/components-layout-defaultpage.json +4 -4
- package/data/docs/routes/components-layout-modalpage.json +4 -4
- package/data/docs/routes/components-layout-scrollarea.json +3 -3
- package/data/docs/routes/components-layout-splitter.json +654 -0
- package/data/docs/routes/components-media-avatar.json +24 -2
- package/data/docs/routes/components-utilities-region.json +265 -0
- package/data/docs/routes/home-getting-started-bundler-plugins.json +248 -0
- package/data/docs/routes/hooks-usedraganddrop.json +310 -0
- package/data/docs/routes/patterns-actions-form-action-bar.json +412 -0
- package/data/docs/routes/patterns-actions.json +78 -0
- package/data/docs/routes/patterns-dialogs-confirmation-dialog.json +391 -0
- package/data/docs/routes/patterns-dialogs-form-dialog.json +358 -0
- package/data/docs/routes/patterns-dialogs-info-dialog.json +315 -0
- package/data/docs/routes/patterns-dialogs.json +78 -0
- package/data/docs/routes/patterns-pages-public-page-layout.json +371 -0
- package/data/docs/routes/patterns-pages.json +78 -0
- package/data/docs/search-index.json +1 -1
- package/data/docs/types/AccordionContent.json +32 -32
- package/data/docs/types/AccordionHeader.json +102 -102
- package/data/docs/types/AccordionItem.json +28 -28
- package/data/docs/types/AccordionRoot.json +15 -15
- package/data/docs/types/AlertDescription.json +8 -8
- package/data/docs/types/AlertDismissButton.json +89 -89
- package/data/docs/types/AlertTitle.json +8 -8
- package/data/docs/types/Avatar.json +8 -8
- package/data/docs/types/Badge.json +2 -2
- package/data/docs/types/Body.json +6 -6
- package/data/docs/types/Box.json +6 -6
- package/data/docs/types/Button.json +97 -97
- package/data/docs/types/Calendar.json +111 -65
- package/data/docs/types/Caption.json +6 -6
- package/data/docs/types/Card.json +1 -1
- package/data/docs/types/{CardContent.json → CardBody.json} +2 -2
- package/data/docs/types/CardFooter.json +27 -0
- package/data/docs/types/CardRoot.json +18 -48
- package/data/docs/types/Cell.json +20 -20
- package/data/docs/types/Checkbox.json +99 -99
- package/data/docs/types/Code.json +10 -10
- package/data/docs/types/CollapsibleMotionContent.json +2 -2
- package/data/docs/types/CollapsibleMotionRoot.json +2 -2
- package/data/docs/types/CollapsibleMotionTrigger.json +4 -4
- package/data/docs/types/Column.json +8 -8
- package/data/docs/types/ColumnGroup.json +8 -8
- package/data/docs/types/ColumnHeader.json +18 -18
- package/data/docs/types/ComboBoxListBox.json +80 -80
- package/data/docs/types/ComboBoxOption.json +77 -77
- package/data/docs/types/ComboBoxPopover.json +77 -77
- package/data/docs/types/ComboBoxRoot.json +8 -8
- package/data/docs/types/ComboBoxSection.json +29 -29
- package/data/docs/types/ComboBoxTrigger.json +6 -6
- package/data/docs/types/ConfirmationDialog.json +224 -0
- package/data/docs/types/Content.json +2 -2
- package/data/docs/types/DataTable.json +17 -2
- package/data/docs/types/DataTableBody.json +24 -24
- package/data/docs/types/DataTableHeader.json +31 -31
- package/data/docs/types/DataTableRoot.json +17 -2
- package/data/docs/types/DataTableTable.json +35 -20
- package/data/docs/types/DateInput.json +84 -84
- package/data/docs/types/DatePicker.json +65 -65
- package/data/docs/types/DateRangePicker.json +99 -99
- package/data/docs/types/DateRangePickerField.json +99 -99
- package/data/docs/types/DefaultPageBackLink.json +16 -16
- package/data/docs/types/DefaultPageRoot.json +2 -2
- package/data/docs/types/DialogCloseTrigger.json +87 -87
- package/data/docs/types/DialogTrigger.json +2 -2
- package/data/docs/types/DragAndDropItemData.json +9 -0
- package/data/docs/types/DragAndDropProps.json +9 -0
- package/data/docs/types/DraggableListField.json +159 -70
- package/data/docs/types/DraggableListItem.json +63 -63
- package/data/docs/types/DraggableListRoot.json +159 -70
- package/data/docs/types/DrawerCloseTrigger.json +87 -87
- package/data/docs/types/DrawerTrigger.json +2 -2
- package/data/docs/types/FieldErrors.json +2 -2
- package/data/docs/types/Flex.json +22 -22
- package/data/docs/types/Footer.json +6 -6
- package/data/docs/types/FormActionBar.json +200 -0
- package/data/docs/types/FormDialog.json +198 -0
- package/data/docs/types/FormFieldRoot.json +2 -2
- package/data/docs/types/Grid.json +24 -24
- package/data/docs/types/Group.json +12 -12
- package/data/docs/types/Header.json +6 -6
- package/data/docs/types/Heading.json +8 -8
- package/data/docs/types/Icon.json +4 -4
- package/data/docs/types/IconButton.json +97 -97
- package/data/docs/types/IconToggleButton.json +84 -84
- package/data/docs/types/Image.json +30 -30
- package/data/docs/types/Indicator.json +6 -6
- package/data/docs/types/InfoDialog.json +104 -0
- package/data/docs/types/InlineSvg.json +2 -2
- package/data/docs/types/Item.json +6 -6
- package/data/docs/types/Kbd.json +8 -8
- package/data/docs/types/Link.json +31 -31
- package/data/docs/types/ListIndicator.json +6 -6
- package/data/docs/types/ListItem.json +6 -6
- package/data/docs/types/ListRoot.json +10 -10
- package/data/docs/types/LoadingSpinner.json +2 -2
- package/data/docs/types/MakeElementFocusable.json +19 -19
- package/data/docs/types/MenuItem.json +75 -75
- package/data/docs/types/MenuRoot.json +63 -63
- package/data/docs/types/MenuSection.json +35 -54
- package/data/docs/types/MenuSubmenuTrigger.json +5 -5
- package/data/docs/types/MenuTrigger.json +102 -102
- package/data/docs/types/MultilineTextInput.json +134 -134
- package/data/docs/types/MultilineTextInputField.json +131 -131
- package/data/docs/types/NumberInput.json +100 -100
- package/data/docs/types/NumberInputField.json +95 -95
- package/data/docs/types/PageContentColumn.json +6 -6
- package/data/docs/types/PageContentRoot.json +6 -6
- package/data/docs/types/PasswordInput.json +129 -129
- package/data/docs/types/PasswordInputField.json +129 -129
- package/data/docs/types/ProgressBar.json +14 -14
- package/data/docs/types/PublicPageLayout.json +99 -0
- package/data/docs/types/RadioInputOption.json +64 -64
- package/data/docs/types/RadioInputRoot.json +55 -55
- package/data/docs/types/RangeCalendar.json +90 -71
- package/data/docs/types/Region.json +114 -0
- package/data/docs/types/RegionProvider.json +25 -0
- package/data/docs/types/RegionTarget.json +112 -0
- package/data/docs/types/RichTextInput.json +2 -2
- package/data/docs/types/Root.json +10 -10
- package/data/docs/types/Row.json +6 -6
- package/data/docs/types/SPLITTER_SIZE_TOKENS.json +9 -0
- package/data/docs/types/ScrollArea.json +6 -6
- package/data/docs/types/SearchInput.json +136 -136
- package/data/docs/types/SearchInputField.json +131 -131
- package/data/docs/types/SelectOption.json +66 -66
- package/data/docs/types/SelectOptionGroup.json +22 -22
- package/data/docs/types/SelectOptions.json +74 -74
- package/data/docs/types/SelectRoot.json +102 -102
- package/data/docs/types/Separator.json +4 -4
- package/data/docs/types/SimpleGrid.json +28 -28
- package/data/docs/types/SplitButton.json +12 -12
- package/data/docs/types/Splitter.json +12 -0
- package/data/docs/types/SplitterAside.json +27 -0
- package/data/docs/types/SplitterHandle.json +27 -0
- package/data/docs/types/SplitterMain.json +27 -0
- package/data/docs/types/SplitterRoot.json +271 -0
- package/data/docs/types/SplitterSizeToken.json +9 -0
- package/data/docs/types/Stack.json +2 -2
- package/data/docs/types/StepsNextTrigger.json +2 -2
- package/data/docs/types/StepsPrevTrigger.json +2 -2
- package/data/docs/types/StepsRoot.json +2 -2
- package/data/docs/types/StepsTrigger.json +2 -2
- package/data/docs/types/Switch.json +38 -38
- package/data/docs/types/TabNavItem.json +18 -18
- package/data/docs/types/TabNavRoot.json +2 -2
- package/data/docs/types/TableBody.json +6 -6
- package/data/docs/types/TableCaption.json +6 -6
- package/data/docs/types/TableCell.json +20 -20
- package/data/docs/types/TableColumn.json +8 -8
- package/data/docs/types/TableColumnGroup.json +8 -8
- package/data/docs/types/TableColumnHeader.json +18 -18
- package/data/docs/types/TableFooter.json +6 -6
- package/data/docs/types/TableHeader.json +6 -6
- package/data/docs/types/TableRoot.json +32 -32
- package/data/docs/types/TableRow.json +6 -6
- package/data/docs/types/TableScrollArea.json +6 -6
- package/data/docs/types/TabsTab.json +2 -2
- package/data/docs/types/TagGroupRoot.json +27 -27
- package/data/docs/types/TagGroupTag.json +68 -68
- package/data/docs/types/TagGroupTagList.json +18 -18
- package/data/docs/types/Text.json +8 -8
- package/data/docs/types/TextInput.json +132 -132
- package/data/docs/types/TextInputField.json +129 -129
- package/data/docs/types/TimeInput.json +78 -78
- package/data/docs/types/ToggleButton.json +86 -86
- package/data/docs/types/ToggleButtonGroupButton.json +33 -33
- package/data/docs/types/ToggleButtonGroupRoot.json +20 -20
- package/data/docs/types/Toolbar.json +12 -12
- package/data/docs/types/TooltipContent.json +31 -31
- package/data/docs/types/TooltipRoot.json +18 -18
- package/data/docs/types/Trigger.json +4 -4
- package/data/docs/types/UseDragAndDropOptions.json +9 -0
- package/data/docs/types/VisuallyHidden.json +7 -7
- package/data/docs/types/createArrayHandlers.json +12 -0
- package/data/docs/types/createItemsFromCsvDrop.json +833 -0
- package/data/docs/types/createItemsFromDirectoryDrop.json +833 -0
- package/data/docs/types/createItemsFromFileDrop.json +833 -0
- package/data/docs/types/createItemsFromImageDrop.json +833 -0
- package/data/docs/types/createItemsFromJsonDrop.json +833 -0
- package/data/docs/types/createItemsFromTextDrop.json +12 -0
- package/data/docs/types/createListDataHandlers.json +102 -0
- package/data/docs/types/manifest.json +32 -2
- package/data/docs/types/toast.json +0 -15
- package/data/docs/types/useDragAndDrop.json +174 -0
- package/data/docs/types/useRegion.json +1052 -0
- package/data/docs/types/useResponsiveSplitterSizes.json +143 -0
- package/package.json +7 -7
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"id": "Patterns-ConfirmationDialog",
|
|
4
|
+
"title": "Confirmation dialog",
|
|
5
|
+
"exportName": "ConfirmationDialog",
|
|
6
|
+
"description": "A pre-composed confirm/cancel dialog with a flat, opinionated API.",
|
|
7
|
+
"order": 999,
|
|
8
|
+
"repoPath": "packages/nimbus/src/patterns/dialogs/confirmation-dialog/confirmation-dialog.mdx",
|
|
9
|
+
"menu": [
|
|
10
|
+
"Patterns",
|
|
11
|
+
"Dialogs",
|
|
12
|
+
"Confirmation dialog"
|
|
13
|
+
],
|
|
14
|
+
"route": "patterns/dialogs/confirmation-dialog",
|
|
15
|
+
"tags": [
|
|
16
|
+
"component",
|
|
17
|
+
"pattern",
|
|
18
|
+
"dialog",
|
|
19
|
+
"ConfirmationDialog"
|
|
20
|
+
],
|
|
21
|
+
"toc": [
|
|
22
|
+
{
|
|
23
|
+
"value": "Overview",
|
|
24
|
+
"href": "#overview",
|
|
25
|
+
"depth": 2,
|
|
26
|
+
"numbering": [
|
|
27
|
+
1,
|
|
28
|
+
1
|
|
29
|
+
],
|
|
30
|
+
"parent": "root"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"value": "When to use",
|
|
34
|
+
"href": "#when-to-use",
|
|
35
|
+
"depth": 3,
|
|
36
|
+
"numbering": [
|
|
37
|
+
1,
|
|
38
|
+
1,
|
|
39
|
+
1
|
|
40
|
+
],
|
|
41
|
+
"parent": "root"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"value": "When not to use",
|
|
45
|
+
"href": "#when-not-to-use",
|
|
46
|
+
"depth": 3,
|
|
47
|
+
"numbering": [
|
|
48
|
+
1,
|
|
49
|
+
1,
|
|
50
|
+
2
|
|
51
|
+
],
|
|
52
|
+
"parent": "root"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"value": "Resources",
|
|
56
|
+
"href": "#resources",
|
|
57
|
+
"depth": 3,
|
|
58
|
+
"numbering": [
|
|
59
|
+
1,
|
|
60
|
+
1,
|
|
61
|
+
3
|
|
62
|
+
],
|
|
63
|
+
"parent": "root"
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
"layout": "app-frame",
|
|
67
|
+
"tabs": [
|
|
68
|
+
{
|
|
69
|
+
"key": "overview",
|
|
70
|
+
"title": "Overview",
|
|
71
|
+
"order": 0
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"key": "dev",
|
|
75
|
+
"title": "Implementation",
|
|
76
|
+
"order": 3
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
"mdx": "\n## Overview\n\nConfirmationDialog is a pattern component that wraps the Dialog primitive plus two Buttons in a flat, opinionated API for the most common confirm/cancel dialog shape: a title, a body, two action callbacks, and optional state and intent props. It is the recommended replacement for the Merchant Center Application Kit's `ConfirmationDialog`.\n\nThe pattern exposes a small, flat set of props — `title`, `children`, `onConfirm`, `onCancel`, plus optional state, label, intent, and accessibility props — and delegates everything else (sizing, stacking, portaling, focus management, button styling) to the underlying `Dialog` and `Button` primitives.\n\n### When to use\n\n- Asking the user to confirm an action before it executes (delete, remove, discard, submit, publish)\n- Any scenario that needs a confirm/cancel pair with optional destructive styling and an in-flight loading state\n- Replacing app-kit's `ConfirmationDialog` during the migration\n\n### When not to use\n\n- Read-only informational dialogs without action buttons — use the `InfoDialog` pattern\n- Dialogs hosting editable forms — use `Dialog` directly with form wiring\n- Any scenario that needs a non-default size, custom dismissability behaviour, per-button `data-*` attributes, or a separate `onClose`/`onCancel` distinction — drop down to `Dialog` directly (see the escape hatch in the developer documentation)\n\n### Resources\n\nFor detailed guidance on the underlying primitives, consult the component guidelines:\n\n- [Dialog Guidelines](/components/feedback/dialog) — Variants, dismissability, sizing, placement, accessibility\n- [Button Guidelines](/components/forms/button) — Variants, color palettes, loading states\n- [Storybook](https://nimbus-storybook.vercel.app/?path=/docs/patterns-dialogs-confirmationdialog--docs)\n",
|
|
81
|
+
"views": {
|
|
82
|
+
"overview": {
|
|
83
|
+
"mdx": "\n## Overview\n\nConfirmationDialog is a pattern component that wraps the Dialog primitive plus two Buttons in a flat, opinionated API for the most common confirm/cancel dialog shape: a title, a body, two action callbacks, and optional state and intent props. It is the recommended replacement for the Merchant Center Application Kit's `ConfirmationDialog`.\n\nThe pattern exposes a small, flat set of props — `title`, `children`, `onConfirm`, `onCancel`, plus optional state, label, intent, and accessibility props — and delegates everything else (sizing, stacking, portaling, focus management, button styling) to the underlying `Dialog` and `Button` primitives.\n\n### When to use\n\n- Asking the user to confirm an action before it executes (delete, remove, discard, submit, publish)\n- Any scenario that needs a confirm/cancel pair with optional destructive styling and an in-flight loading state\n- Replacing app-kit's `ConfirmationDialog` during the migration\n\n### When not to use\n\n- Read-only informational dialogs without action buttons — use the `InfoDialog` pattern\n- Dialogs hosting editable forms — use `Dialog` directly with form wiring\n- Any scenario that needs a non-default size, custom dismissability behaviour, per-button `data-*` attributes, or a separate `onClose`/`onCancel` distinction — drop down to `Dialog` directly (see the escape hatch in the developer documentation)\n\n### Resources\n\nFor detailed guidance on the underlying primitives, consult the component guidelines:\n\n- [Dialog Guidelines](/components/feedback/dialog) — Variants, dismissability, sizing, placement, accessibility\n- [Button Guidelines](/components/forms/button) — Variants, color palettes, loading states\n- [Storybook](https://nimbus-storybook.vercel.app/?path=/docs/patterns-dialogs-confirmationdialog--docs)\n",
|
|
84
|
+
"toc": [
|
|
85
|
+
{
|
|
86
|
+
"value": "Overview",
|
|
87
|
+
"href": "#overview",
|
|
88
|
+
"depth": 2,
|
|
89
|
+
"numbering": [
|
|
90
|
+
1,
|
|
91
|
+
1
|
|
92
|
+
],
|
|
93
|
+
"parent": "root"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"value": "When to use",
|
|
97
|
+
"href": "#when-to-use",
|
|
98
|
+
"depth": 3,
|
|
99
|
+
"numbering": [
|
|
100
|
+
1,
|
|
101
|
+
1,
|
|
102
|
+
1
|
|
103
|
+
],
|
|
104
|
+
"parent": "root"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"value": "When not to use",
|
|
108
|
+
"href": "#when-not-to-use",
|
|
109
|
+
"depth": 3,
|
|
110
|
+
"numbering": [
|
|
111
|
+
1,
|
|
112
|
+
1,
|
|
113
|
+
2
|
|
114
|
+
],
|
|
115
|
+
"parent": "root"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"value": "Resources",
|
|
119
|
+
"href": "#resources",
|
|
120
|
+
"depth": 3,
|
|
121
|
+
"numbering": [
|
|
122
|
+
1,
|
|
123
|
+
1,
|
|
124
|
+
3
|
|
125
|
+
],
|
|
126
|
+
"parent": "root"
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
},
|
|
130
|
+
"dev": {
|
|
131
|
+
"mdx": "\n## Comparison: ConfirmationDialog vs manual Dialog composition\n\n**With ConfirmationDialog:**\n\n```tsx\n<ConfirmationDialog\n title=\"Delete project\"\n intent=\"destructive\"\n isOpen={isOpen}\n onOpenChange={setIsOpen}\n onConfirm={handleDelete}\n onCancel={() => setIsOpen(false)}\n>\n <Text>This action cannot be undone.</Text>\n</ConfirmationDialog>\n```\n\n**Manual composition:**\n\n```tsx\n<Dialog.Root\n isOpen={isOpen}\n onOpenChange={setIsOpen}\n isDismissable\n>\n <Dialog.Content>\n <Dialog.Header>\n <Dialog.Title>Delete project</Dialog.Title>\n <Dialog.CloseTrigger />\n </Dialog.Header>\n <Dialog.Body>\n <Text>This action cannot be undone.</Text>\n </Dialog.Body>\n <Dialog.Footer>\n <Button variant=\"outline\" onPress={() => setIsOpen(false)}>\n Cancel\n </Button>\n <Button\n variant=\"solid\"\n colorPalette=\"critical\"\n onPress={() => {\n handleDelete();\n setIsOpen(false);\n }}\n >\n Delete\n </Button>\n </Dialog.Footer>\n </Dialog.Content>\n</Dialog.Root>\n```\n\n### When to use which\n\n**Use ConfirmationDialog when:**\n\n- You need a confirm/cancel dialog with default or destructive intent\n- You want localized default Confirm/Cancel labels without wiring `useIntl` boilerplate\n- You want a built-in loading lockout for async confirm handlers\n- You're happy treating Escape, overlay click, and the X button as equivalent to clicking Cancel\n\n**Use Dialog directly when:**\n\n- You need a non-default size or custom dismissability behaviour\n- You need per-button `data-*` attributes (test IDs, tracking)\n- You need to distinguish the cancel button click from ambient dismissals (Escape, overlay, X) in your handlers\n- Your confirm action needs custom styling beyond `default` and `destructive` intent\n\n## Migrating from `merchant-center-application-kit`\n\nThe Nimbus `ConfirmationDialog` is intentionally smaller and more opinionated than the app-kit equivalent.\n\n| app-kit prop | Nimbus equivalent |\n| --- | --- |\n| `isOpen`, `onClose` | `isOpen`, `onOpenChange` (close routes through `onCancel` for ambient dismissals) |\n| `title`, `aria-label` | unchanged |\n| `children` | unchanged |\n| `labelPrimary`, `labelSecondary` | `confirmLabel`, `cancelLabel` |\n| `isPrimaryButtonDisabled` | `isConfirmDisabled` |\n| `onCancel`, `onConfirm` | unchanged |\n| `size` | dropped — drop down to `Dialog` for non-default sizes |\n| `zIndex` | dropped — Dialog primitive handles z-index stacking |\n| `dataAttributesPrimaryButton`, `dataAttributesSecondaryButton` | dropped — drop down to `Dialog` to add `data-*` attributes per button |\n| `getParentSelector` | dropped — React Aria handles portaling |\n| `ConfirmationDialog.TextTitle` | dropped — `title` accepts any `ReactNode` |\n| `ConfirmationDialog.Intl` | dropped — pass `confirmLabel` / `cancelLabel` directly |\n| _no equivalent_ | new: `intent=\"destructive\"` for delete/remove flows |\n| _no equivalent_ | new: `isConfirmLoading` for async confirm lockout |\n\nThe most consequential semantic change is that **`onClose` and `onCancel` are unified onto a single `onCancel`** that fires from every close path: the cancel button, Escape, overlay click, and the X button. ~55% of audited app-kit consumers already wire both to the same handler, so this is a no-op for the majority. If your app relies on the distinction, drop down to `Dialog` directly.\n\n## Getting started\n\n### Import\n\n```tsx\nimport {\n ConfirmationDialog,\n type ConfirmationDialogProps,\n} from \"@commercetools/nimbus\";\n```\n\n### Basic usage\n\nThe simplest implementation with a string title and controlled open state:\n\n```jsx live-dev\nconst App = () => {\n const [isOpen, setIsOpen] = useState(false);\n\n return (\n <>\n <Button onPress={() => setIsOpen(true)}>Submit order</Button>\n <ConfirmationDialog\n title=\"Submit order\"\n isOpen={isOpen}\n onOpenChange={setIsOpen}\n onConfirm={() => {\n console.log(\"submitting\");\n setIsOpen(false);\n }}\n onCancel={() => setIsOpen(false)}\n >\n <Text>You're about to submit this order for fulfillment.</Text>\n </ConfirmationDialog>\n </>\n );\n};\n```\n\n## Usage examples\n\n### Destructive intent\n\nSet `intent=\"destructive\"` for delete, remove, discard, and other irreversible actions. The confirm button receives the critical color palette automatically.\n\n```jsx live-dev\nconst App = () => {\n const [isOpen, setIsOpen] = useState(false);\n\n return (\n <>\n <Button colorPalette=\"critical\" onPress={() => setIsOpen(true)}>\n Delete project\n </Button>\n <ConfirmationDialog\n title=\"Delete project\"\n intent=\"destructive\"\n confirmLabel=\"Delete\"\n isOpen={isOpen}\n onOpenChange={setIsOpen}\n onConfirm={() => {\n console.log(\"deleting\");\n setIsOpen(false);\n }}\n onCancel={() => setIsOpen(false)}\n >\n <Text>\n This will permanently delete the project and all its data.\n </Text>\n </ConfirmationDialog>\n </>\n );\n};\n```\n\n### Async confirm with loading lockout\n\nIf `onConfirm` returns a `Promise`, the dialog stays open while the promise is pending and closes automatically when it fulfills. Hold `isConfirmLoading` true for the duration so the pattern can:\n\n- Show a spinner inside the confirm button\n- Disable both buttons\n- Suppress Escape, overlay click, and the X button\n\n```jsx live-dev\nconst App = () => {\n const [isOpen, setIsOpen] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n\n const handleConfirm = async () => {\n setIsLoading(true);\n try {\n await new Promise((resolve) => setTimeout(resolve, 1500));\n // Dialog closes automatically when the promise fulfills.\n } finally {\n setIsLoading(false);\n }\n };\n\n return (\n <>\n <Button onPress={() => setIsOpen(true)}>Publish</Button>\n <ConfirmationDialog\n title=\"Publish to production?\"\n isOpen={isOpen}\n onOpenChange={setIsOpen}\n isConfirmLoading={isLoading}\n onConfirm={handleConfirm}\n onCancel={() => setIsOpen(false)}\n >\n <Text>The change will be visible to all customers.</Text>\n </ConfirmationDialog>\n </>\n );\n};\n```\n\nIf the promise **rejects**, the dialog stays open so the consumer can surface the error (e.g. a Toast or an inline banner) and let the user retry. Let the error propagate out of `onConfirm` to keep the dialog open — catching the error inside the handler resolves the promise successfully and closes the dialog.\n\nFor long-running operations, prefer closing the dialog optimistically and reporting progress via a Toast or a banner, rather than holding the dialog open with a spinner.\n\n### Disabled confirm\n\nUse `isConfirmDisabled` to gate the confirm action on consumer-side validity (e.g. a required acknowledgement checkbox is unchecked).\n\n```jsx live-dev\nconst App = () => {\n const [isOpen, setIsOpen] = useState(false);\n const [acknowledged, setAcknowledged] = useState(false);\n\n return (\n <>\n <Button onPress={() => setIsOpen(true)}>Continue</Button>\n <ConfirmationDialog\n title=\"Confirm acknowledgement\"\n isOpen={isOpen}\n onOpenChange={setIsOpen}\n isConfirmDisabled={!acknowledged}\n onConfirm={() => setIsOpen(false)}\n onCancel={() => setIsOpen(false)}\n >\n <Stack gap=\"200\">\n <Text>Please acknowledge before continuing.</Text>\n <Checkbox isSelected={acknowledged} onChange={setAcknowledged}>\n I understand\n </Checkbox>\n </Stack>\n </ConfirmationDialog>\n </>\n );\n};\n```\n\n### Custom labels\n\n`confirmLabel` and `cancelLabel` accept any `ReactNode`, so consumer-localized strings (e.g. from `intl.formatMessage(...)`) work directly:\n\n```tsx\n<ConfirmationDialog\n title={intl.formatMessage(messages.unpublishTitle)}\n confirmLabel={intl.formatMessage(messages.unpublishConfirm)}\n cancelLabel={intl.formatMessage(messages.unpublishCancel)}\n isOpen={isOpen}\n onOpenChange={setIsOpen}\n onConfirm={handleUnpublish}\n onCancel={() => setIsOpen(false)}\n>\n <Text>{intl.formatMessage(messages.unpublishBody)}</Text>\n</ConfirmationDialog>\n```\n\n### ReactNode title with aria-label\n\n`title` accepts any ReactNode, so you can compose a heading with an icon or badge alongside text. When the composed markup wouldn't form a meaningful accessible name, pass `aria-label`:\n\n```tsx\n<ConfirmationDialog\n title={\n <Flex alignItems=\"center\" gap=\"200\">\n <Text>Cancel subscription</Text>\n <Badge>Pro</Badge>\n </Flex>\n }\n aria-label=\"Cancel subscription\"\n intent=\"destructive\"\n confirmLabel=\"Cancel subscription\"\n cancelLabel=\"Keep subscription\"\n isOpen={isOpen}\n onOpenChange={setIsOpen}\n onConfirm={handleCancel}\n onCancel={() => setIsOpen(false)}\n>\n <Text>You'll keep access until the end of the billing period.</Text>\n</ConfirmationDialog>\n```\n\n## Close affordances\n\nEvery close path other than the confirm button invokes `onCancel`:\n\n- **Cancel button** → `onCancel()` then `onOpenChange(false)`\n- **Confirm button** → `onConfirm()` then `onOpenChange(false)` (after the returned `Promise` fulfills, if any; rejected promises leave the dialog open). Does NOT invoke `onCancel`.\n- **Escape key** → `onCancel()` then `onOpenChange(false)`\n- **Overlay click** → `onCancel()` then `onOpenChange(false)`\n- **X button in header** → `onCancel()` then `onOpenChange(false)`\n\nWhile `isConfirmLoading` is `true`, all four cancel paths are suppressed and neither callback fires.\n\n## Accessibility\n\nConfirmationDialog inherits its accessibility guarantees from the Nimbus `Dialog` primitive:\n\n- `role=\"dialog\"` is exposed to assistive technology while open\n- Focus moves into the dialog on open and is trapped within it\n- Focus is restored to the triggering element on close\n- When `title` is a string, the dialog's accessible name is derived from it automatically — no extra `aria-label` is required\n\nIf the `title` is a composed ReactNode, pass an explicit `aria-label` so the dialog has a meaningful accessible name.\n\nThe cancel button is rendered before the confirm button in DOM order, so the natural first-focusable target is Cancel — a safer default for destructive confirmations.\n\n## Escape hatch\n\nIf you need a non-default size, per-button `data-*` attributes, custom dismissability, or a separate `onClose`-vs-`onCancel` distinction, drop down to composing `Dialog` and `Button` directly:\n\n```jsx live-dev\nconst App = () => {\n const [isOpen, setIsOpen] = useState(false);\n\n return (\n <>\n <Button onPress={() => setIsOpen(true)}>Open large confirmation</Button>\n <Dialog.Root\n isOpen={isOpen}\n onOpenChange={setIsOpen}\n isDismissable\n aria-label=\"Bulk delete\"\n >\n <Dialog.Content size=\"lg\">\n <Dialog.Header>\n <Dialog.Title>Delete 250 records?</Dialog.Title>\n <Dialog.CloseTrigger data-test-id=\"bulk-delete-close\" />\n </Dialog.Header>\n <Dialog.Body>\n <Text>This action cannot be undone.</Text>\n </Dialog.Body>\n <Dialog.Footer>\n <Button\n variant=\"outline\"\n data-test-id=\"bulk-delete-cancel\"\n onPress={() => setIsOpen(false)}\n >\n Cancel\n </Button>\n <Button\n variant=\"solid\"\n colorPalette=\"critical\"\n data-test-id=\"bulk-delete-confirm\"\n onPress={() => setIsOpen(false)}\n >\n Delete\n </Button>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Root>\n </>\n );\n};\n```\n\n## API reference\n\n<PropsTable id=\"ConfirmationDialog\" />\n\n## Testing your implementation\n\nThese examples demonstrate how to test your implementation when using ConfirmationDialog within your application. The component's internal behaviour is already covered by Nimbus — these tests help you verify your integration.\n\n### Basic Rendering\n\nVerify the ConfirmationDialog opens with default localized button labels.\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\nimport { userEvent } from \"@testing-library/user-event\";\nimport { useState } from \"react\";\nimport {\n Button,\n ConfirmationDialog,\n NimbusProvider,\n Text,\n} from \"@commercetools/nimbus\";\n\ndescribe(\"ConfirmationDialog - Basic rendering\", () => {\n it(\"renders title, body, and default Confirm/Cancel labels when isOpen is true\", () => {\n render(\n <NimbusProvider>\n <ConfirmationDialog\n title=\"Discard changes?\"\n isOpen\n onConfirm={() => {}}\n onCancel={() => {}}\n >\n <Text>You will lose any unsaved changes.</Text>\n </ConfirmationDialog>\n </NimbusProvider>\n );\n\n expect(\n screen.getByRole(\"heading\", { name: \"Discard changes?\" })\n ).toBeInTheDocument();\n expect(\n screen.getByText(\"You will lose any unsaved changes.\")\n ).toBeInTheDocument();\n expect(screen.getByRole(\"button\", { name: \"Confirm\" })).toBeInTheDocument();\n expect(screen.getByRole(\"button\", { name: \"Cancel\" })).toBeInTheDocument();\n });\n\n it(\"uses the string title as the dialog's accessible name\", () => {\n render(\n <NimbusProvider>\n <ConfirmationDialog\n title=\"Delete project\"\n isOpen\n onConfirm={() => {}}\n onCancel={() => {}}\n >\n <Text>This action cannot be undone.</Text>\n </ConfirmationDialog>\n </NimbusProvider>\n );\n\n expect(screen.getByRole(\"dialog\")).toHaveAccessibleName(\"Delete project\");\n });\n});\n```\n\n### Confirm and Cancel callbacks\n\nWire onConfirm and onCancel to consumer state to react to user choices.\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\nimport { userEvent } from \"@testing-library/user-event\";\nimport { useState } from \"react\";\nimport {\n Button,\n ConfirmationDialog,\n NimbusProvider,\n Text,\n} from \"@commercetools/nimbus\";\n\ndescribe(\"ConfirmationDialog - Confirm and Cancel callbacks\", () => {\n it(\"invokes onConfirm and closes the dialog when the confirm button is clicked\", async () => {\n const user = userEvent.setup();\n const handleConfirm = vi.fn();\n const handleCancel = vi.fn();\n\n const ControlledConfirmationDialog = () => {\n const [isOpen, setIsOpen] = useState(true);\n return (\n <ConfirmationDialog\n title=\"Submit order\"\n isOpen={isOpen}\n onOpenChange={setIsOpen}\n onConfirm={handleConfirm}\n onCancel={handleCancel}\n >\n <Text>Submit this order for fulfillment.</Text>\n </ConfirmationDialog>\n );\n };\n\n render(\n <NimbusProvider>\n <ControlledConfirmationDialog />\n </NimbusProvider>\n );\n\n await waitFor(() => expect(screen.getByRole(\"dialog\")).toBeInTheDocument());\n\n await user.click(screen.getByRole(\"button\", { name: \"Confirm\" }));\n\n expect(handleConfirm).toHaveBeenCalledTimes(1);\n expect(handleCancel).not.toHaveBeenCalled();\n await waitFor(() => {\n expect(screen.queryByRole(\"dialog\")).not.toBeInTheDocument();\n });\n });\n\n it(\"invokes onCancel and closes the dialog when the cancel button is clicked\", async () => {\n const user = userEvent.setup();\n const handleConfirm = vi.fn();\n const handleCancel = vi.fn();\n\n const ControlledConfirmationDialog = () => {\n const [isOpen, setIsOpen] = useState(true);\n return (\n <ConfirmationDialog\n title=\"Discard changes?\"\n isOpen={isOpen}\n onOpenChange={setIsOpen}\n onConfirm={handleConfirm}\n onCancel={handleCancel}\n >\n <Text>You will lose any unsaved changes.</Text>\n </ConfirmationDialog>\n );\n };\n\n render(\n <NimbusProvider>\n <ControlledConfirmationDialog />\n </NimbusProvider>\n );\n\n await waitFor(() => expect(screen.getByRole(\"dialog\")).toBeInTheDocument());\n\n await user.click(screen.getByRole(\"button\", { name: \"Cancel\" }));\n\n expect(handleCancel).toHaveBeenCalledTimes(1);\n expect(handleConfirm).not.toHaveBeenCalled();\n await waitFor(() => {\n expect(screen.queryByRole(\"dialog\")).not.toBeInTheDocument();\n });\n });\n});\n```\n\n### Destructive intent\n\nUse intent=\"destructive\" for delete, remove, and discard flows.\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\nimport { userEvent } from \"@testing-library/user-event\";\nimport { useState } from \"react\";\nimport {\n Button,\n ConfirmationDialog,\n NimbusProvider,\n Text,\n} from \"@commercetools/nimbus\";\n\ndescribe(\"ConfirmationDialog - Destructive intent\", () => {\n it(\"renders a destructive confirm button styled with the critical palette\", () => {\n render(\n <NimbusProvider>\n <ConfirmationDialog\n title=\"Delete project\"\n intent=\"destructive\"\n confirmLabel=\"Delete\"\n isOpen\n onConfirm={() => {}}\n onCancel={() => {}}\n >\n <Text>This will permanently delete the project.</Text>\n </ConfirmationDialog>\n </NimbusProvider>\n );\n\n expect(screen.getByRole(\"button\", { name: \"Delete\" })).toBeInTheDocument();\n });\n});\n```\n\n### Loading state lockout\n\nHold the dialog open while an async confirm is in flight.\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\nimport { userEvent } from \"@testing-library/user-event\";\nimport { useState } from \"react\";\nimport {\n Button,\n ConfirmationDialog,\n NimbusProvider,\n Text,\n} from \"@commercetools/nimbus\";\n\ndescribe(\"ConfirmationDialog - Loading state\", () => {\n it(\"disables both buttons while isConfirmLoading is true\", () => {\n render(\n <NimbusProvider>\n <ConfirmationDialog\n title=\"Submitting…\"\n isOpen\n isConfirmLoading\n onConfirm={() => {}}\n onCancel={() => {}}\n >\n <Text>Your request is being processed.</Text>\n </ConfirmationDialog>\n </NimbusProvider>\n );\n\n expect(screen.getByRole(\"button\", { name: /confirm/i })).toBeDisabled();\n expect(screen.getByRole(\"button\", { name: /cancel/i })).toBeDisabled();\n });\n});\n```\n\n### Gated confirm button\n\nUse isConfirmDisabled to gate confirm on consumer-side validity.\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\nimport { userEvent } from \"@testing-library/user-event\";\nimport { useState } from \"react\";\nimport {\n Button,\n ConfirmationDialog,\n NimbusProvider,\n Text,\n} from \"@commercetools/nimbus\";\n\ndescribe(\"ConfirmationDialog - Disabled confirm\", () => {\n it(\"disables the confirm button when isConfirmDisabled is true\", async () => {\n const user = userEvent.setup();\n const handleConfirm = vi.fn();\n\n render(\n <NimbusProvider>\n <ConfirmationDialog\n title=\"Confirm acknowledgement\"\n isOpen\n isConfirmDisabled\n onConfirm={handleConfirm}\n onCancel={() => {}}\n >\n <Text>Please review the disclaimer before confirming.</Text>\n </ConfirmationDialog>\n </NimbusProvider>\n );\n\n const confirm = screen.getByRole(\"button\", { name: \"Confirm\" });\n expect(confirm).toBeDisabled();\n\n await user.click(confirm);\n expect(handleConfirm).not.toHaveBeenCalled();\n });\n});\n```\n\n### Uncontrolled open state\n\nOpen the dialog by default with defaultOpen instead of managing state.\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\nimport { userEvent } from \"@testing-library/user-event\";\nimport { useState } from \"react\";\nimport {\n Button,\n ConfirmationDialog,\n NimbusProvider,\n Text,\n} from \"@commercetools/nimbus\";\n\ndescribe(\"ConfirmationDialog - Uncontrolled state\", () => {\n it(\"opens by default in uncontrolled mode via defaultOpen\", () => {\n render(\n <NimbusProvider>\n <ConfirmationDialog\n title=\"Confirm action\"\n defaultOpen\n onConfirm={() => {}}\n onCancel={() => {}}\n >\n <Text>Are you sure?</Text>\n </ConfirmationDialog>\n </NimbusProvider>\n );\n\n expect(screen.getByRole(\"dialog\")).toBeInTheDocument();\n expect(screen.getByText(\"Are you sure?\")).toBeInTheDocument();\n });\n});\n```\n\n### Triggering from a button\n\nRender your own trigger and drive isOpen / onOpenChange from state.\n\n```tsx\nimport { describe, it, expect, vi } from \"vitest\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\nimport { userEvent } from \"@testing-library/user-event\";\nimport { useState } from \"react\";\nimport {\n Button,\n ConfirmationDialog,\n NimbusProvider,\n Text,\n} from \"@commercetools/nimbus\";\n\ndescribe(\"ConfirmationDialog - Trigger pattern\", () => {\n it(\"opens from a consumer-rendered trigger and closes after confirm\", async () => {\n const user = userEvent.setup();\n const handleConfirm = vi.fn();\n const handleCancel = vi.fn();\n\n const App = () => {\n const [isOpen, setIsOpen] = useState(false);\n return (\n <>\n <Button onPress={() => setIsOpen(true)}>Submit order</Button>\n <ConfirmationDialog\n title=\"Submit order\"\n isOpen={isOpen}\n onOpenChange={setIsOpen}\n onConfirm={handleConfirm}\n onCancel={handleCancel}\n >\n <Text>Submit this order for fulfillment.</Text>\n </ConfirmationDialog>\n </>\n );\n };\n\n render(\n <NimbusProvider>\n <App />\n </NimbusProvider>\n );\n\n expect(screen.queryByRole(\"dialog\")).not.toBeInTheDocument();\n\n await user.click(screen.getByRole(\"button\", { name: \"Submit order\" }));\n\n await waitFor(() => expect(screen.getByRole(\"dialog\")).toBeInTheDocument());\n\n await user.click(screen.getByRole(\"button\", { name: \"Confirm\" }));\n\n expect(handleConfirm).toHaveBeenCalledTimes(1);\n expect(handleCancel).not.toHaveBeenCalled();\n await waitFor(() => {\n expect(screen.queryByRole(\"dialog\")).not.toBeInTheDocument();\n });\n });\n});\n```\n\n",
|
|
132
|
+
"toc": [
|
|
133
|
+
{
|
|
134
|
+
"value": "Comparison: ConfirmationDialog vs manual Dialog composition",
|
|
135
|
+
"href": "#comparison-confirmationdialog-vs-manual-dialog-composition",
|
|
136
|
+
"depth": 2,
|
|
137
|
+
"numbering": [
|
|
138
|
+
1,
|
|
139
|
+
1
|
|
140
|
+
],
|
|
141
|
+
"parent": "root"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"value": "When to use which",
|
|
145
|
+
"href": "#when-to-use-which",
|
|
146
|
+
"depth": 3,
|
|
147
|
+
"numbering": [
|
|
148
|
+
1,
|
|
149
|
+
1,
|
|
150
|
+
1
|
|
151
|
+
],
|
|
152
|
+
"parent": "root"
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"value": "Migrating from merchant-center-application-kit",
|
|
156
|
+
"href": "#migrating-from-merchant-center-application-kit",
|
|
157
|
+
"depth": 2,
|
|
158
|
+
"numbering": [
|
|
159
|
+
1,
|
|
160
|
+
2
|
|
161
|
+
],
|
|
162
|
+
"parent": "root"
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"value": "Getting started",
|
|
166
|
+
"href": "#getting-started",
|
|
167
|
+
"depth": 2,
|
|
168
|
+
"numbering": [
|
|
169
|
+
1,
|
|
170
|
+
3
|
|
171
|
+
],
|
|
172
|
+
"parent": "root"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"value": "Import",
|
|
176
|
+
"href": "#import",
|
|
177
|
+
"depth": 3,
|
|
178
|
+
"numbering": [
|
|
179
|
+
1,
|
|
180
|
+
3,
|
|
181
|
+
1
|
|
182
|
+
],
|
|
183
|
+
"parent": "root"
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"value": "Basic usage",
|
|
187
|
+
"href": "#basic-usage",
|
|
188
|
+
"depth": 3,
|
|
189
|
+
"numbering": [
|
|
190
|
+
1,
|
|
191
|
+
3,
|
|
192
|
+
2
|
|
193
|
+
],
|
|
194
|
+
"parent": "root"
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"value": "Usage examples",
|
|
198
|
+
"href": "#usage-examples",
|
|
199
|
+
"depth": 2,
|
|
200
|
+
"numbering": [
|
|
201
|
+
1,
|
|
202
|
+
4
|
|
203
|
+
],
|
|
204
|
+
"parent": "root"
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"value": "Destructive intent",
|
|
208
|
+
"href": "#destructive-intent",
|
|
209
|
+
"depth": 3,
|
|
210
|
+
"numbering": [
|
|
211
|
+
1,
|
|
212
|
+
4,
|
|
213
|
+
1
|
|
214
|
+
],
|
|
215
|
+
"parent": "root"
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"value": "Async confirm with loading lockout",
|
|
219
|
+
"href": "#async-confirm-with-loading-lockout",
|
|
220
|
+
"depth": 3,
|
|
221
|
+
"numbering": [
|
|
222
|
+
1,
|
|
223
|
+
4,
|
|
224
|
+
2
|
|
225
|
+
],
|
|
226
|
+
"parent": "root"
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"value": "Disabled confirm",
|
|
230
|
+
"href": "#disabled-confirm",
|
|
231
|
+
"depth": 3,
|
|
232
|
+
"numbering": [
|
|
233
|
+
1,
|
|
234
|
+
4,
|
|
235
|
+
3
|
|
236
|
+
],
|
|
237
|
+
"parent": "root"
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"value": "Custom labels",
|
|
241
|
+
"href": "#custom-labels",
|
|
242
|
+
"depth": 3,
|
|
243
|
+
"numbering": [
|
|
244
|
+
1,
|
|
245
|
+
4,
|
|
246
|
+
4
|
|
247
|
+
],
|
|
248
|
+
"parent": "root"
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
"value": "ReactNode title with aria-label",
|
|
252
|
+
"href": "#reactnode-title-with-aria-label",
|
|
253
|
+
"depth": 3,
|
|
254
|
+
"numbering": [
|
|
255
|
+
1,
|
|
256
|
+
4,
|
|
257
|
+
5
|
|
258
|
+
],
|
|
259
|
+
"parent": "root"
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
"value": "Close affordances",
|
|
263
|
+
"href": "#close-affordances",
|
|
264
|
+
"depth": 2,
|
|
265
|
+
"numbering": [
|
|
266
|
+
1,
|
|
267
|
+
5
|
|
268
|
+
],
|
|
269
|
+
"parent": "root"
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"value": "Accessibility",
|
|
273
|
+
"href": "#accessibility",
|
|
274
|
+
"depth": 2,
|
|
275
|
+
"numbering": [
|
|
276
|
+
1,
|
|
277
|
+
6
|
|
278
|
+
],
|
|
279
|
+
"parent": "root"
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"value": "Escape hatch",
|
|
283
|
+
"href": "#escape-hatch",
|
|
284
|
+
"depth": 2,
|
|
285
|
+
"numbering": [
|
|
286
|
+
1,
|
|
287
|
+
7
|
|
288
|
+
],
|
|
289
|
+
"parent": "root"
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"value": "API reference",
|
|
293
|
+
"href": "#api-reference",
|
|
294
|
+
"depth": 2,
|
|
295
|
+
"numbering": [
|
|
296
|
+
1,
|
|
297
|
+
8
|
|
298
|
+
],
|
|
299
|
+
"parent": "root"
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
"value": "Testing your implementation",
|
|
303
|
+
"href": "#testing-your-implementation",
|
|
304
|
+
"depth": 2,
|
|
305
|
+
"numbering": [
|
|
306
|
+
1,
|
|
307
|
+
9
|
|
308
|
+
],
|
|
309
|
+
"parent": "root"
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
"value": "Basic Rendering",
|
|
313
|
+
"href": "#basic-rendering",
|
|
314
|
+
"depth": 3,
|
|
315
|
+
"numbering": [
|
|
316
|
+
1,
|
|
317
|
+
9,
|
|
318
|
+
1
|
|
319
|
+
],
|
|
320
|
+
"parent": "root"
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
"value": "Confirm and Cancel callbacks",
|
|
324
|
+
"href": "#confirm-and-cancel-callbacks",
|
|
325
|
+
"depth": 3,
|
|
326
|
+
"numbering": [
|
|
327
|
+
1,
|
|
328
|
+
9,
|
|
329
|
+
2
|
|
330
|
+
],
|
|
331
|
+
"parent": "root"
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
"value": "Destructive intent",
|
|
335
|
+
"href": "#destructive-intent-1",
|
|
336
|
+
"depth": 3,
|
|
337
|
+
"numbering": [
|
|
338
|
+
1,
|
|
339
|
+
9,
|
|
340
|
+
3
|
|
341
|
+
],
|
|
342
|
+
"parent": "root"
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
"value": "Loading state lockout",
|
|
346
|
+
"href": "#loading-state-lockout",
|
|
347
|
+
"depth": 3,
|
|
348
|
+
"numbering": [
|
|
349
|
+
1,
|
|
350
|
+
9,
|
|
351
|
+
4
|
|
352
|
+
],
|
|
353
|
+
"parent": "root"
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
"value": "Gated confirm button",
|
|
357
|
+
"href": "#gated-confirm-button",
|
|
358
|
+
"depth": 3,
|
|
359
|
+
"numbering": [
|
|
360
|
+
1,
|
|
361
|
+
9,
|
|
362
|
+
5
|
|
363
|
+
],
|
|
364
|
+
"parent": "root"
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
"value": "Uncontrolled open state",
|
|
368
|
+
"href": "#uncontrolled-open-state",
|
|
369
|
+
"depth": 3,
|
|
370
|
+
"numbering": [
|
|
371
|
+
1,
|
|
372
|
+
9,
|
|
373
|
+
6
|
|
374
|
+
],
|
|
375
|
+
"parent": "root"
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
"value": "Triggering from a button",
|
|
379
|
+
"href": "#triggering-from-a-button",
|
|
380
|
+
"depth": 3,
|
|
381
|
+
"numbering": [
|
|
382
|
+
1,
|
|
383
|
+
9,
|
|
384
|
+
7
|
|
385
|
+
],
|
|
386
|
+
"parent": "root"
|
|
387
|
+
}
|
|
388
|
+
]
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|