@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
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
]
|
|
98
98
|
},
|
|
99
99
|
"a11y": {
|
|
100
|
-
"mdx": "\n## Accessibility\n\nAccessibility ensures that digital content and functionality are usable by\neveryone, including people with disabilities, by addressing visual, auditory,\ncognitive, and physical limitations.\n\n```jsx live\nconst App = () => (\n <Card.Root
|
|
100
|
+
"mdx": "\n## Accessibility\n\nAccessibility ensures that digital content and functionality are usable by\neveryone, including people with disabilities, by addressing visual, auditory,\ncognitive, and physical limitations.\n\n### Automatic ARIA wiring\n\nCard supports automatic ARIA wiring via React Aria's slot system. When you place\na `<Heading slot=\"title\">` or `<Text slot=\"description\">` inside a Card, the\nroot element automatically receives `aria-labelledby` and/or `aria-describedby`\npointing to those elements. The card itself stays a plain `<div>` — no implicit\n`role` is applied. If you need a landmark role (e.g., `role=\"article\"` or\n`role=\"region\"`), set it explicitly on `Card.Root`.\n\n```jsx live\nconst App = () => (\n <Card.Root variant=\"outlined\" size=\"md\" role=\"article\">\n <Card.Header>\n <Heading slot=\"title\" as=\"h3\">Sprint Summary</Heading>\n </Card.Header>\n <Card.Body>\n <Text slot=\"description\">\n The team completed 85% of planned story points this sprint.\n </Text>\n </Card.Body>\n <Card.Footer>\n <Button variant=\"solid\" colorPalette=\"primary\" size=\"sm\">View Sprint</Button>\n </Card.Footer>\n </Card.Root>\n)\n```\n\n### Slot behavior\n\n| Slots present | `aria-labelledby` | `aria-describedby` |\n|---|---|---|\n| `Heading slot=\"title\"` + `Text slot=\"description\"` | points to Heading | points to Text |\n| `Heading slot=\"title\"` only | points to Heading | — |\n| `Text slot=\"description\"` only | — | points to Text |\n| No slots | — | — |\n\nThe card never sets a `role` automatically. A `<Heading>` or `<Text>` without\na `slot` prop is not wired up.\n\n### Manual labeling\n\nIf slot-based labeling is not suitable, pass `aria-label` directly to\n`Card.Root`:\n\n```jsx live\nconst App = () => (\n <Card.Root variant=\"outlined\" size=\"md\" aria-label=\"Product summary card\">\n <Card.Body>\n <Text>Content with manual aria-label.</Text>\n </Card.Body>\n </Card.Root>\n)\n```\n\n### Accessibility standards\n\n- **Non-text content:** Provide descriptive alternative text (`alt` attribute)\n for images within cards.\n- **Info and relationships:** Use semantic HTML to structure the card content\n logically (e.g., headings, lists).\n- **Color contrast:** Ensure sufficient color contrast between text and\n background within the card.\n- **Keyboard accessibility:** Ensure the entire card or its primary interactive\n elements are focusable and operable using only a keyboard.\n- **Focus visible:** Provide a clear visual focus indicator when the card or its\n interactive elements are focused.\n- **Target size:** If the card is interactive, ensure touch target sizes are\n adequate.\n- **Meaningful sequence:** Ensure the content within the card is presented in a\n logical order.\n- **Semantic HTML:** Use semantic HTML to ensure compatibility with assistive\n technologies.\n- **Avoid complex interactive cards:** Avoid making the entire card a single\n interactive element if it contains multiple distinct actions, to ensure proper\n interaction for assistive technology users.\n",
|
|
101
101
|
"toc": [
|
|
102
102
|
{
|
|
103
103
|
"value": "Accessibility",
|
|
@@ -109,6 +109,39 @@
|
|
|
109
109
|
],
|
|
110
110
|
"parent": "root"
|
|
111
111
|
},
|
|
112
|
+
{
|
|
113
|
+
"value": "Automatic ARIA wiring",
|
|
114
|
+
"href": "#automatic-aria-wiring",
|
|
115
|
+
"depth": 3,
|
|
116
|
+
"numbering": [
|
|
117
|
+
1,
|
|
118
|
+
1,
|
|
119
|
+
1
|
|
120
|
+
],
|
|
121
|
+
"parent": "root"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"value": "Slot behavior",
|
|
125
|
+
"href": "#slot-behavior",
|
|
126
|
+
"depth": 3,
|
|
127
|
+
"numbering": [
|
|
128
|
+
1,
|
|
129
|
+
1,
|
|
130
|
+
2
|
|
131
|
+
],
|
|
132
|
+
"parent": "root"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"value": "Manual labeling",
|
|
136
|
+
"href": "#manual-labeling",
|
|
137
|
+
"depth": 3,
|
|
138
|
+
"numbering": [
|
|
139
|
+
1,
|
|
140
|
+
1,
|
|
141
|
+
3
|
|
142
|
+
],
|
|
143
|
+
"parent": "root"
|
|
144
|
+
},
|
|
112
145
|
{
|
|
113
146
|
"value": "Accessibility standards",
|
|
114
147
|
"href": "#accessibility-standards",
|
|
@@ -116,14 +149,14 @@
|
|
|
116
149
|
"numbering": [
|
|
117
150
|
1,
|
|
118
151
|
1,
|
|
119
|
-
|
|
152
|
+
4
|
|
120
153
|
],
|
|
121
154
|
"parent": "root"
|
|
122
155
|
}
|
|
123
156
|
]
|
|
124
157
|
},
|
|
125
158
|
"dev": {
|
|
126
|
-
"mdx": "\n## Getting started\n\n### Import\n\n```tsx\nimport { Box, Card, Link, type CardProps } from '@commercetools/nimbus';\n```\n\n### Basic usage\n\nThe Card component uses a compound pattern to structure content. You must wrap `Card.Header` and `Card.Content` within `Card.Root`.\n\n```jsx live-dev\nconst App = () => (\n <Card.Root>\n <Card.Header>Card Title</Card.Header>\n <Card.Content>\n <Text>This is the main card content.</Text>\n </Card.Content>\n </Card.Root>\n)\n```\n\n## Usage examples\n\n### Size options\n\nThe `cardPadding` prop controls the internal spacing of the card. Available sizes are `sm`, `md`, and `lg`.\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <Card.Root cardPadding=\"sm\">\n <Card.Header>Small Padding</Card.Header>\n <Card.Content>Compact content spacing.</Card.Content>\n </Card.Root>\n\n <Card.Root cardPadding=\"md\">\n <Card.Header>Medium Padding</Card.Header>\n <Card.Content>Standard content spacing (default).</Card.Content>\n </Card.Root>\n\n <Card.Root cardPadding=\"lg\">\n <Card.Header>Large Padding</Card.Header>\n <Card.Content>Spacious content layout.</Card.Content>\n </Card.Root>\n </Stack>\n)\n```\n\n### Visual variants\n\nCustomize the card's appearance using `borderStyle`, `elevation`, and `backgroundStyle`.\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <Card.Root borderStyle=\"outlined\" elevation=\"none\">\n <Card.Header>Outlined (Default)</Card.Header>\n <Card.Content>Standard bordered look.</Card.Content>\n </Card.Root>\n\n <Card.Root borderStyle=\"none\" elevation=\"elevated\">\n <Card.Header>Elevated</Card.Header>\n <Card.Content>Shadow depth without border.</Card.Content>\n </Card.Root>\n\n <Card.Root backgroundStyle=\"muted\" borderStyle=\"none\">\n <Card.Header>Muted Background</Card.Header>\n <Card.Content>Subtle background color for differentiation.</Card.Content>\n </Card.Root>\n </Stack>\n)\n```\n\n### Interactive cards\n\nWhen making a card interactive, avoid placing `onClick` directly on the `Card.Root`. Instead, wrap the card in an anchor tag or use proper ARIA roles to ensure accessibility.\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n {/* Option 1: Wrapped in a Nimbus Link (Recommended for navigation) */}\n <Link \n href=\"#\" \n textDecoration=\"none\" \n color=\"inherit\" \n display=\"block\"\n _hover={{ textDecoration: 'none' }}\n aria-label=\"Navigate to details\"\n >\n <Card.Root borderStyle=\"outlined\" elevation=\"elevated\">\n <Card.Header>Navigational Card</Card.Header>\n <Card.Content>\n This entire card acts as a link using the system Link component.\n </Card.Content>\n </Card.Root>\n </Link>\n\n {/* Option 2: Interactive element with ARIA (For actions) */}\n <Box\n role=\"button\"\n tabIndex={0}\n onClick={() => alert(\"Card clicked\")}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n alert(\"Card clicked\");\n }\n }}\n cursor=\"pointer\"\n aria-label=\"Trigger action\"\n >\n <Card.Root borderStyle=\"outlined\">\n <Card.Header>Action Card</Card.Header>\n <Card.Content>\n Behaves like a button with keyboard support (Tab, Enter, Space).\n </Card.Content>\n </Card.Root>\n </Box>\n </Stack>\n)\n```\n\n## Component requirements\n\n## Accessibility\n\nThe `Card` component handles most accessibility requirements internally, rendering semantic `div` elements by default. It acts as a generic container.\n\n- **Headings**: Ensure the content within `Card.Header` follows your page's heading hierarchy (e.g., use `Heading` component or `h3`, `h4` tags).\n- **Interactive Cards**: If a card is interactive (clickable), do not attach `onClick` directly to the card div if possible. Instead, wrap the card in a link or button, or ensure proper ARIA roles (`role=\"button\"`) and keyboard handling (`tabIndex={0}`, Enter/Space key listeners) are implemented.\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 = \"project-summary-card\";\n\nexport const Example = () => (\n <Card.Root id={PERSISTENT_ID}>\n <Card.Header>Summary</Card.Header>\n <Card.Content>...</Card.Content>\n </Card.Root>\n);\n```\n\n#### Keyboard navigation\n\nStandard Cards are not focusable. Interactive content inside the card (buttons, links) follows the default focus order.\n\n## API reference\n\n<PropsTable id=\"Card\" />\n\n## Testing your implementation\n\nThese examples demonstrate how to test your implementation when using Card 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 card displays the correct title and content\n\n```tsx\nimport { describe, it, expect } from \"vitest\";\nimport { render, screen } from \"@testing-library/react\";\nimport { Card, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Card - Basic rendering\", () => {\n it(\"renders project details\", () => {\n render(\n <NimbusProvider>\n <Card.Root>\n <Card.Header>Project X</Card.Header>\n <Card.Content>Status: Active</Card.Content>\n </Card.Root>\n </NimbusProvider>\n );\n\n expect(screen.getByText(\"Project X\")).toBeInTheDocument();\n expect(screen.getByText(\"Status: Active\")).toBeInTheDocument();\n });\n\n it(\"renders with header only\", () => {\n render(\n <NimbusProvider>\n <Card.Root>\n <Card.Header>Card Title</Card.Header>\n </Card.Root>\n </NimbusProvider>\n );\n\n expect(screen.getByText(\"Card Title\")).toBeInTheDocument();\n });\n\n it(\"renders with content only\", () => {\n render(\n <NimbusProvider>\n <Card.Root>\n <Card.Content>This is the main content.</Card.Content>\n </Card.Root>\n </NimbusProvider>\n );\n\n expect(screen.getByText(\"This is the main content.\")).toBeInTheDocument();\n });\n});\n```\n\n\n## Resources\n\n- [Storybook](https://nimbus-storybook.vercel.app/?path=/docs/components-card--docs)\n\n",
|
|
159
|
+
"mdx": "\n## Getting started\n\n### Import\n\n```tsx\nimport { Button, Card, Link, type CardProps } from '@commercetools/nimbus';\n```\n\n### Basic usage\n\nThe Card component uses a compound pattern to structure content. Wrap `Card.Header`, `Card.Body`, and `Card.Footer` within `Card.Root`.\n\n```jsx live-dev\nconst App = () => (\n <Card.Root>\n <Card.Header>Card Title</Card.Header>\n <Card.Body>\n <Text>This is the main card content.</Text>\n </Card.Body>\n </Card.Root>\n)\n```\n\n## Usage examples\n\n### Size options\n\nThe `size` prop controls the internal padding and gap of the card. Available sizes are `sm`, `md`, and `lg`.\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <Card.Root size=\"sm\">\n <Card.Header>Small</Card.Header>\n <Card.Body>Compact content spacing.</Card.Body>\n </Card.Root>\n\n <Card.Root size=\"md\">\n <Card.Header>Medium</Card.Header>\n <Card.Body>Standard content spacing (default).</Card.Body>\n </Card.Root>\n\n <Card.Root size=\"lg\">\n <Card.Header>Large</Card.Header>\n <Card.Body>Spacious content layout.</Card.Body>\n </Card.Root>\n </Stack>\n)\n```\n\n### Visual variants\n\nThe `variant` prop controls the card's visual treatment. Eight variants\nexpose every combination of three independent axes — `outlined` (border),\n`elevated` (shadow), and `muted` (background) — joined with hyphens.\nVariant names omit any axis that is off.\n\n| variant | border | shadow | background |\n| ----------------------------- | :----: | :----: | :--------: |\n| `plain` | | | default |\n| `outlined` _(default)_ | ✓ | | default |\n| `elevated` | | ✓ | default |\n| `outlined-elevated` | ✓ | ✓ | default |\n| `muted` | | | muted |\n| `outlined-muted` | ✓ | | muted |\n| `elevated-muted` | | ✓ | muted |\n| `outlined-elevated-muted` | ✓ | ✓ | muted |\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n <Card.Root variant=\"outlined\">\n <Card.Header>Outlined (Default)</Card.Header>\n <Card.Body>Standard bordered look.</Card.Body>\n </Card.Root>\n\n <Card.Root variant=\"elevated\">\n <Card.Header>Elevated</Card.Header>\n <Card.Body>Shadow depth without border.</Card.Body>\n </Card.Root>\n\n <Card.Root variant=\"outlined-elevated\">\n <Card.Header>Outlined + elevated</Card.Header>\n <Card.Body>Both border and shadow.</Card.Body>\n </Card.Root>\n\n <Card.Root variant=\"muted\">\n <Card.Header>Muted</Card.Header>\n <Card.Body>Muted background for differentiation.</Card.Body>\n </Card.Root>\n\n <Card.Root variant=\"plain\">\n <Card.Header>Plain</Card.Header>\n <Card.Body>Minimal visual treatment.</Card.Body>\n </Card.Root>\n </Stack>\n)\n```\n\n### Card with footer\n\nUse `Card.Footer` for actions and metadata placed below the body content.\n\n```jsx live-dev\nconst App = () => (\n <Card.Root variant=\"outlined\" size=\"md\">\n <Card.Header>Project Summary</Card.Header>\n <Card.Body>\n <Text>The project is on track for the next milestone.</Text>\n </Card.Body>\n <Card.Footer>\n <Button variant=\"solid\" colorPalette=\"primary\" size=\"sm\">View Details</Button>\n </Card.Footer>\n </Card.Root>\n)\n```\n\n### Accessible cards\n\nUse `<Heading slot=\"title\">` and `<Text slot=\"description\">` to automatically wire `aria-labelledby` and `aria-describedby` on the card. The card itself stays a plain `<div>` — set `role` explicitly on the consumer side if a landmark or interactive role is needed.\n\n```jsx live-dev\nconst App = () => (\n <Card.Root variant=\"outlined\" size=\"md\">\n <Card.Header>\n <Heading slot=\"title\" as=\"h3\">Sprint Summary</Heading>\n </Card.Header>\n <Card.Body>\n <Text slot=\"description\">\n The team completed 85% of planned story points this sprint.\n </Text>\n </Card.Body>\n <Card.Footer>\n <Button variant=\"solid\" colorPalette=\"primary\" size=\"sm\">View Sprint</Button>\n </Card.Footer>\n </Card.Root>\n)\n```\n\n### Interactive cards\n\nWhen making a card interactive, avoid placing `onClick` directly on the `Card.Root`. Instead, wrap the card in an anchor tag or use proper ARIA roles to ensure accessibility.\n\n```jsx live-dev\nconst App = () => (\n <Stack direction=\"column\" gap=\"400\">\n {/* Option 1: Wrapped in a Nimbus Link (Recommended for navigation) */}\n <Link \n href=\"#\" \n textDecoration=\"none\" \n color=\"inherit\" \n display=\"block\"\n _hover={{ textDecoration: 'none' }}\n aria-label=\"Navigate to details\"\n >\n <Card.Root variant=\"outlined\">\n <Card.Header>Navigational Card</Card.Header>\n <Card.Body>\n This entire card acts as a link using the system Link component.\n </Card.Body>\n </Card.Root>\n </Link>\n\n {/* Option 2: Wrapped in a native <button> (Recommended for actions) */}\n <Button\n variant=\"ghost\"\n onPress={() => alert(\"Card clicked\")}\n aria-label=\"Trigger action\"\n p=\"0\"\n >\n <Card.Root variant=\"outlined\">\n <Card.Header>Action Card</Card.Header>\n <Card.Body>\n Native button gives you Tab focus, Enter/Space activation, and a focus\n ring for free.\n </Card.Body>\n </Card.Root>\n </Button>\n </Stack>\n)\n```\n\n## Component requirements\n\n## Accessibility\n\nThe `Card` component supports automatic ARIA wiring via React Aria's slot system.\n\n- **Automatic ARIA wiring**: Place `<Heading slot=\"title\">` inside the card for automatic `aria-labelledby`. Place `<Text slot=\"description\">` for `aria-describedby`. The card itself stays a plain `<div>` — no implicit `role` is applied.\n- **Manual labeling**: Pass `aria-label` directly to `Card.Root` when slot-based labeling is not suitable.\n- **Semantic role**: If you need a landmark role (e.g., `role=\"article\"` or `role=\"region\"`), set it explicitly on `Card.Root` or on a wrapping element.\n- **Headings**: Ensure the content within `Card.Header` follows your page's heading hierarchy (e.g., use `Heading` component with appropriate `as` prop).\n- **Interactive Cards**: If a card is interactive (clickable), do not attach `onClick` directly to the card div. Instead, wrap the card in a native link or button, which provides focus, keyboard activation, and the correct accessible name automatically.\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 = \"project-summary-card\";\n\nexport const Example = () => (\n <Card.Root id={PERSISTENT_ID}>\n <Card.Header>Summary</Card.Header>\n <Card.Body>...</Card.Body>\n </Card.Root>\n);\n```\n\n#### Keyboard navigation\n\nStandard Cards are not focusable. Interactive content inside the card (buttons, links) follows the default focus order.\n\n## API reference\n\n<PropsTable id=\"Card\" />\n\n## Testing your implementation\n\nThese examples demonstrate how to test your implementation when using Card 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 card displays the correct title and content\n\n```tsx\nimport { describe, it, expect } from \"vitest\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\nimport { Card, Heading, Text, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Card - Basic rendering\", () => {\n it(\"renders project details\", () => {\n render(\n <NimbusProvider>\n <Card.Root>\n <Card.Header>Project X</Card.Header>\n <Card.Body>Status: Active</Card.Body>\n </Card.Root>\n </NimbusProvider>\n );\n\n expect(screen.getByText(\"Project X\")).toBeInTheDocument();\n expect(screen.getByText(\"Status: Active\")).toBeInTheDocument();\n });\n\n it(\"renders with header only\", () => {\n render(\n <NimbusProvider>\n <Card.Root>\n <Card.Header>Card Title</Card.Header>\n </Card.Root>\n </NimbusProvider>\n );\n\n expect(screen.getByText(\"Card Title\")).toBeInTheDocument();\n });\n\n it(\"renders with body only\", () => {\n render(\n <NimbusProvider>\n <Card.Root>\n <Card.Body>This is the main content.</Card.Body>\n </Card.Root>\n </NimbusProvider>\n );\n\n expect(screen.getByText(\"This is the main content.\")).toBeInTheDocument();\n });\n\n it(\"renders with footer\", () => {\n render(\n <NimbusProvider>\n <Card.Root>\n <Card.Header>Title</Card.Header>\n <Card.Body>Content</Card.Body>\n <Card.Footer>Footer actions</Card.Footer>\n </Card.Root>\n </NimbusProvider>\n );\n\n expect(screen.getByText(\"Title\")).toBeInTheDocument();\n expect(screen.getByText(\"Content\")).toBeInTheDocument();\n expect(screen.getByText(\"Footer actions\")).toBeInTheDocument();\n });\n\n it(\"renders with variant and size props\", () => {\n render(\n <NimbusProvider>\n <Card.Root variant=\"elevated\" size=\"lg\">\n <Card.Body>Elevated card</Card.Body>\n </Card.Root>\n </NimbusProvider>\n );\n\n expect(screen.getByText(\"Elevated card\")).toBeInTheDocument();\n });\n});\n```\n\n### Slot-Based Accessibility\n\nUsing Heading and Text slots for automatic ARIA wiring\n\n```tsx\nimport { describe, it, expect } from \"vitest\";\nimport { render, screen, waitFor } from \"@testing-library/react\";\nimport { Card, Heading, Text, NimbusProvider } from \"@commercetools/nimbus\";\n\ndescribe(\"Card - Slot-based accessibility\", () => {\n it(\"wires aria-labelledby and aria-describedby from title and description slots\", async () => {\n render(\n <NimbusProvider>\n <Card.Root data-testid=\"card-slot\">\n <Card.Header>\n <Heading slot=\"title\" as=\"h3\">\n Product Details\n </Heading>\n </Card.Header>\n <Card.Body>\n <Text slot=\"description\">\n Overview of the product's key features.\n </Text>\n </Card.Body>\n </Card.Root>\n </NimbusProvider>\n );\n\n const card = screen.getByTestId(\"card-slot\");\n const heading = screen.getByText(\"Product Details\");\n const description = screen.getByText(/key features/);\n\n // useSlotId completes its registration on a follow-up render.\n await waitFor(() => {\n expect(card).toHaveAttribute(\"aria-labelledby\", heading.id);\n expect(card).toHaveAttribute(\"aria-describedby\", description.id);\n });\n\n // Card is a plain div — set role explicitly if a landmark role is needed.\n expect(card).not.toHaveAttribute(\"role\");\n });\n\n it(\"has no role or ARIA labelling attributes without slots\", () => {\n render(\n <NimbusProvider>\n <Card.Root data-testid=\"card-plain\">\n <Card.Header>Title</Card.Header>\n <Card.Body>Content</Card.Body>\n </Card.Root>\n </NimbusProvider>\n );\n\n const card = screen.getByTestId(\"card-plain\");\n\n expect(card).not.toHaveAttribute(\"role\");\n expect(card).not.toHaveAttribute(\"aria-labelledby\");\n expect(card).not.toHaveAttribute(\"aria-describedby\");\n });\n});\n```\n\n\n## Resources\n\n- [Storybook](https://nimbus-storybook.vercel.app/?path=/docs/components-card--docs)\n",
|
|
127
160
|
"toc": [
|
|
128
161
|
{
|
|
129
162
|
"value": "Getting started",
|
|
@@ -189,6 +222,28 @@
|
|
|
189
222
|
],
|
|
190
223
|
"parent": "root"
|
|
191
224
|
},
|
|
225
|
+
{
|
|
226
|
+
"value": "Card with footer",
|
|
227
|
+
"href": "#card-with-footer",
|
|
228
|
+
"depth": 3,
|
|
229
|
+
"numbering": [
|
|
230
|
+
1,
|
|
231
|
+
2,
|
|
232
|
+
3
|
|
233
|
+
],
|
|
234
|
+
"parent": "root"
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"value": "Accessible cards",
|
|
238
|
+
"href": "#accessible-cards",
|
|
239
|
+
"depth": 3,
|
|
240
|
+
"numbering": [
|
|
241
|
+
1,
|
|
242
|
+
2,
|
|
243
|
+
4
|
|
244
|
+
],
|
|
245
|
+
"parent": "root"
|
|
246
|
+
},
|
|
192
247
|
{
|
|
193
248
|
"value": "Interactive cards",
|
|
194
249
|
"href": "#interactive-cards",
|
|
@@ -196,7 +251,7 @@
|
|
|
196
251
|
"numbering": [
|
|
197
252
|
1,
|
|
198
253
|
2,
|
|
199
|
-
|
|
254
|
+
5
|
|
200
255
|
],
|
|
201
256
|
"parent": "root"
|
|
202
257
|
},
|
|
@@ -263,6 +318,17 @@
|
|
|
263
318
|
],
|
|
264
319
|
"parent": "root"
|
|
265
320
|
},
|
|
321
|
+
{
|
|
322
|
+
"value": "Slot-Based Accessibility",
|
|
323
|
+
"href": "#slot-based-accessibility",
|
|
324
|
+
"depth": 3,
|
|
325
|
+
"numbering": [
|
|
326
|
+
1,
|
|
327
|
+
6,
|
|
328
|
+
2
|
|
329
|
+
],
|
|
330
|
+
"parent": "root"
|
|
331
|
+
},
|
|
266
332
|
{
|
|
267
333
|
"value": "Resources",
|
|
268
334
|
"href": "#resources",
|
|
@@ -276,7 +342,7 @@
|
|
|
276
342
|
]
|
|
277
343
|
},
|
|
278
344
|
"guidelines": {
|
|
279
|
-
"mdx": "\n## Guidelines\n\nCard component guidelines focus on providing a clear, concise, and visually\ndistinct container for related content, ensuring scannability, clear actions,\nand adaptability across various layouts and screen sizes.\n\n### Best practices\n\n- **Clear purpose:** Each card should represent a single, distinct piece of\n content or concept. Avoid combining multiple unrelated ideas into one card.\n- **Concise content:** Keep the information within a card brief and scannable.\n Use clear headings, short descriptions, and only essential details.\n- **Visual hierarchy:** Establish a clear visual hierarchy to guide the user's\n eye. Use appropriate typography, spacing, and visual cues to prioritize\n important information.\n- **Actionable elements:** If the card requires user interaction, clearly\n present the primary action(s) with prominent buttons or links. Limit the\n number of actions to avoid overwhelming the user.\n- **Consistent styling:** Maintain consistent styling for cards. This includes\n borders, shadows, typography, and spacing.\n- **Responsive design:** Ensure cards adapt well to different screen sizes and\n orientations. Consider how the layout will change on mobile devices.\n\n### Usage\n\nThe strength of using cards in a UI lies in their ability to present information\nin concise, digestible chunks, making it easy for users to quickly scan,\nunderstand, and interact with related content, especially in responsive layouts.\n\n> [!TIP]\\\n> When to use\n\n- **Displaying a collection of related items:** When you have multiple, distinct\n items that share a similar structure or theme (e.g., product listings,\n documentation, user profiles).\n- **Presenting scannable summaries:** When you need to provide a quick overview\n of information, allowing users to grasp the key details at a glance.\n- **Highlighting key information:** When you want to draw attention to important\n pieces of content or features.\n- **Facilitating task completion:** When a card can contain actions that allow\n users to quickly interact with or manage the displayed information.\n- **Creating a visually organized layout:** When you need to break down complex\n information into digestible chunks and create a structured, modular design.\n- **Responsive design:** When you need a component that adapts well to various\n screen sizes and can be easily rearranged on different devices.\n- **Content discovery:** When you want to encourage users to explore different\n pieces of content.\n\n> [!CAUTION]\\\n> When not to use\n\n- **Presenting linear processes:** When users need to follow a specific,\n sequential flow (e.g., a step-by-step form or a tutorial). Other patterns like\n steppers are more appropriate.\n- **Displaying single, detailed items:** When you need to present a lot of\n in-depth information about one specific item. A dedicated page is usually\n better.\n- **Primary navigation:** Using cards for main site navigation can be\n overwhelming and make it difficult for users to understand the site's\n structure.\n- **Simple lists:** For basic lists of items with minimal information, a simple\n list or table might be more efficient and less visually heavy.\n- **When content is highly interrelated and needs comparison:** If users need to\n compare specific attributes across multiple items, a table might be a better\n choice.\n- **Overcrowding the UI with too many cards:** Using too many cards on a page\n can lead to visual clutter and make it hard for users to focus on what's\n important.\n- **Forcing content into a card structure:** If the content doesn't naturally\n fit into a card format, trying to force it can lead to awkward design and a\n poor user experience.\n\n### Content\n\nContent within cards should be concise and focused, prioritizing key information\nand clear actions to ensure scannability and quick user comprehension. Consider\nthe card's purpose and limit content to only the most relevant details, using\nclear headings and short descriptions.\n\n> [!TIP]\\\n> **Do**\n>\n> - Cards are best for presenting self-contained pieces of information.\n> - Design cards with clear headings, concise text, and a logical visual\n> hierarchy for easy scanning.\n\n```jsx live\nconst App = () => (\n <Card.Root cardPadding=\"md\" borderStyle=\"outlined\" width=\"8000\">\n <Card.Content>\n <Stack gap=\"400\">\n <img src=\"/images/card/card-discount-template.png\" alt=\"discount template illustration\" />\n <Text fontWeight=\"bold\">\n Discount templates\n </Text>\n <Text>\n Templates allow you to get started quickly and easily by displaying only\n what is needed for creating your discount.\n </Text>\n <Select.Root aria-label=\"Select template\" placeholder=\"Select...\">\n <Select.Options>{/* Options would go here */}</Select.Options>\n </Select.Root>\n <Box>\n <Button colorPalette=\"primary\" variant=\"solid\">\n Select template\n </Button>\n </Box>\n </Stack>\n </Card.Content>\n </Card.Root>\n);\n```\n\n> [!CAUTION]\\\n> **Don't**\n>\n> - Avoid cramming too much information into a single card. Each card should\n> focus on a single subject.\n> - Long, scrolling cards can be cumbersome; prioritize key information.\n> - Don't use a card to compare information.\n\n```jsx live\nconst App = () => (\n <Card.Root cardPadding=\"md\" borderStyle=\"outlined\" width=\"1\">\n <Card.Content>\n <Stack direction=\"horizontal\" gap=\"400\">\n <Stack gap=\"400\" width=\"1/2\">\n <img src=\"/images/card/card-discount-template.png\" alt=\"discount template illustration\" />\n <Text fontWeight=\"bold\">\n Discount templates\n </Text>\n <Text>\n Templates allow you to get started quickly and easily by displaying\n only what is needed for creating your discount.\n </Text>\n <Select.Root aria-label=\"Select template\" placeholder=\"Select...\">\n <Select.Options>{/* Options would go here */}</Select.Options>\n </Select.Root>\n <Box>\n <Button colorPalette=\"primary\" variant=\"solid\">\n Select template\n </Button>\n </Box>\n </Stack>\n <Stack gap=\"400\" width=\"1/2\">\n <img src=\"/images/card/card-product-discount.png\" alt=\"product discount illustration\" />\n <Text fontWeight=\"bold\">\n Product discount\n </Text>\n <Text>\n A product discount applies a percentage-off (relative) or amount-ff\n (absolute) discount to a specific product or subset of products\n before adding them to the cart. They are useful for displaying\n discounted or sale prices on a product info page\n </Text>\n <Box>\n <Button colorPalette=\"primary\" variant=\"solid\">\n Add product discount\n </Button>\n </Box>\n </Stack>\n </Stack>\n </Card.Content>\n </Card.Root>\n);\n```\n\n### Actions\n\nActions within a card should be limited and focused, prioritizing the primary\naction related to the card's content to avoid overwhelming the user. Ensure\nactions are clearly labeled and visually prominent to facilitate quick\ninteraction.\n\n> [!TIP]\\\n> **Do**\n>\n> - If interaction is needed, provide obvious and limited actions.\n> - Users often assume cards are clickable, especially when they contain visual\n> cues that suggest interactivity, like buttons, links, or hover effects.\n> However, this assumption isn't universal and can vary depending on the\n> context and user experience.\n\n```jsx live\nconst App = () => (\n <Card.Root cardPadding=\"md\" borderStyle=\"outlined\" width=\"384px\">\n <Card.Content>\n <Stack direction=\"horizontal\" gap=\"400\">\n <Box\n color=\"primary.11\"\n boxSize=\"1000\"\n borderRadius=\"50%\"\n bg=\"primary.3\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n flexShrink=\"0\"\n >\n <Icons.ViewInAr width=\"24px\" height=\"24px\" />\n </Box>\n <Stack gap=\"100\">\n <Text fontWeight=\"bold\">\n Learn more about products\n </Text>\n <Text color=\"neutral.11\">\n Discover what a product list is and how to manage it.\n </Text>\n </Stack>\n </Stack>\n </Card.Content>\n </Card.Root>\n);\n```\n\n> [!CAUTION]\\\n> **Don't**\n>\n> - Don't use too many actions for the user within cards.\n> - Cards are generally not suitable for primary site navigation.\n\n```jsx live\nconst App = () => (\n <Stack gap=\"400\" alignItems=\"start\">\n {/* Main Card */}\n <Card.Root cardPadding=\"md\" borderStyle=\"outlined\" width=\"423px\">\n <Card.Content>\n <Stack direction=\"horizontal\" gap=\"400\">\n <Box\n alignSelf=\"flex-start\"\n color=\"primary.11\"\n boxSize=\"1000\"\n borderRadius=\"50%\"\n bg=\"primary.3\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n flexShrink=\"0\"\n >\n <Icons.ViewInAr width=\"24px\" height=\"24px\" />\n </Box>\n <Stack direction=\"horizontal\" gap=\"400\" alignItems=\"center\">\n <Stack gap=\"200\">\n <Flex gap=\"100\" alignItems=\"center\">\n <Text fontWeight=\"bold\" color=\"primary.11\">\n See your products\n </Text>\n <Box color=\"primary.11\" boxSize=\"600\">\n <Icons.ArrowForward width=\"full\" height=\"full\" />\n </Box>\n </Flex>\n <Text color=\"neutral.11\">\n You have modified products that are waiting to be published\n </Text>\n {/* Buttons */}\n <Stack gap=\"200\">\n <Button\n colorPalette=\"primary\"\n variant=\"solid\"\n alignSelf=\"start\"\n >\n Publish Products\n </Button>\n <Stack direction=\"horizontal\" gap=\"300\">\n <Button colorPalette=\"primary\" variant=\"link\" size=\"sm\">\n Review\n </Button>\n <Button colorPalette=\"primary\" variant=\"link\" size=\"sm\">\n Reject\n </Button>\n <Button colorPalette=\"primary\" variant=\"link\" size=\"sm\">\n See drafts\n </Button>\n </Stack>\n </Stack>\n </Stack>\n </Stack>\n </Stack>\n </Card.Content>\n </Card.Root>\n\n {/* Bottom Row Cards */}\n <Stack direction=\"horizontal\" gap=\"400\">\n {/* Products Card */}\n <Card.Root\n cardPadding=\"md\"\n borderStyle=\"outlined\"\n width=\"201.5px\"\n > {/* Half width approx */}\n <Card.Content>\n <Stack direction=\"horizontal\" gap=\"300\" alignItems=\"center\">\n <Box\n alignSelf=\"flex-start\"\n color=\"primary.11\"\n boxSize=\"1000\"\n borderRadius=\"50%\"\n bg=\"primary.3\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n flexShrink=\"0\"\n >\n <Icons.ViewInAr width=\"24px\" height=\"24px\" />\n </Box>\n <Text textStyle=\"bodyStrong\" fontWeight=\"bold\" color=\"primary.11\">\n Products\n </Text>\n </Stack>\n </Card.Content>\n </Card.Root>\n\n {/* Discounts Card */}\n <Card.Root\n cardPadding=\"md\"\n borderStyle=\"outlined\"\n width=\"201.5px\"\n > {/* Half width approx */}\n <Card.Content>\n <Stack direction=\"horizontal\" gap=\"300\" alignItems=\"center\">\n <Box\n alignSelf=\"flex-start\"\n color=\"primary.11\"\n boxSize=\"1000\"\n borderRadius=\"50%\"\n bg=\"primary.3\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n flexShrink=\"0\"\n >\n <Icons.Discount width=\"24px\" height=\"24px\" />\n </Box>\n <Text textStyle=\"bodyStrong\" fontWeight=\"bold\" color=\"primary.11\">\n Discounts\n </Text>\n </Stack>\n </Card.Content>\n </Card.Root>\n </Stack>\n </Stack>\n);\n```\n",
|
|
345
|
+
"mdx": "\n## Guidelines\n\nCard component guidelines focus on providing a clear, concise, and visually\ndistinct container for related content, ensuring scannability, clear actions,\nand adaptability across various layouts and screen sizes.\n\n### Best practices\n\n- **Clear purpose:** Each card should represent a single, distinct piece of\n content or concept. Avoid combining multiple unrelated ideas into one card.\n- **Concise content:** Keep the information within a card brief and scannable.\n Use clear headings, short descriptions, and only essential details.\n- **Visual hierarchy:** Establish a clear visual hierarchy to guide the user's\n eye. Use appropriate typography, spacing, and visual cues to prioritize\n important information.\n- **Actionable elements:** If the card requires user interaction, clearly\n present the primary action(s) with prominent buttons or links. Limit the\n number of actions to avoid overwhelming the user.\n- **Consistent styling:** Maintain consistent styling for cards. This includes\n borders, shadows, typography, and spacing.\n- **Responsive design:** Ensure cards adapt well to different screen sizes and\n orientations. Consider how the layout will change on mobile devices.\n\n### Usage\n\nThe strength of using cards in a UI lies in their ability to present information\nin concise, digestible chunks, making it easy for users to quickly scan,\nunderstand, and interact with related content, especially in responsive layouts.\n\n> [!TIP]\\\n> When to use\n\n- **Displaying a collection of related items:** When you have multiple, distinct\n items that share a similar structure or theme (e.g., product listings,\n documentation, user profiles).\n- **Presenting scannable summaries:** When you need to provide a quick overview\n of information, allowing users to grasp the key details at a glance.\n- **Highlighting key information:** When you want to draw attention to important\n pieces of content or features.\n- **Facilitating task completion:** When a card can contain actions that allow\n users to quickly interact with or manage the displayed information.\n- **Creating a visually organized layout:** When you need to break down complex\n information into digestible chunks and create a structured, modular design.\n- **Responsive design:** When you need a component that adapts well to various\n screen sizes and can be easily rearranged on different devices.\n- **Content discovery:** When you want to encourage users to explore different\n pieces of content.\n\n> [!CAUTION]\\\n> When not to use\n\n- **Presenting linear processes:** When users need to follow a specific,\n sequential flow (e.g., a step-by-step form or a tutorial). Other patterns like\n steppers are more appropriate.\n- **Displaying single, detailed items:** When you need to present a lot of\n in-depth information about one specific item. A dedicated page is usually\n better.\n- **Primary navigation:** Using cards for main site navigation can be\n overwhelming and make it difficult for users to understand the site's\n structure.\n- **Simple lists:** For basic lists of items with minimal information, a simple\n list or table might be more efficient and less visually heavy.\n- **When content is highly interrelated and needs comparison:** If users need to\n compare specific attributes across multiple items, a table might be a better\n choice.\n- **Overcrowding the UI with too many cards:** Using too many cards on a page\n can lead to visual clutter and make it hard for users to focus on what's\n important.\n- **Forcing content into a card structure:** If the content doesn't naturally\n fit into a card format, trying to force it can lead to awkward design and a\n poor user experience.\n\n### Content\n\nContent within cards should be concise and focused, prioritizing key information\nand clear actions to ensure scannability and quick user comprehension. Consider\nthe card's purpose and limit content to only the most relevant details, using\nclear headings and short descriptions.\n\n> [!TIP]\\\n> **Do**\n>\n> - Cards are best for presenting self-contained pieces of information.\n> - Design cards with clear headings, concise text, and a logical visual\n> hierarchy for easy scanning.\n\n```jsx live\nconst App = () => (\n <Card.Root variant=\"outlined\" size=\"md\" width=\"8000\">\n <Card.Body>\n <Stack gap=\"400\">\n <img src=\"/images/card/card-discount-template.png\" alt=\"discount template illustration\" />\n <Text fontWeight=\"bold\">\n Discount templates\n </Text>\n <Text>\n Templates allow you to get started quickly and easily by displaying only\n what is needed for creating your discount.\n </Text>\n <Select.Root aria-label=\"Select template\" placeholder=\"Select...\">\n <Select.Options>{/* Options would go here */}</Select.Options>\n </Select.Root>\n <Box>\n <Button colorPalette=\"primary\" variant=\"solid\">\n Select template\n </Button>\n </Box>\n </Stack>\n </Card.Body>\n </Card.Root>\n);\n```\n\n> [!CAUTION]\\\n> **Don't**\n>\n> - Avoid cramming too much information into a single card. Each card should\n> focus on a single subject.\n> - Long, scrolling cards can be cumbersome; prioritize key information.\n> - Don't use a card to compare information.\n\n```jsx live\nconst App = () => (\n <Card.Root variant=\"outlined\" size=\"md\" width=\"1\">\n <Card.Body>\n <Stack direction=\"horizontal\" gap=\"400\">\n <Stack gap=\"400\" width=\"1/2\">\n <img src=\"/images/card/card-discount-template.png\" alt=\"discount template illustration\" />\n <Text fontWeight=\"bold\">\n Discount templates\n </Text>\n <Text>\n Templates allow you to get started quickly and easily by displaying\n only what is needed for creating your discount.\n </Text>\n <Select.Root aria-label=\"Select template\" placeholder=\"Select...\">\n <Select.Options>{/* Options would go here */}</Select.Options>\n </Select.Root>\n <Box>\n <Button colorPalette=\"primary\" variant=\"solid\">\n Select template\n </Button>\n </Box>\n </Stack>\n <Stack gap=\"400\" width=\"1/2\">\n <img src=\"/images/card/card-product-discount.png\" alt=\"product discount illustration\" />\n <Text fontWeight=\"bold\">\n Product discount\n </Text>\n <Text>\n A product discount applies a percentage-off (relative) or amount-ff\n (absolute) discount to a specific product or subset of products\n before adding them to the cart. They are useful for displaying\n discounted or sale prices on a product info page\n </Text>\n <Box>\n <Button colorPalette=\"primary\" variant=\"solid\">\n Add product discount\n </Button>\n </Box>\n </Stack>\n </Stack>\n </Card.Body>\n </Card.Root>\n);\n```\n\n### Actions\n\nActions within a card should be limited and focused, prioritizing the primary\naction related to the card's content to avoid overwhelming the user. Ensure\nactions are clearly labeled and visually prominent to facilitate quick\ninteraction.\n\n> [!TIP]\\\n> **Do**\n>\n> - If interaction is needed, provide obvious and limited actions.\n> - Users often assume cards are clickable, especially when they contain visual\n> cues that suggest interactivity, like buttons, links, or hover effects.\n> However, this assumption isn't universal and can vary depending on the\n> context and user experience.\n\n```jsx live\nconst App = () => (\n <Card.Root variant=\"outlined\" size=\"md\" width=\"384px\">\n <Card.Body>\n <Stack direction=\"horizontal\" gap=\"400\">\n <Box\n color=\"primary.11\"\n boxSize=\"1000\"\n borderRadius=\"50%\"\n bg=\"primary.3\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n flexShrink=\"0\"\n >\n <Icons.ViewInAr width=\"24px\" height=\"24px\" />\n </Box>\n <Stack gap=\"100\">\n <Text fontWeight=\"bold\">\n Learn more about products\n </Text>\n <Text color=\"neutral.11\">\n Discover what a product list is and how to manage it.\n </Text>\n </Stack>\n </Stack>\n </Card.Body>\n </Card.Root>\n);\n```\n\n> [!CAUTION]\\\n> **Don't**\n>\n> - Don't use too many actions for the user within cards.\n> - Cards are generally not suitable for primary site navigation.\n\n```jsx live\nconst App = () => (\n <Stack gap=\"400\" alignItems=\"start\">\n {/* Main Card */}\n <Card.Root variant=\"outlined\" size=\"md\" width=\"423px\">\n <Card.Body>\n <Stack direction=\"horizontal\" gap=\"400\">\n <Box\n alignSelf=\"flex-start\"\n color=\"primary.11\"\n boxSize=\"1000\"\n borderRadius=\"50%\"\n bg=\"primary.3\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n flexShrink=\"0\"\n >\n <Icons.ViewInAr width=\"24px\" height=\"24px\" />\n </Box>\n <Stack direction=\"horizontal\" gap=\"400\" alignItems=\"center\">\n <Stack gap=\"200\">\n <Flex gap=\"100\" alignItems=\"center\">\n <Text fontWeight=\"bold\" color=\"primary.11\">\n See your products\n </Text>\n <Box color=\"primary.11\" boxSize=\"600\">\n <Icons.ArrowForward width=\"full\" height=\"full\" />\n </Box>\n </Flex>\n <Text color=\"neutral.11\">\n You have modified products that are waiting to be published\n </Text>\n {/* Buttons */}\n <Stack gap=\"200\">\n <Button\n colorPalette=\"primary\"\n variant=\"solid\"\n alignSelf=\"start\"\n >\n Publish Products\n </Button>\n <Stack direction=\"horizontal\" gap=\"300\">\n <Button colorPalette=\"primary\" variant=\"link\" size=\"sm\">\n Review\n </Button>\n <Button colorPalette=\"primary\" variant=\"link\" size=\"sm\">\n Reject\n </Button>\n <Button colorPalette=\"primary\" variant=\"link\" size=\"sm\">\n See drafts\n </Button>\n </Stack>\n </Stack>\n </Stack>\n </Stack>\n </Stack>\n </Card.Body>\n </Card.Root>\n\n {/* Bottom Row Cards */}\n <Stack direction=\"horizontal\" gap=\"400\">\n {/* Products Card */}\n <Card.Root\n variant=\"outlined\"\n size=\"md\"\n width=\"201.5px\"\n > {/* Half width approx */}\n <Card.Body>\n <Stack direction=\"horizontal\" gap=\"300\" alignItems=\"center\">\n <Box\n alignSelf=\"flex-start\"\n color=\"primary.11\"\n boxSize=\"1000\"\n borderRadius=\"50%\"\n bg=\"primary.3\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n flexShrink=\"0\"\n >\n <Icons.ViewInAr width=\"24px\" height=\"24px\" />\n </Box>\n <Text textStyle=\"bodyStrong\" fontWeight=\"bold\" color=\"primary.11\">\n Products\n </Text>\n </Stack>\n </Card.Body>\n </Card.Root>\n\n {/* Discounts Card */}\n <Card.Root\n variant=\"outlined\"\n size=\"md\"\n width=\"201.5px\"\n > {/* Half width approx */}\n <Card.Body>\n <Stack direction=\"horizontal\" gap=\"300\" alignItems=\"center\">\n <Box\n alignSelf=\"flex-start\"\n color=\"primary.11\"\n boxSize=\"1000\"\n borderRadius=\"50%\"\n bg=\"primary.3\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n flexShrink=\"0\"\n >\n <Icons.Discount width=\"24px\" height=\"24px\" />\n </Box>\n <Text textStyle=\"bodyStrong\" fontWeight=\"bold\" color=\"primary.11\">\n Discounts\n </Text>\n </Stack>\n </Card.Body>\n </Card.Root>\n </Stack>\n </Stack>\n);\n```\n",
|
|
280
346
|
"toc": [
|
|
281
347
|
{
|
|
282
348
|
"value": "Guidelines",
|