CollapsibleCard

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

View on Storybook

View source on GitHub

Import

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

Props

NameTypeDefaultRequiredDescription
classNamestring

CSS class name to apply to the element.

styleReact.CSSProperties

CSS style to apply to the element.

render| ComponentRenderFn< HTMLAttributesWithRef > | React.ReactElement< Record< string, unknown > >

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

childrenReactNode

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

openboolean

Whether the collapsible panel is currently open (controlled).

To render an uncontrolled collapsible card, use defaultOpen instead.

defaultOpenboolean

Whether the collapsible panel is initially open (uncontrolled). @default false

onOpenChange( open: boolean ) => void

Event handler called when the panel is opened or closed.

disabledboolean

Whether the component should ignore user interaction. @default false

Examples

Default

A collapsible card that is open by default.

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

Initially Opened

A collapsible card that starts collapsed.

const InitiallyOpened = () => <CollapsibleCard.Root defaultOpen>(<>
        <CollapsibleCard.Header>
            <Card.Title>Collapsed by default</Card.Title>
        </CollapsibleCard.Header>
        <CollapsibleCard.Content>
            <Text>This content was hidden until you expanded it.</Text>
        </CollapsibleCard.Content>
    </>)</CollapsibleCard.Root>;

Disabled

A disabled collapsible card cannot be toggled by the user.

const Disabled = () => <CollapsibleCard.Root disabled>(<>
        <CollapsibleCard.Header>
            <Card.Title>Disabled card</Card.Title>
        </CollapsibleCard.Header>
        <CollapsibleCard.Content>
            <Text>The header is not interactive when disabled.</Text>
        </CollapsibleCard.Content>
    </>)</CollapsibleCard.Root>;

Stacked

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

const Stacked = () => (
    <div
        style={ {
            display: 'flex',
            flexDirection: 'column',
            gap: 'var(--wpds-dimension-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>
                        Configure all { title.toLowerCase() } settings for
                        your site. Changes here affect how your site behaves
                        across all pages and posts.
                    </Text>
                    <Text>
                        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>
                        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>
        ) ) }
    </div>
);

With Heading Element

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 = () => (
    <div
        style={ {
            display: 'flex',
            flexDirection: 'column',
            gap: 'var(--wpds-dimension-gap-lg)',
        } }
    >
        <CollapsibleCard.Root>
            <CollapsibleCard.Header render={ <h2 /> }>
                <Card.Title>Heading level 2</Card.Title>
            </CollapsibleCard.Header>
            <CollapsibleCard.Content>
                <Text>
                    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>
                    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>
                    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>
    </div>
);

With Header Description

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

const WithHeaderDescription = ( { open, defaultOpen, onOpenChange, disabled, ...restArgs } ) => (
    <CollapsibleCard.Root
        open={ open }
        defaultOpen={ defaultOpen }
        onOpenChange={ onOpenChange }
        disabled={ disabled }
        { ...restArgs }
    >
        <CollapsibleCard.Header>
            <Stack justify="space-between">
                <Card.Title>Settings</Card.Title>
                <CollapsibleCard.HeaderDescription>
                    <span
                        style={ {
                            fontSize: 'var(--wpds-typography-font-size-sm)',
                            color: 'var(--wpds-color-fg-content-neutral-weak)',
                        } }
                    >
                        3 items configured
                    </span>
                </CollapsibleCard.HeaderDescription>
            </Stack>
        </CollapsibleCard.Header>
        <CollapsibleCard.Content>
            <Text>
                The header description provides supplementary context to the
                trigger button. Assistive technologies will announce the
                description alongside the button label.
            </Text>
        </CollapsibleCard.Content>
    </CollapsibleCard.Root>
);

Compared To Card

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

const ComparedToCard = ( { open, defaultOpen, onOpenChange, disabled, ...restArgs } ) => (
    <div
        style={ {
            display: 'flex',
            flexDirection: 'column',
            gap: 'var( --wpds-dimension-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>
                    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>
                    Content should align with the collapsible card above.
                </Text>
            </Card.Content>
        </Card.Root>
    </div>
);