XDSCard@xds/core · Card
Preview coming soon
Usage
Card groups related content into a visually distinct container with a border and background. Use it for profile cards, settings panels, data summaries, or any content that needs to stand out from the page.Best practices
| Guidance | Practices |
|---|---|
| Do | Try a section first — only use a card when you need the visual separation of a border and elevated background. |
| Do | Keep padding consistent across sibling cards so they align visually in a grid or list. |
| Do | Use the muted variant for secondary content like tips, callouts, or background information. |
| Do | Pair a card with XDSLayout when you need a structured header, scrollable content, and footer with actions. |
| Don't | Nest cards inside other cards — flatten the hierarchy or use a section instead. |
| Don't | Use color variants for status — use Banner or Badge for that. Color cards are for categorization. |
Anatomy
| Element | Description | |
|---|---|---|
| Container | required | The outer box with border, background, border-radius, and padding. |
| Content | required | Any children rendered inside the card. Often a stack of heading, text, and actions. |
Import
tsimport {XDSCard} from '@xds/core/Card'
Props
| Prop | Type | Description |
|---|---|---|
width | SizeValue | Width of the card (number = pixels, string = used as-is). |
height | SizeValue | Height of the card (number = pixels, string = used as-is). |
maxWidth | SizeValue | Maximum width of the card. |
minHeight | SizeValue | Minimum height of the card. |
children | ReactNode | Content to render inside the card. |
padding | 0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10 (default: 4) | Internal padding using the spacing scale. |
variant | 'default' | 'muted' | 'blue' | 'cyan' | 'gray' | 'green' | 'orange' | 'pink' | 'purple' | 'red' | 'teal' | 'yellow' (default: 'default') | Background color variant. `default` uses the standard card background. `muted` uses the wash background for de-emphasised cards. The non-semantic variants use the corresponding `--color-<name>-background` token. |
Examples
Common configurations, variations, and states.Card — Callout
tsx'use client';import {XDSCard} from '@xds/core/Card';import {XDSStack} from '@xds/core/Layout';import {XDSHeading, XDSText} from '@xds/core/Text';export default function CardCallout() {return (<XDSStack direction="horizontal" gap={4}><XDSCard width={270} variant="muted"><XDSStack direction="vertical" gap={2}><XDSHeading level={3}>Tip</XDSHeading><XDSText type="body" color="secondary">Use the muted variant for callouts or supplementary information.</XDSText></XDSStack></XDSCard><XDSCard width={270} variant="muted"><XDSStack direction="vertical" gap={2}><XDSHeading level={3}>Note</XDSHeading><XDSText type="body" color="secondary">Muted cards work well in sidebars or help panels.</XDSText></XDSStack></XDSCard></XDSStack>);}
Card — Layout
tsx'use client';import {XDSCard} from '@xds/core/Card';import {XDSLayout,XDSLayoutHeader,XDSLayoutContent,XDSLayoutFooter,XDSHStack,} from '@xds/core/Layout';import {XDSButton} from '@xds/core/Button';import {XDSHeading, XDSText} from '@xds/core/Text';export default function CardWithInnerLayout() {return (<XDSCard width={380}><XDSLayoutheader={<XDSLayoutHeader hasDivider><XDSHeading level={3}>Edit Profile</XDSHeading></XDSLayoutHeader>}content={<XDSLayoutContent><XDSText type="body" color="secondary">Update your display name, bio, and profile photo. Changes aresaved immediately.</XDSText></XDSLayoutContent>}footer={<XDSLayoutFooter hasDivider><XDSHStack gap={2} hAlign="end"><XDSButton label="Cancel" variant="ghost" /><XDSButton label="Save changes" variant="primary" /></XDSHStack></XDSLayoutFooter>}/></XDSCard>);}
Card — Simple
tsx'use client';import {XDSCard} from '@xds/core/Card';import {XDSStack} from '@xds/core/Layout';import {XDSHeading, XDSText} from '@xds/core/Text';export default function CardWithSimpleContent() {return (<XDSCard width={360}><XDSStack direction="vertical" gap={2}><XDSHeading level={3}>Project Overview</XDSHeading><XDSText type="body" color="secondary">This project tracks the redesign of the onboarding flow. The goal isto reduce drop-off by 15% in Q2.</XDSText><XDSText type="supporting" color="secondary">Last updated 2 hours ago</XDSText></XDSStack></XDSCard>);}
Card — Variants
tsx'use client';import {XDSCard} from '@xds/core/Card';import {XDSStack} from '@xds/core/Layout';import {XDSText} from '@xds/core/Text';const VARIANTS = [{variant: 'default' as const, label: 'General', note: '4 tasks due today'},{variant: 'muted' as const,label: 'Archived',note: 'No activity in 30 days',},{variant: 'blue' as const, label: 'Engineering', note: '12 open issues'},{variant: 'green' as const, label: 'Marketing', note: '3 campaigns active'},{variant: 'orange' as const, label: 'Urgent', note: '2 items need review'},{variant: 'purple' as const, label: 'Design', note: '5 drafts in progress'},];export default function CardVariants() {return (<XDSStack direction="horizontal" gap={3} style={{flexWrap: 'wrap'}}>{VARIANTS.map(({variant, label, note}) => (<XDSCard key={variant} variant={variant} width={160}><XDSStack direction="vertical" gap={1}><XDSText type="body" weight="bold">{label}</XDSText><XDSText type="supporting" color="secondary">{note}</XDSText></XDSStack></XDSCard>))}</XDSStack>);}
ClickableCardWithNestedButtonA product card that navigates on click but has an independent
tsx'use client';import {XDSClickableCard} from '@xds/core/ClickableCard';import {XDSStack} from '@xds/core/Layout';import {XDSText, XDSHeading} from '@xds/core/Text';import {XDSButton} from '@xds/core/Button';export default function ClickableCardWithNestedButton() {return (<XDSClickableCard label="Product" href="/product/123" width={320}><XDSStack direction="vertical" gap={3}><XDSStack direction="vertical" gap={1}><XDSHeading level={4}>Wireless Headphones</XDSHeading><XDSText type="body" color="secondary">$79.99</XDSText></XDSStack><XDSButton label="Add to cart" onClick={() => {}} variant="primary" /></XDSStack></XDSClickableCard>);}
SelectableCardMultiMulti-select tag picker using color variant selectable cards with color-matched selection borders.
tsx'use client';import {useState} from 'react';import {XDSSelectableCard} from '@xds/core/SelectableCard';import {XDSStack} from '@xds/core/Layout';import {XDSText} from '@xds/core/Text';const tags = [{id: 'react', name: 'React', variant: 'blue' as const},{id: 'typescript', name: 'TypeScript', variant: 'cyan' as const},{id: 'node', name: 'Node.js', variant: 'green' as const},{id: 'python', name: 'Python', variant: 'yellow' as const},{id: 'rust', name: 'Rust', variant: 'orange' as const},{id: 'go', name: 'Go', variant: 'teal' as const},];export default function SelectableCardMulti() {const [selected, setSelected] = useState(new Set(['react', 'typescript']));return (<XDSStack direction="horizontal" gap={2} wrap="wrap">{tags.map(tag => (<XDSSelectableCardkey={tag.id}label={tag.name}isSelected={selected.has(tag.id)}variant={tag.variant}onChange={isNow => {setSelected(prev => {const next = new Set(prev);if (isNow) {next.add(tag.id);} else {next.delete(tag.id);}return next;});}}width={130}><XDSText type="body" weight="bold">{tag.name}</XDSText></XDSSelectableCard>))}</XDSStack>);}
Showcase source
tsx'use client';import {XDSCard} from '@xds/core/Card';import {XDSStack} from '@xds/core/Layout';import {XDSText, XDSHeading} from '@xds/core/Text';export default function CardShowcase() {return (<XDSCard width={320}><XDSStack direction="vertical" gap={2}><XDSHeading level={4}>Card title</XDSHeading><XDSText type="body" color="secondary">Cards group related content with a border and background. Use them forprofiles, settings panels, or data summaries.</XDSText></XDSStack></XDSCard>);}