@wordpress/dataviews: migrate card layout to @wordpress/ui#76282
Conversation
|
Size Change: +25 kB (+0.33%) Total Size: 7.69 MB
ℹ️ View Unchanged
|
|
Flaky tests detected in 1f53d34. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/23552816891
|
There was a problem hiding this comment.
Pull request overview
Migrates @wordpress/dataviews DataForm card layout (and related stories) from @wordpress/components Card primitives to the newer @wordpress/ui Card and CollapsibleCard, aligning DataViews/DataForm with the Base UI + DS-token-based card implementation.
Changes:
- Refactor DataForm card layout to use
Card.*for standard cards andCollapsibleCard.*for collapsible cards, simplifying toggle/ARIA handling. - Update card layout SCSS to match the new header structure and typography responsibilities.
- Update Storybook stories to use
@wordpress/uicards and note expected visual differences.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/dataviews/src/components/dataform-layouts/card/index.tsx | Migrates DataForm card layout rendering to @wordpress/ui Card/CollapsibleCard and restructures header/body composition. |
| packages/dataviews/src/components/dataform-layouts/card/style.scss | Updates card layout styles for the new header content wrapper and removes old heading mixin usage. |
| packages/dataviews/src/dataviews/stories/with-card.tsx | Updates DataViews “WithCard” story to wrap content with Card.Root/Header/Title/Content. |
| packages/dataviews/src/dataviews/stories/free-composition.tsx | Updates “FreeComposition” story to use @wordpress/ui Card primitives (and drops unsupported variant). |
| packages/dataviews/CHANGELOG.md | Adds an Unreleased entry documenting the migration. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
API-wise this is working well (different combinations can be tested via storybook). |
|
Validation is working as expected as well. |
|
Other than this, this PR looks good to me and it's ready to ship. |
|
Another aspect is that we may want to remove this rule gutenberg/packages/dataviews/src/dataviews/style.scss Lines 130 to 137 in d410e57 |
28d0fbf to
d3d10da
Compare
|
Update: header flickr (customer card):The flicker can be mitigated by setting a minimum height on the card header, although:
For now, I set a min height of card wrapper for dataviews: misaligned (header) & missspaced (dataviews doesn't take the full width):I can see three main differences:
Toggle button label:Opened #76329 to tackle separately Other style changes:I guess that overall differences in card spacing are an expected consequence of swapping card component. On top of individual CHANGELOG entries, we should probably prepare a detailed dev note for the next release, since dataviews/dataforms will go through other similar visual changes, as we refactor to use more Re. the summary badge, I un-did that change — I guess we can refactor all |
Starting without the border seems fine to me. We can add it back later if necessary, but I suppose that would be better handled in a separate PR.
I still think the cleanest solution here is for dataviews to not supply any padding at all. I appreciate this is a tricky change, but its the one that makes the most sense to me. Dataviews should inherit padding from its container, not supply its own imo. Otherwise we're going to run into this issue with all containers; dialogs, tabs, cards, page, accordions, and so on... I don't remember if we added a css variable for padding in dataviews, but perhaps that would be another approach? Then we can set padding to 0 when dataviews is rendered inside a card. Or do the full-bleed thing and set the padding to match the card. |
|
Took the PR for a spin (haven't looked at the code yet).
I'm reading this is intentional change that's part of the Design System, and that's something we'd need to address at some point. 👍 to ship. For reference, these are the differences (left is after, right is before):
Compared to how it worked, this looks shippable to me (left is after, right is before):
|
|
@ciampo I'm trying to understand where this PR stands. With a mindset of solving one problem at a time and iterate quickly, and given these testing scenarios, are there any more changes you'd like to address here? I know we talked about maintaning the exact spacing so this PR is just a replacement from the old to the new card. That approach would make me more comfortable. However, I understand you're arguing these changes are in line with the DS, is that correct? If it is, I'm fine shipping and iterating on the remaining aspects we've discussed (fix mobile view, explore tweaking the spacing via theme tokens/style prop, etc.). |
Next steps before merging:
I updated the PR description with non-blocking follow-up work. What do you think? |
431bee1 to
52dcd6b
Compare
52dcd6b to
d91d92c
Compare
… move this PR's entry to "unreleased"
Made-with: Cursor
…om assistive technology content)
be32cc9 to
25560ed
Compare
|
DataViews within Card ✅ It's now working well, other than design decisions (different spacing, lack of separator between header/body).
DataForm Card Layout ✅ Screen.Recording.2026-03-25.at.16.08.02.mov |
|
|
||
| ### Enhancements | ||
|
|
||
| - DataForm: Migrate card layout to use `Card` and `CollapsibleCard` from `@wordpress/ui`. [#76282](https://github.com/WordPress/gutenberg/pull/76282) |
There was a problem hiding this comment.
Can we mark this as a breaking change (e.g., use the new card component with dataviews and the removal of card-related styles)?
|
This is working great and code-wise is also ready. There's only this bit to update, but happy to pre-approve. |
* Refactor dataform card layout to use @wordpress/ui Card and CollapsibleCard Replace @wordpress/components Card, CardBody, CardHeader with @wordpress/ui Card.Root, Card.Header, Card.Content, Card.Title and CollapsibleCard.Root, CollapsibleCard.Header, CollapsibleCard.Content. The collapsible behavior previously implemented manually with useState and toggle callbacks is now delegated to CollapsibleCard's built-in defaultOpen/onOpenChange API. The header layout (title, summary fields, validation badge) and the body content are extracted into dedicated sub-components for clarity. The card-specific SCSS is simplified by removing the heading-large mixin (now handled by Card.Title) and the header-label class. Made-with: Cursor * Migrate DataViews stories to use @wordpress/ui Card Update with-card.tsx and free-composition.tsx stories to use Card.Root, Card.Header, Card.Content, and Card.Title from @wordpress/ui instead of Card, CardHeader, and CardBody from @wordpress/components. Made-with: Cursor * Update dataviews CHANGELOG Made-with: Cursor * Fix header layout and isOpened sync in card layout Address review feedback: - Wrap header content (title, validation badge, summary fields) in a flex container to preserve the horizontal layout that existed before the refactoring. - Use controlled `open` prop instead of `defaultOpen` on CollapsibleCard, and restore the useEffect that syncs local state when the isOpened layout config changes externally (e.g. via Storybook controls). Made-with: Cursor * Add PR link to CHANGELOG entry Made-with: Cursor * Tweak badge in Storybook example * Avoid UI jumps when collapsing/expanding a header with badge * Undo badge swap (out of scope) * Smaller min height * Use fullbleed, add todo comment to css * remove custom render function * Allow Card in the `use-recommended-components` ESLint rule * Remove css overrides targeting legacy Card component * Allow Card in the `use-recommended-components` ESLint rule * CHANGELOG: consolidate enhancements sections within the same release, move this PR's entry to "unreleased" * Alphabetical order * Restore comments removed out of scope Made-with: Cursor * Disable Card and CollapsibleCard usage lint errors individually * Use stack * Use header badge and summary to describe the header (removing them from assistive technology content) * Avoid context for fields * Mark as breaking change, review entry --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org>
* Refactor dataform card layout to use @wordpress/ui Card and CollapsibleCard Replace @wordpress/components Card, CardBody, CardHeader with @wordpress/ui Card.Root, Card.Header, Card.Content, Card.Title and CollapsibleCard.Root, CollapsibleCard.Header, CollapsibleCard.Content. The collapsible behavior previously implemented manually with useState and toggle callbacks is now delegated to CollapsibleCard's built-in defaultOpen/onOpenChange API. The header layout (title, summary fields, validation badge) and the body content are extracted into dedicated sub-components for clarity. The card-specific SCSS is simplified by removing the heading-large mixin (now handled by Card.Title) and the header-label class. Made-with: Cursor * Migrate DataViews stories to use @wordpress/ui Card Update with-card.tsx and free-composition.tsx stories to use Card.Root, Card.Header, Card.Content, and Card.Title from @wordpress/ui instead of Card, CardHeader, and CardBody from @wordpress/components. Made-with: Cursor * Update dataviews CHANGELOG Made-with: Cursor * Fix header layout and isOpened sync in card layout Address review feedback: - Wrap header content (title, validation badge, summary fields) in a flex container to preserve the horizontal layout that existed before the refactoring. - Use controlled `open` prop instead of `defaultOpen` on CollapsibleCard, and restore the useEffect that syncs local state when the isOpened layout config changes externally (e.g. via Storybook controls). Made-with: Cursor * Add PR link to CHANGELOG entry Made-with: Cursor * Tweak badge in Storybook example * Avoid UI jumps when collapsing/expanding a header with badge * Undo badge swap (out of scope) * Smaller min height * Use fullbleed, add todo comment to css * remove custom render function * Allow Card in the `use-recommended-components` ESLint rule * Remove css overrides targeting legacy Card component * Allow Card in the `use-recommended-components` ESLint rule * CHANGELOG: consolidate enhancements sections within the same release, move this PR's entry to "unreleased" * Alphabetical order * Restore comments removed out of scope Made-with: Cursor * Disable Card and CollapsibleCard usage lint errors individually * Use stack * Use header badge and summary to describe the header (removing them from assistive technology content) * Avoid context for fields * Mark as breaking change, review entry --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org>
* Refactor dataform card layout to use @wordpress/ui Card and CollapsibleCard Replace @wordpress/components Card, CardBody, CardHeader with @wordpress/ui Card.Root, Card.Header, Card.Content, Card.Title and CollapsibleCard.Root, CollapsibleCard.Header, CollapsibleCard.Content. The collapsible behavior previously implemented manually with useState and toggle callbacks is now delegated to CollapsibleCard's built-in defaultOpen/onOpenChange API. The header layout (title, summary fields, validation badge) and the body content are extracted into dedicated sub-components for clarity. The card-specific SCSS is simplified by removing the heading-large mixin (now handled by Card.Title) and the header-label class. Made-with: Cursor * Migrate DataViews stories to use @wordpress/ui Card Update with-card.tsx and free-composition.tsx stories to use Card.Root, Card.Header, Card.Content, and Card.Title from @wordpress/ui instead of Card, CardHeader, and CardBody from @wordpress/components. Made-with: Cursor * Update dataviews CHANGELOG Made-with: Cursor * Fix header layout and isOpened sync in card layout Address review feedback: - Wrap header content (title, validation badge, summary fields) in a flex container to preserve the horizontal layout that existed before the refactoring. - Use controlled `open` prop instead of `defaultOpen` on CollapsibleCard, and restore the useEffect that syncs local state when the isOpened layout config changes externally (e.g. via Storybook controls). Made-with: Cursor * Add PR link to CHANGELOG entry Made-with: Cursor * Tweak badge in Storybook example * Avoid UI jumps when collapsing/expanding a header with badge * Undo badge swap (out of scope) * Smaller min height * Use fullbleed, add todo comment to css * remove custom render function * Allow Card in the `use-recommended-components` ESLint rule * Remove css overrides targeting legacy Card component * Allow Card in the `use-recommended-components` ESLint rule * CHANGELOG: consolidate enhancements sections within the same release, move this PR's entry to "unreleased" * Alphabetical order * Restore comments removed out of scope Made-with: Cursor * Disable Card and CollapsibleCard usage lint errors individually * Use stack * Use header badge and summary to describe the header (removing them from assistive technology content) * Avoid context for fields * Mark as breaking change, review entry --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: oandregal <oandregal@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org>
| @use "@wordpress/base-styles/variables" as *; | ||
| @use "@wordpress/base-styles/mixins" as *; | ||
|
|
||
| .dataforms-layouts-card__field-header-label { |
There was a problem hiding this comment.
@ciampo I just noticed that this removal is generating a problem, and as a result having these headers to be 13px. The problem is that, right now, the tokens are not there if the extender is not using the ThemeProvider (which I think at this point is not ready to be used by extenders). Would it be worth it to restore this with a TODO comment until the tokens are available?
There was a problem hiding this comment.
I tried the Playground link in that PR, and I'm seeing that it's still using the Card components from @wordpress/components, not the @wordpress/ui ones we replaced them with here.
Are you seeing a version where it's actually using in the @wordpress/ui Cards? We inject fallback values into the CSS var()s at build time, so @wordpress/ui should be safe to use without ThemeProvider or other special stylesheet setup (see for example the CSS var fallbacks in packages/ui/build-module/card/content.mjs). Let us know if that doesn't seem to be the case.










What?
Part of #76100
Migrate the dataform card layout component and DataViews story files from using
Card,CardBody,CardHeaderfrom@wordpress/componentsto the newerCardandCollapsibleCardfrom@wordpress/ui.Why?
The
@wordpress/uipackage recently addedCardandCollapsibleCardcomponents (#76252), built on Base UI with CSS modules and design system tokens. This PR adopts them in the@wordpress/dataviewspackage, which is one of the first consumers.How?
Expand for more details
Main component (
dataform-layouts/card/index.tsx)Card.Root,Card.Header,Card.Content, andCard.Titlefrom@wordpress/uiCollapsibleCard.Root,CollapsibleCard.Header,CollapsibleCard.Contentfrom@wordpress/ui, which handles expand/collapse behavior internally via Base UI's Collapsible primitivesHeaderContentsub-component wrapped in a flex container for proper horizontal layoutBodyContentsub-componentopenprop is used onCollapsibleCard.Rootto keep local state in sync (needed for summary field visibility rules anduseReportValidity)aria-expanded/aria-controls/aria-labelledbyattributes — these are now handled by Base UI's Collapsible@wordpress/composeuseInstanceIddependency (no longer needed)@wordpress/iconsdependency (chevron icons now handled by CollapsibleCard)@wordpress/componentsButtondependency (toggle button now handled by CollapsibleCard)Card styles (
card/style.scss)heading-large()mixin — replaced byCard.Title's built-in typography.dataforms-layouts-card__field-header-labelclass.dataforms-layouts-card__field-header-contentflex container for the header row layoutDataViews styles (
dataviews/style.scss).components-card__body:has(> .dataviews-wrapper)CSS override block, which appliedpaddingandoverflow: hiddento the legacy@wordpress/componentsCardBody. This override is no longer needed since the@wordpress/uiCard uses CSS modules with different class names (style.contentinstead ofcomponents-card__body), and no production code wraps DataViews inside a legacyCardBody.Story files
with-card.tsx: Migrated fromCard/CardHeader/CardBodytoCard.Root/Card.Header/Card.Title/Card.Content/Card.FullBleedfree-composition.tsx: Migrated similarly. Note: thevariant="secondary"prop on one Card instance is dropped since@wordpress/uiCard doesn't support variants — this is an expected visual change aligned with the design systemESLint rule
Cardto the allowlist in theuse-recommended-componentsESLint rule, so that importingCardfrom@wordpress/uino longer triggers a lint warning.Bundle size note
This PR increases the bundle size of
block-editor,editor, andedit-siteby ~35-40 kB each. This is expected: the old code importedCard/CardBody/CardHeaderfrom@wordpress/components(which is externalized viawpScript: true), while the new code imports from@wordpress/ui(which is bundled inline viawpScript: false). The@wordpress/uiCard/CollapsibleCard components and their@base-ui/reactdependencies now get included in each consumer's bundle. This is an inherent characteristic of@wordpress/ui's current packaging and will be resolved when@wordpress/uitransitions towpScript: true.Testing Instructions
npx jest --config test/unit/jest.config.js packages/dataviews— all 221 tests should passDataForm / LayoutCardstory and test all Storybook control combinations (withHeader,isCollapsible,isOpened,withSummary)DataViews / WithCardstory — verify card wrapping withCard.FullBleedDataViews / FreeCompositionstory — verify cards in custom layoutAI Tooling
Cursor + Claude Opus 4.6
Next Steps
@wordpress/componentswith@wordpress/uiversion, including the ones used in dataviews/dataforms, both source code and Storybook examples