CollapsibleCard

A card that can be expanded and collapsed. When collapsed, only the header is visible.

import { CollapsibleCard } from '@wordpress/ui';

View on Storybook

View source on GitHub

PropsPermalink to this section

NameDefaultDescription
children

ReactNode

The content to be rendered inside the collapsible card. Should include CollapsibleCard.Header and CollapsibleCard.Content.

open

boolean

Whether the collapsible panel is currently open (controlled).

To render an uncontrolled collapsible card, use defaultOpen instead.

defaultOpenfalse

boolean

Whether the collapsible panel is initially open (uncontrolled).

onOpenChange

(open: boolean) => void

Event handler called when the panel is opened or closed.

disabledfalse

boolean

Whether the component should ignore user interaction.

className

string

CSS class name to apply to the element.

style

CSSProperties

CSS style to apply to the element.

render

ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

Replaces the component’s default HTML element using a given React element, or a function that returns a React element.

ExamplesPermalink to this section

DefaultPermalink to this section

A collapsible card that is open by default.

const Default = () => <CollapsibleCard.Root>{[
        <CollapsibleCard.Header key="header">
            <Card.Title>Collapsible card (closed by default)</Card.Title>
        </CollapsibleCard.Header>,
        <CollapsibleCard.Content key="content">
            <Text render={ <p /> }>
                This is the collapsible content area. It can contain any
                elements, just like a regular Card.Content.
            </Text>
            <Text render={ <p /> }>
                When collapsed, only the header and chevron are visible.
            </Text>
        </CollapsibleCard.Content>,
    ]}</CollapsibleCard.Root>;

Initially OpenedPermalink to this section

A collapsible card that starts collapsed.

const InitiallyOpened = () => <CollapsibleCard.Root defaultOpen>{[
        <CollapsibleCard.Header key="header">
            <Card.Title>Collapsed by default</Card.Title>
        </CollapsibleCard.Header>,
        <CollapsibleCard.Content key="content">
            <Text render={ <p /> }>
                This content was hidden until you expanded it.
            </Text>
        </CollapsibleCard.Content>,
    ]}</CollapsibleCard.Root>;

DisabledPermalink to this section

A disabled collapsible card cannot be toggled by the user.

const Disabled = () => <CollapsibleCard.Root disabled>{[
        <CollapsibleCard.Header key="header">
            <Card.Title>Disabled card</Card.Title>
        </CollapsibleCard.Header>,
        <CollapsibleCard.Content key="content">
            <Text render={ <p /> }>
                The header is not interactive when disabled.
            </Text>
        </CollapsibleCard.Content>,
    ]}</CollapsibleCard.Root>;

StackedPermalink to this section

Multiple collapsible cards stacked vertically, simulating a typical settings-panel or FAQ-style layout.

const Stacked = () => (
    <Stack direction="column" gap="lg">
        { [
            'General',
            'Advanced',
            'Accessibility',
            'Performance',
            'Privacy',
            'Notifications',
        ].map( ( title ) => (
            <CollapsibleCard.Root key={ title }>
                <CollapsibleCard.Header>
                    <Card.Title>{ title }</Card.Title>
                </CollapsibleCard.Header>
                <CollapsibleCard.Content>
                    <Text render={ <p /> }>
                        Configure all { title.toLowerCase() } settings for
                        your site. Changes here affect how your site behaves
                        across all pages and posts.
                    </Text>
                    <Text render={ <p /> }>
                        Review each option carefully before saving. Some
                        changes may require a page reload to take effect.
                        Hover over individual options for more details about
                        what they control.
                    </Text>
                    <Text render={ <p /> }>
                        If you&apos;re unsure about a setting, you can
                        always reset to defaults using the button at the
                        bottom of this section. Your previous configuration
                        will be saved as a backup.
                    </Text>
                </CollapsibleCard.Content>
            </CollapsibleCard.Root>
        ) ) }
    </Stack>
);

With Heading ElementPermalink to this section

CollapsibleCard.Header renders a <div> wrapper by default. Pass an <h1><h6> React element to the render prop to wrap the trigger in a heading and contribute to the document outline. The right level depends on the surrounding outline, so the consumer is expected to opt in.

const WithHeadingElement = () => (
    <Stack direction="column" gap="lg">
        <CollapsibleCard.Root>
            <CollapsibleCard.Header render={ <h2 /> }>
                <Card.Title>Heading level 2</Card.Title>
            </CollapsibleCard.Header>
            <CollapsibleCard.Content>
                <Text render={ <p /> }>
                    The wrapper renders as an h2 element when the consumer
                    passes an h2 React element to the render prop.
                </Text>
            </CollapsibleCard.Content>
        </CollapsibleCard.Root>
        <CollapsibleCard.Root>
            <CollapsibleCard.Header render={ <h3 /> }>
                <Card.Title>Heading level 3</Card.Title>
            </CollapsibleCard.Header>
            <CollapsibleCard.Content>
                <Text render={ <p /> }>
                    Pass any of h1–h6 to choose the level that fits the
                    surrounding document outline.
                </Text>
            </CollapsibleCard.Content>
        </CollapsibleCard.Root>
        <CollapsibleCard.Root>
            <CollapsibleCard.Header>
                <Card.Title>No heading (default)</Card.Title>
            </CollapsibleCard.Header>
            <CollapsibleCard.Content>
                <Text render={ <p /> }>
                    Without a render prop, the header wraps the trigger in a
                    plain div and does not contribute to the document
                    outline.
                </Text>
            </CollapsibleCard.Content>
        </CollapsibleCard.Root>
    </Stack>
);

With Header DescriptionPermalink to this section

A collapsible card with a HeaderDescription that provides supplementary information (e.g. status, summary) as an aria-describedby relationship.

const WithHeaderDescription = ( {
    open: _open,
    defaultOpen: _defaultOpen,
    onOpenChange: _onOpenChange,
    ...restArgs
} ) => (
    <CollapsibleCard.Root { ...restArgs }>
        <CollapsibleCard.Header>
            <Stack justify="space-between" align="center">
                <Card.Title>Settings</Card.Title>
                <CollapsibleCard.HeaderDescription>
                    3 items configured
                </CollapsibleCard.HeaderDescription>
            </Stack>
        </CollapsibleCard.Header>
        <CollapsibleCard.Content>
            <Text render={ <p /> }>
                The description appears next to the title.
            </Text>
        </CollapsibleCard.Content>
    </CollapsibleCard.Root>
);

Compared To CardPermalink to this section

Visual comparison: a CollapsibleCard (open) next to a regular Card to verify identical spacing and layout.

const ComparedToCard = ( { open, defaultOpen, onOpenChange, disabled, ...restArgs } ) => (
    <Stack direction="column" gap="lg">
        <CollapsibleCard.Root
            open={ open }
            defaultOpen={ defaultOpen }
            onOpenChange={ onOpenChange }
            disabled={ disabled }
            { ...restArgs }
        >
            <CollapsibleCard.Header>
                <Card.Title>CollapsibleCard (open)</Card.Title>
            </CollapsibleCard.Header>
            <CollapsibleCard.Content>
                <Text render={ <p /> }>
                    Content should align with the regular card below.
                </Text>
            </CollapsibleCard.Content>
        </CollapsibleCard.Root>
        <Card.Root { ...restArgs }>
            <Card.Header>
                <Card.Title>Regular Card</Card.Title>
            </Card.Header>
            <Card.Content>
                <Text render={ <p /> }>
                    Content should align with the collapsible card above.
                </Text>
            </Card.Content>
        </Card.Root>
    </Stack>
);

Full Bleed Cover With HeaderPermalink to this section

When Card.FullBleed is the sole child of CollapsibleCard.Content and a header sits above it, the media bumps against the card&apos;s side and bottom edges while the header retains its normal padding. (Unlike a plain Card, a header is always required here for the collapse trigger — see Card stories for a body-only FullBleedCoverOnly example.)

const FullBleedCoverWithHeader = () => <CollapsibleCard.Root defaultOpen>{[
        <CollapsibleCard.Header key="header">
            <Card.Title>Card title</Card.Title>
        </CollapsibleCard.Header>,
        <CollapsibleCard.Content key="content">
            <Card.FullBleed>
                <div
                    style={ {
                        height: 180,
                        background:
                            'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
                    } }
                />
            </Card.FullBleed>
        </CollapsibleCard.Content>,
    ]}</CollapsibleCard.Root>;

With Full BleedPermalink to this section

Card.FullBleed breaks out of the content padding to span edge-to-edge. Useful for images, dividers, or embedded content inside the collapsible region.

const WithFullBleed = () => <CollapsibleCard.Root defaultOpen>{[
        <CollapsibleCard.Header key="header">
            <Card.Title>Featured image</Card.Title>
        </CollapsibleCard.Header>,
        <CollapsibleCard.Content
            render={ <Stack direction="column" gap="lg" /> }
            key="content"
        >
            <Card.FullBleed>
                <div
                    style={ {
                        height: 160,
                        background:
                            'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
                    } }
                />
            </Card.FullBleed>
            <Text render={ <p /> }>Content below the full-bleed area.</Text>
        </CollapsibleCard.Content>,
    ]}</CollapsibleCard.Root>;