Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/ui/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- `Notice`: Use `Text` component for `Title` and `Description` typography ([#75870](https://github.com/WordPress/gutenberg/pull/75870)).
- `Card`, `CollapsibleCard`: update padding to match legacy `Card` component ([#76368](https://github.com/WordPress/gutenberg/pull/76368)).
- `CollapsibleCard`: move trigger to the header ([#76265](https://github.com/WordPress/gutenberg/pull/76265)).
- `CollapsibleCard`: add animations ([#76378](https://github.com/WordPress/gutenberg/pull/76378)).

## 0.8.0 (2026-03-04)

Expand Down
3 changes: 2 additions & 1 deletion packages/ui/src/card/style.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
.root {
--wp-ui-card-padding: var(--wpds-dimension-padding-2xl);
--wp-ui-card-header-content-gap: var(--wpds-dimension-gap-xl);
--wp-ui-card-header-content-margin: calc(var(--wp-ui-card-header-content-gap) - var(--wp-ui-card-padding));

display: flex;
flex-direction: column;
Expand All @@ -28,7 +29,7 @@
/* Custom vertical gap between header and content */
.header + .content {
padding-block-start: 0;
margin-block-start: calc(var(--wp-ui-card-header-content-gap) - var(--wp-ui-card-padding));
margin-block-start: var(--wp-ui-card-header-content-margin);
}

.fullbleed {
Expand Down
18 changes: 15 additions & 3 deletions packages/ui/src/collapsible-card/content.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
import { forwardRef } from '@wordpress/element';
import clsx from 'clsx';
import * as Card from '../card';
import * as Collapsible from '../collapsible';
import styles from './style.module.css';
import type { ContentProps } from './types';

/**
* The collapsible content area of the card. Hidden when collapsed,
* visible when expanded.
*/
export const Content = forwardRef< HTMLDivElement, ContentProps >(
function CollapsibleCardContent( { render, ...restProps }, ref ) {
function CollapsibleCardContent(
{ className, render, children, ...restProps },
ref
) {
return (
<Collapsible.Panel
ref={ ref }
render={ <Card.Content render={ render } /> }
className={ clsx( styles.content, className ) }
{ ...restProps }
/>
>
<Card.Content
className={ styles[ 'content-inner' ] }
render={ render }
>
{ children }
</Card.Content>
</Collapsible.Panel>
);
}
);
51 changes: 51 additions & 0 deletions packages/ui/src/collapsible-card/stories/index.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,57 @@ export const Disabled: Story = {
},
};

/**
* Multiple collapsible cards stacked vertically, simulating a typical
* settings-panel or FAQ-style layout.
*/
export const Stacked: Story = {
parameters: { controls: { disable: true } },
render: () => (
<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>
),
};

/**
* Visual comparison: a `CollapsibleCard` (open) next to a regular `Card`
* to verify identical spacing and layout.
Expand Down
28 changes: 28 additions & 0 deletions packages/ui/src/collapsible-card/style.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@

/* For an outline that looks like `IconButton`'s */
border-radius: var(--wpds-border-radius-sm);

@media not (prefers-reduced-motion) {
transition: rotate 0.15s ease-out;
}
}

.header[data-panel-open] .header-trigger {
Expand All @@ -33,9 +37,33 @@
.header[data-disabled] .header-trigger {
color: var(--wpds-color-fg-interactive-neutral-disabled);
}

.content {
height: var(--collapsible-panel-height);
overflow: hidden;
margin-block-start: var(--wp-ui-card-header-content-margin);

&[hidden]:not([hidden="until-found"]) {
display: none;
}
Comment on lines +46 to +48

@ciampo ciampo Mar 13, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes to DOM structure and styles actually now make adding hiddenUntilFound trivial (cc @mirka who suggested it in #76280 (review) )

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


&[data-starting-style],
&[data-ending-style] {
height: 0;
}

@media not (prefers-reduced-motion) {
transition: all 150ms ease-out;
}
}

}

@layer wp-ui-compositions {
.content-inner {
padding-block-start: 0;
}

.header {
display: flex;
flex-direction: row;
Expand Down
Loading