Card
Rounded container surface for grouping related content.
Examples
Section titled “Examples”Card content
<Card {...args} style={{width: 360}}> <Text type="body">Card content</Text></Card>Variants
Section titled “Variants”default
section
transparent
muted
<div style={{display: 'grid', gap: 16, gridTemplateColumns: 'repeat(4, 1fr)'}}> {(['default', 'section', 'transparent', 'muted'] as const).map( variant => ( <Card key={variant} padding={4} variant={variant}> <Text type="body">{variant}</Text> </Card> ), )}</div>Colors
Section titled “Colors”blue
cyan
gray
green
orange
pink
purple
red
teal
yellow
<div style={{display: 'grid', gap: 16, gridTemplateColumns: 'repeat(5, 1fr)'}}> {( [ 'blue', 'cyan', 'gray', 'green', 'orange', 'pink', 'purple', 'red', 'teal', 'yellow', ] as const ).map(color => ( <Card color={color} key={color} padding={4}> <Text type="body">{color}</Text> </Card> ))}</div>Padding
Section titled “Padding”padding={0}
padding={1}
padding={2}
padding={3}
padding={4}
padding={6}
padding={8}
padding={10}
() => { const steps: SpacingToken[] = [0, 1, 2, 3, 4, 6, 8, 10]; return ( <div style={{display: 'flex', flexWrap: 'wrap', gap: 16}}> {steps.map(step => ( <Card key={step} padding={step}> <div className={css({ bg: 'surface.blue', borderRadius: 'md', p: '2', })}> <Text type="supporting">{`padding={${step}}`}</Text> </div> </Card> ))} </div> );}Section
Section titled “Section”A section card has no border or border-radius, making it suitable for use inside a larger container.
Another section
Section with color
<div className={containerStyle} style={{width: 400}}> <Card padding={4} variant="section"> <Text type="body"> A section card has no border or border-radius, making it suitable for use inside a larger container. </Text> </Card> <Divider /> <Card padding={4} variant="section"> <Text type="body">Another section</Text> </Card> <Divider /> <Card color="blue" padding={4} variant="section"> <Text type="body">Section with color</Text> </Card></div>Full Bleed Divider
Section titled “Full Bleed Divider”Content above the divider
The divider stretches to the card edges using the
--card-padding custom property.<Card padding={4} style={{width: 360}}> <VStack gap={3}> <Text type="body">Content above the divider</Text> <Divider isFullBleed /> <Text type="body"> The divider stretches to the card edges using the{' '} <code>--card-padding</code> custom property. </Text> </VStack></Card>Nested
Section titled “Nested”Outer card
Nested blue
Nested green
Nested muted card
<Card padding={4} style={{width: 480}}> <VStack gap={3}> <Text type="label">Outer card</Text> <div style={{display: 'grid', gap: 12, gridTemplateColumns: '1fr 1fr'}}> <Card color="blue" padding={3}> <Text type="supporting">Nested blue</Text> </Card> <Card color="green" padding={3}> <Text type="supporting">Nested green</Text> </Card> </div> <Card padding={3} variant="muted"> <Text type="supporting">Nested muted card</Text> </Card> </VStack></Card>Rich Content
Section titled “Rich Content”Featured project
Active<Card padding={4} style={{width: 360}}> <VStack gap={3}> <HStack align="center" gap={3} justify="between"> <HStack align="center" gap={2}> <Icon color="accent" icon={Star} /> <Text type="label">Featured project</Text> </HStack> <Badge color="success" label="Active" /> </HStack> <Text color="secondary" type="body"> A short description of the project with enough detail to understand what it does at a glance. </Text> <Divider isFullBleed /> <HStack gap={2} justify="end"> <Button label="Details" size="sm" variant="ghost" /> <Button label="Open" size="sm" variant="primary" /> </HStack> </VStack></Card>Card List
Section titled “Card List”ProfileEdit your personal info
NotificationsConfigure alerts
SettingsApp preferences
() => { const items = [ {icon: User, title: 'Profile', description: 'Edit your personal info'}, {icon: Bell, title: 'Notifications', description: 'Configure alerts'}, {icon: Settings, title: 'Settings', description: 'App preferences'}, ];
return ( <VStack gap={2} style={{width: 400}}> {items.map(item => ( <Card key={item.title} padding={3}> <HStack align="center" gap={3}> <Icon icon={item.icon} /> <VStack gap={0}> <Text type="label">{item.title}</Text> <Text color="secondary" type="supporting"> {item.description} </Text> </VStack> </HStack> </Card> ))} </VStack> );}With Layout
Section titled “With Layout”Settings
Sidebar
Main content area
<Card style={{height: 360, width: 600}}> <Layout content={ <LayoutContent> <Text type="body">Main content area</Text> </LayoutContent> } footer={ <LayoutFooter primaryButton={<Button label="Save" variant="primary" />} secondaryButton={<Button label="Cancel" variant="ghost" />} /> } header={<LayoutHeader title="Settings" />} start={ <LayoutPanel width={160}> <Text type="body">Sidebar</Text> </LayoutPanel> } /></Card>CheckboxCard examples
Section titled “CheckboxCard examples”Import Items
Section titled “Import Items”Content to import
function ImportSelection(): React.JSX.Element { const [value, setValue] = useState(['documents']); const items = [ { description: '24 PDF and text files', icon: FileText, label: 'Documents', value: 'documents', }, { description: '128 photos and illustrations', icon: Image, label: 'Images', value: 'images', }, { description: '6 compressed archives', icon: FileArchive, label: 'Archives', value: 'archives', }, ];
return ( <CheckboxGroup className={groupClassName} label="Content to import" onChange={setValue} value={value}> {items.map(item => ( <CheckboxCard key={item.value} label={item.label} padding={4} value={item.value}> <HStack align="center" gap={3} justify="between"> <HStack align="center" gap={2}> <Icon color="secondary" icon={item.icon} /> <VStack gap={0}> <Text type="label">{item.label}</Text> <Text color="secondary" type="supporting"> {item.description} </Text> </VStack> </HStack> {item.value === 'documents' ? ( <Badge color="blue" label="Recommended" /> ) : null} </HStack> </CheckboxCard> ))} </CheckboxGroup> );}
<ImportSelection />States
Section titled “States”Selection states
<CheckboxGroup className={groupClassName} label="Selection states" onChange={() => {}} value={['selected']}> <CheckboxCard label="Selected option" padding={4} value="selected"> <Text type="label">Selected option</Text> </CheckboxCard> <CheckboxCard isDisabled label="Disabled option" padding={4} value="disabled"> <Text type="label">Disabled option</Text> </CheckboxCard></CheckboxGroup>ClickableCard examples
Section titled “ClickableCard examples”Action
Section titled “Action”<ClickableCard className={cardClassName} label="Open account settings" onClick={() => {}} padding={4}> {( <HStack align="center" gap={3} justify="between"> <HStack align="center" gap={2}> <Icon icon={Settings} /> <VStack gap={0}> <Text type="label">Account settings</Text> <Text color="secondary" type="supporting"> Manage your profile and preferences </Text> </VStack> </HStack> <Icon color="secondary" icon={ChevronRight} /> </HStack> )}</ClickableCard><ClickableCard className={cardClassName} label="Open account settings" onClick={undefined} padding={4} href="/settings/account"> {( <HStack align="center" gap={3} justify="between"> <HStack align="center" gap={2}> <Icon icon={Settings} /> <VStack gap={0}> <Text type="label">Account settings</Text> <Text color="secondary" type="supporting"> Manage your profile and preferences </Text> </VStack> </HStack> <Icon color="secondary" icon={ChevronRight} /> </HStack> )}</ClickableCard>Nested Control
Section titled “Nested Control”<ClickableCard {...args}> <VStack gap={3}> <VStack gap={0}> <Text type="label">Quarterly report</Text> <Text color="secondary" type="supporting"> Open the report without capturing its independent actions. </Text> </VStack> <HStack gap={2}> <Button label="Archive report" onClick={() => {}} size="sm" /> </HStack> </VStack></ClickableCard>Disabled
Section titled “Disabled”Account settings are unavailable
<ClickableCard className={cardClassName} label="Open account settings" onClick={() => {}} padding={4} disabledReason="Account settings are unavailable" isDisabled> {( <HStack align="center" gap={3} justify="between"> <HStack align="center" gap={2}> <Icon icon={Settings} /> <VStack gap={0}> <Text type="label">Account settings</Text> <Text color="secondary" type="supporting"> Manage your profile and preferences </Text> </VStack> </HStack> <Icon color="secondary" icon={ChevronRight} /> </HStack> )}</ClickableCard>Read Only
Section titled “Read Only”Account settingsManage your profile and preferences
<ClickableCard className={cardClassName} label="Open account settings" onClick={() => {}} padding={4} isReadOnly> {( <HStack align="center" gap={3} justify="between"> <HStack align="center" gap={2}> <Icon icon={Settings} /> <VStack gap={0}> <Text type="label">Account settings</Text> <Text color="secondary" type="supporting"> Manage your profile and preferences </Text> </VStack> </HStack> <Icon color="secondary" icon={ChevronRight} /> </HStack> )}</ClickableCard>RadioCard examples
Section titled “RadioCard examples”Plan
function PlanSelection({isReadOnly = false}: {isReadOnly?: boolean}) { const [value, setValue] = useState('pro'); const plans = [ {description: 'For personal projects', label: 'Free', value: 'free'}, {description: 'For growing teams', label: 'Pro', value: 'pro'}, { description: 'For organizations at scale', label: 'Enterprise', value: 'enterprise', }, ];
return ( <RadioGroup className={groupClassName} isReadOnly={isReadOnly} label="Plan" onChange={setValue} value={value}> {plans.map(plan => ( <RadioCard key={plan.value} label={plan.label} padding={4} value={plan.value}> <HStack align="center" gap={3} justify="between"> <VStack gap={0}> <Text type="label">{plan.label}</Text> <Text color="secondary" type="supporting"> {plan.description} </Text> </VStack> {plan.value === 'pro' ? ( <Badge color="blue" label="Popular" /> ) : null} </HStack> </RadioCard> ))} </RadioGroup> );}
<PlanSelection />Read Only
Section titled “Read Only”Plan
FreeFor personal projects
ProFor growing teams
PopularEnterpriseFor organizations at scale
function PlanSelection({isReadOnly = false}: {isReadOnly?: boolean}) { const [value, setValue] = useState('pro'); const plans = [ {description: 'For personal projects', label: 'Free', value: 'free'}, {description: 'For growing teams', label: 'Pro', value: 'pro'}, { description: 'For organizations at scale', label: 'Enterprise', value: 'enterprise', }, ];
return ( <RadioGroup className={groupClassName} isReadOnly={isReadOnly} label="Plan" onChange={setValue} value={value}> {plans.map(plan => ( <RadioCard key={plan.value} label={plan.label} padding={4} value={plan.value}> <HStack align="center" gap={3} justify="between"> <VStack gap={0}> <Text type="label">{plan.label}</Text> <Text color="secondary" type="supporting"> {plan.description} </Text> </VStack> {plan.value === 'pro' ? ( <Badge color="blue" label="Popular" /> ) : null} </HStack> </RadioCard> ))} </RadioGroup> );}
<PlanSelection isReadOnly />Disabled
Section titled “Disabled”Plan
<RadioGroup className={groupClassName} label="Plan" onChange={() => {}} value="free"> <RadioCard label="Free" padding={4} value="free"> <Text type="label">Free plan</Text> </RadioCard> <RadioCard isDisabled label="Pro" padding={4} value="pro"> <Text type="label">Pro plan</Text> </RadioCard></RadioGroup>Rounded container surface for grouping related content.
| Prop | Type | Default | Description |
|---|---|---|---|
color | "red" | "orange" | "yellow" | "green" | "teal" | "cyan" | "blue" | "purple" | "pink" | "gray" | — | Decorative surface color. When set, overrides the variant's default background with the corresponding surface color token. |
data-testid | string | — | Test ID applied to the root element. |
padding | 0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 0 | Inner padding step. |
variant | "section" | "default" | "transparent" | "muted" | 'default' | Visual style variant. - default — bordered, rounded container with bg background. - section — flat container with no border or border-radius, for use inside a larger container. - transparent — no background. - muted — subtle background, no visible border. |
CheckboxCard
Section titled “CheckboxCard”A rich Card option that participates in a CheckboxGroup.
| Prop | Type | Default | Description |
|---|---|---|---|
children* | ReactNode | — | Rich content rendered beside the selection indicator. |
className | string | — | Additional CSS class names applied to the card root. |
color | "red" | "orange" | "yellow" | "green" | "teal" | "cyan" | "blue" | "purple" | "pink" | "gray" | — | Decorative surface color. When set, overrides the variant's default background with the corresponding surface color token. |
data-testid | string | — | Test ID applied to the card root. |
isDisabled | boolean | false | Whether this selection item is disabled. |
label* | string | — | Accessible name for the native checkbox or radio. It is not rendered. |
padding | 0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 0 | Inner padding step. |
ref | Ref<HTMLDivElement> | — | Ref forwarded to the card root. |
style | CSSProperties | — | Inline styles applied to the card root. |
value* | string | — | Value represented by this selection item. |
variant | "section" | "default" | "transparent" | "muted" | 'default' | Visual style variant. |
ClickableCard
Section titled “ClickableCard”A Card surface that delegates activation to a real button or link while keeping nested controls independently operable.
| Prop | Type | Default | Description |
|---|---|---|---|
color | "red" | "orange" | "yellow" | "green" | "teal" | "cyan" | "blue" | "purple" | "pink" | "gray" | — | Decorative surface color. When set, overrides the variant's default background with the corresponding surface color token. |
padding | 0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 0 | Inner padding step. |
variant | "section" | "default" | "transparent" | "muted" | 'default' | Visual style variant. |
ref | Ref<HTMLDivElement> | — | Ref forwarded to the outer, non-interactive container. |
children* | ReactNode | — | Non-interactive phrasing content that becomes the action's visual target. |
className | string | — | Additional CSS class names applied to the root element. |
data-testid | string | — | Test ID applied to the root element. |
disabledReason | string | — | Explanation shown in a tooltip and exposed as the control's accessible description while disabled. |
href | string | — | Navigation URL. When provided, the action renders as a link and takes precedence over onClick. |
isDisabled | boolean | false | Whether the action is disabled. Disabled actions remain focusable and use aria-disabled so their reason can be discovered. |
isReadOnly | boolean | false | Whether to preserve the content's appearance while removing interaction. |
label* | string | — | Accessible name for the action. It is not rendered visually. |
onClick | MouseEventHandler<HTMLElement> | — | Called when the action is activated. Also fires for link clicks when href is provided. |
rel | string | — | Link relationship. noopener noreferrer are added for _blank targets. |
style | CSSProperties | — | Inline styles applied to the root element. |
target | string | '_self' | Link browsing-context target. |
RadioCard
Section titled “RadioCard”A rich Card option that participates in a RadioGroup.
| Prop | Type | Default | Description |
|---|---|---|---|
children* | ReactNode | — | Rich content rendered beside the selection indicator. |
className | string | — | Additional CSS class names applied to the card root. |
color | "red" | "orange" | "yellow" | "green" | "teal" | "cyan" | "blue" | "purple" | "pink" | "gray" | — | Decorative surface color. When set, overrides the variant's default background with the corresponding surface color token. |
data-testid | string | — | Test ID applied to the card root. |
isDisabled | boolean | false | Whether this selection item is disabled. |
label* | string | — | Accessible name for the native checkbox or radio. It is not rendered. |
padding | 0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 0 | Inner padding step. |
ref | Ref<HTMLDivElement> | — | Ref forwarded to the card root. |
style | CSSProperties | — | Inline styles applied to the card root. |
value* | string | — | Value represented by this selection item. |
variant | "section" | "default" | "transparent" | "muted" | 'default' | Visual style variant. |