newspack-components 4.10.0 → 4.12.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/DEVELOPMENT.md +80 -38
  3. package/dist/cjs/breadcrumbs/index.js +1 -0
  4. package/dist/cjs/breadcrumbs/style.scss +3 -10
  5. package/dist/cjs/card/style-core.scss +1 -1
  6. package/dist/cjs/card-sortable-list/index.js +23 -12
  7. package/dist/cjs/card-sortable-list/index.test.js +21 -0
  8. package/dist/cjs/card-sortable-list/style.scss +8 -0
  9. package/dist/cjs/drawer/body.js +4 -6
  10. package/dist/cjs/drawer/content.js +7 -37
  11. package/dist/cjs/drawer/footer.js +10 -1
  12. package/dist/cjs/drawer/header.js +9 -1
  13. package/dist/cjs/drawer/index.test.js +3 -4
  14. package/dist/cjs/drawer/slots.test.js +25 -67
  15. package/dist/cjs/drawer/style.scss +0 -18
  16. package/dist/cjs/index.js +14 -0
  17. package/dist/cjs/page/index.js +10 -2
  18. package/dist/cjs/page/style.scss +24 -2
  19. package/dist/cjs/reorder-modal/index.js +521 -0
  20. package/dist/cjs/reorder-modal/index.test.js +1223 -0
  21. package/dist/cjs/reorder-modal/style.scss +114 -0
  22. package/dist/cjs/tabbed-navigation/style.scss +5 -0
  23. package/dist/cjs/tooltip-badge/index.js +50 -0
  24. package/dist/cjs/tooltip-badge/index.test.js +30 -0
  25. package/dist/cjs/wizard/index.js +21 -8
  26. package/dist/cjs/wizard/index.test.js +78 -0
  27. package/dist/cjs/wizard/store/index.js +2 -1
  28. package/dist/esm/breadcrumbs/index.js +1 -0
  29. package/dist/esm/breadcrumbs/style.scss +3 -10
  30. package/dist/esm/card/style-core.scss +1 -1
  31. package/dist/esm/card-sortable-list/index.js +25 -13
  32. package/dist/esm/card-sortable-list/index.test.js +21 -0
  33. package/dist/esm/card-sortable-list/style.scss +8 -0
  34. package/dist/esm/drawer/body.js +4 -5
  35. package/dist/esm/drawer/content.js +7 -36
  36. package/dist/esm/drawer/footer.js +10 -1
  37. package/dist/esm/drawer/header.js +9 -1
  38. package/dist/esm/drawer/index.test.js +3 -4
  39. package/dist/esm/drawer/slots.test.js +25 -67
  40. package/dist/esm/drawer/style.scss +0 -18
  41. package/dist/esm/index.js +2 -0
  42. package/dist/esm/page/index.js +10 -2
  43. package/dist/esm/page/style.scss +24 -2
  44. package/dist/esm/reorder-modal/index.js +514 -0
  45. package/dist/esm/reorder-modal/index.test.js +1224 -0
  46. package/dist/esm/reorder-modal/style.scss +114 -0
  47. package/dist/esm/tabbed-navigation/style.scss +5 -0
  48. package/dist/esm/tooltip-badge/index.js +43 -0
  49. package/dist/esm/tooltip-badge/index.test.js +26 -0
  50. package/dist/esm/wizard/index.js +23 -12
  51. package/dist/esm/wizard/index.test.js +78 -0
  52. package/dist/esm/wizard/store/index.js +2 -1
  53. package/package.json +2 -2
  54. package/src/breadcrumbs/index.js +1 -1
  55. package/src/breadcrumbs/style.scss +3 -10
  56. package/src/card/style-core.scss +1 -1
  57. package/src/card-form/README.md +2 -2
  58. package/src/card-sortable-list/index.test.js +13 -0
  59. package/src/card-sortable-list/index.tsx +31 -12
  60. package/src/card-sortable-list/style.scss +8 -0
  61. package/src/drawer/README.md +10 -16
  62. package/src/drawer/body.tsx +4 -5
  63. package/src/drawer/content.tsx +7 -33
  64. package/src/drawer/footer.tsx +8 -1
  65. package/src/drawer/header.tsx +8 -1
  66. package/src/drawer/index.test.js +3 -4
  67. package/src/drawer/slots.test.js +14 -48
  68. package/src/drawer/style.scss +0 -18
  69. package/src/drawer/types.ts +8 -3
  70. package/src/index.js +2 -0
  71. package/src/page/index.js +7 -3
  72. package/src/page/style.scss +24 -2
  73. package/src/reorder-modal/index.js +484 -0
  74. package/src/reorder-modal/index.test.js +566 -0
  75. package/src/reorder-modal/style.scss +114 -0
  76. package/src/tabbed-navigation/style.scss +5 -0
  77. package/src/tooltip-badge/index.test.js +24 -0
  78. package/src/tooltip-badge/index.tsx +40 -0
  79. package/src/wizard/index.js +25 -14
  80. package/src/wizard/index.test.js +38 -0
  81. package/src/wizard/store/index.js +1 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,28 @@
1
+ # newspack-components [4.12.0-alpha.1](https://github.com/Automattic/newspack-workspace/compare/newspack-components@4.11.0...newspack-components@4.12.0-alpha.1) (2026-10-15)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **components:** fit the page header and tabs on mobile (DSGNEWS-237, [#1263](https://github.com/Automattic/newspack-workspace/issues/1263)) ([e5b89f7](https://github.com/Automattic/newspack-workspace/commit/e5b89f719b7d22cd2be0aef33f0d1f9773fadb06))
7
+ * **components:** lay out the drawer with Stack and end-align its actions ([#1258](https://github.com/Automattic/newspack-workspace/issues/1258)) ([e8dfd37](https://github.com/Automattic/newspack-workspace/commit/e8dfd3766e8a12ffd584a6be7f5352aff9a53f19))
8
+
9
+
10
+ ### Features
11
+
12
+ * **content-gate:** reorganize Access Control into tabs ([#1164](https://github.com/Automattic/newspack-workspace/issues/1164)) ([f0622f2](https://github.com/Automattic/newspack-workspace/commit/f0622f2a59bdfd0a7064b551ddd2a7a2895281d2))
13
+
14
+
15
+ ### Dependencies
16
+
17
+ * **newspack-icons:** upgraded to 1.3.0-alpha.1
18
+
19
+ # newspack-components [4.11.0](https://github.com/Automattic/newspack-workspace/compare/newspack-components@4.10.0...newspack-components@4.11.0) (2026-10-14)
20
+
21
+
22
+ ### Features
23
+
24
+ * **newsletters:** show premium lists in the subscription form ([#1291](https://github.com/Automattic/newspack-workspace/issues/1291)) ([456d762](https://github.com/Automattic/newspack-workspace/commit/456d762ba465aafc6e5be08ed47836acafaad1a6))
25
+
1
26
  # newspack-components [4.10.0](https://github.com/Automattic/newspack-workspace/compare/newspack-components@4.9.2...newspack-components@4.10.0) (2026-10-12)
2
27
 
3
28
 
package/DEVELOPMENT.md CHANGED
@@ -22,7 +22,7 @@ Comprehensive developer guidelines for working with the Newspack Components pack
22
22
 
23
23
  This package provides custom React components designed specifically for Newspack backend/admin interfaces (wizards, settings pages, etc.). These components are built on top of WordPress components and provide Newspack-specific functionality, styling, and patterns.
24
24
 
25
- **In short:** For backend/admin screens use Newspack components first (Card, ActionCard, SectionHeader, etc.), fall back to WordPress components when needed, and follow the spacing scale and hierarchy patterns so UIs stay consistent. For block editor UI use WordPress components (and `AutocompleteTokenField` only when you need autocomplete). For reader-facing UI use Newspack UI or theme components, not this package.
25
+ **In short:** For backend/admin screens use `@wordpress/ui` for primitives (`Stack`, `Card`, `Badge`, `Text`), Newspack components for Newspack patterns (SectionHeader, ActionCard, EmptyState, etc.), and `@wordpress/components` for what neither covers. Follow the spacing scale and hierarchy patterns so UIs stay consistent. For block editor UI use WordPress components (and `AutocompleteTokenField` only when you need autocomplete). For reader-facing UI use Newspack UI or theme components, not this package.
26
26
 
27
27
  **Design-wise:** Backend UIs should feel consistent with the WordPress admin, with clear visual hierarchy (section → card → controls) and predictable spacing. Use the same components and spacing scale across wizards so design and code stay aligned; when introducing a new pattern or layout, align with design (and designer review) before implementing.
28
28
 
@@ -31,8 +31,9 @@ This package provides custom React components designed specifically for Newspack
31
31
  ### Decision Tree
32
32
 
33
33
  **Backend/Admin UI (Wizards, Settings Pages):**
34
- - ✅ **Use Newspack components first** - Check if a Newspack component exists for your use case
35
- - ⚠️ **Fallback to WordPress components** - If no Newspack component exists, use `@wordpress/components`
34
+ - ✅ **Use `@wordpress/ui` for primitives** - Layout, surfaces, badges and text come from the WordPress design system: `Stack`, `Card`, `Badge`, `Text`, `Link`, `Popover`, `VisuallyHidden`
35
+ - ✅ **Use Newspack components for Newspack patterns** - Check if a Newspack component exists for your use case; most new ones are built on `@wordpress/ui`
36
+ - ⚠️ **Fallback to WordPress components** - If neither covers it, use `@wordpress/components` (form controls, core `Notice`, `DropdownMenu`)
36
37
  - Examples: Dashboard, Settings, Audience Management, Setup Wizard
37
38
 
38
39
  **Gutenberg Blocks:**
@@ -49,17 +50,21 @@ This package provides custom React components designed specifically for Newspack
49
50
  Follow this step-by-step process when selecting a component:
50
51
 
51
52
  1. **Check Newspack components first**
52
- - Review the [Available Components](#available-components) list below
53
+ - Review the [Available Components](#available-components) list below, skipping entries marked legacy or deprecated
53
54
  - Check `packages/components/src/` directory for component implementations
54
55
  - Newspack components are optimized for backend/admin workflows
55
56
 
56
- 2. **If not available, use WordPress components**
57
+ 2. **For primitives, use `@wordpress/ui`**
58
+ - `Stack`, `Card`, `Badge`, `Text`, `Link`, `Popover`, `Collapsible`, `Tabs`, `VisuallyHidden`
59
+ - Import them directly from `@wordpress/ui`; see [From @wordpress/ui](#from-wordpressui)
60
+
61
+ 3. **If not available, use WordPress components**
57
62
  - Visit [@wordpress/components Storybook](https://wordpress.github.io/gutenberg/?path=/docs/docs-introduction--page)
58
63
  - Check [@wordpress/components npm package](https://www.npmjs.com/package/@wordpress/components)
59
64
  - Cross-reference Storybook documentation and NPM package code with the version of `@wordpress/components` installed via `package.json` to confirm that the installed package contains the expected component(s)
60
65
  - WordPress components provide standard admin UI patterns
61
66
 
62
- 3. **If still not available, flag for designer review**
67
+ 4. **If still not available, flag for designer review**
63
68
  - Use a placeholder component and request a new component design from the design team
64
69
  - Don't create new components without designer review
65
70
  - Once approved, follow existing Newspack component patterns (see [Component Patterns](#component-patterns))
@@ -68,17 +73,31 @@ Follow this step-by-step process when selecting a component:
68
73
 
69
74
  ## Design & layout at a glance
70
75
 
71
- When building a screen, use the **spacing scale** (8px unit: 16, 24, 32, 48, 64) and prefer **VStack** for vertical stacks and **HStack** for related items in a row; use **Grid** for real multi-column layouts. Structure content as **SectionHeader → Card → ActionCard → controls**, with **Divider** between sections and primary actions in **`.newspack-buttons-card`**. Use the same **breakpoints** (e.g. 744px, 1054px) as existing components. Full detail: [Spacing scale](#spacing-scale-design-system), [Layout (HStack / VStack / Grid)](#layout-when-to-use-hstack-vstack-grid), [Responsive breakpoints](#responsive-breakpoints), [Visual hierarchy patterns](#visual-hierarchy-patterns), [Component states](#component-states). For code examples by context and wizard patterns, see [Usage](#usage).
76
+ When building a screen, use the **spacing scale** (8px unit: 16, 24, 32, 48) with **48px** between sections, and use **`Stack`** from `@wordpress/ui` for rows and columns of items; use **Grid** for real multi-column layouts. Structure content as **SectionHeader → Card → ActionCard → controls**, with **Divider** between sections. Settings and edit screens lay each section out as a [two-column section](#layout-when-to-use-stack-or-grid) (title on the left, fields on the right). Settings tabs put Save in the page header; setup flows and wizard steps keep primary actions in **`.newspack-buttons-card`**. Use the same **breakpoints** (e.g. 744px, 1054px) as existing components. Full detail: [Spacing scale](#spacing-scale-design-system), [Layout (Stack / Grid)](#layout-when-to-use-stack-or-grid), [Responsive breakpoints](#responsive-breakpoints), [Visual hierarchy patterns](#visual-hierarchy-patterns), [Component states](#component-states). For code examples by context and wizard patterns, see [Usage](#usage).
72
77
 
73
78
  ## Available Components
74
79
 
80
+ ### From `@wordpress/ui`
81
+
82
+ These come from the WordPress design system rather than this package. Import them from `@wordpress/ui` directly; they are not re-exported from `newspack-components`, and should not be.
83
+
84
+ - **`Stack`** – Flex row or column. Replaces `__experimentalHStack` / `__experimentalVStack`. `gap` takes a token (`xs`, `sm` 8px, `md` 12px, `lg` 16px, `xl` 24px, `2xl` 32px, `3xl`), not a number, so `VStack spacing={ 6 }` becomes `gap="xl"`. It lays out as a row unless you pass `direction="column"`, and it sets nothing you don't pass: a bare `HStack` or `Flex` gives an 8px gap, centered items and `space-between`, and a bare `VStack` an 8px gap, so carry those over (`gap="sm" align="center" justify="space-between"`, or `gap="sm"`). Children of an `HStack` or a row `Flex` also lose `min-width: 0`, so a child that truncates text may need it back.
85
+ - **`Card`** – Surface with `Card.Root`, `Card.Header`, `Card.Title`, `Card.Content` and `Card.FullBleed`. Use it for new cards rather than the Newspack `Card`.
86
+ - **`Badge`** – Single attention marker or chip. Text is `children`; `intent` is `high`, `medium`, `low`, `stable`, `informational`, `draft` or `none`, chosen by the state behind the label rather than the label itself.
87
+ - **`Text`**, **`Link`**, **`Popover`**, **`Collapsible`**, **`Tabs`**, **`VisuallyHidden`** – Use these where a Newspack component does not already wrap them. `Popover`, `Collapsible` and `Tabs` are sets of parts rather than single components (`Popover.Root`, `.Trigger`, `.Popup`, `.Title`; `Portal` and `Positioner` go in the popup's `portal` and `positioner` props rather than wrapping it), and every popup needs a non-empty `Popover.Title`, visually hidden if need be; development builds throw without one. `InfoButton` is the worked example.
88
+
89
+ Their class names are hashed CSS modules, so never target them from our stylesheets. Where a wrapper needs to style one, give it one of our own classes.
90
+
75
91
  ### Layout Components
76
92
 
77
- - **`Card`** – Container for a logical block of content; use for grouping related settings. Default vertical margin is 32px so cards stack with consistent rhythm. Use `noBorder` when cards sit inside another card (e.g. ActionCard children).
93
+ - **`Page`** – Admin page shell: header with breadcrumbs, badges, actions and an optional tab bar. `Wizard` and `withWizardScreen` render it for you unless `hideHeader` is set, but neither passes `badges`, so a header with badges uses `Page` directly. The last breadcrumb is the page's only `h1`.
94
+ - **`Breadcrumbs`** – The trail `Page` renders; the last item is the current page and is not a link.
95
+ - **`Card`** – Legacy container for a logical block of content (class component). Prefer `Card` from `@wordpress/ui` in new code. Default vertical margin is 32px so cards stack with consistent rhythm. Use `noBorder` when cards sit inside another card (e.g. ActionCard children).
78
96
  - **`Divider`** – Use between logical sections (e.g. between ActionCards) to separate content without another card. Margins are 32px (48px at larger breakpoints) so spacing stays consistent with the rest of the layout.
79
97
  - **`EmptyState`** – Use when a list has nothing in it yet, or an onboarding view stands in for a feature that is not set up. Compound: `EmptyState.Root` wraps `EmptyState.Header` and `EmptyState.Actions`. Render it only when the *unfiltered* collection is empty, so a search matching nothing keeps the DataViews "no results" treatment. See [src/empty-state/README.md](src/empty-state/README.md).
80
- - **`Grid`** – Use for laying out several items in columns (e.g. multiple controls or cards). Default gap is 32px; use `columns` and `gutter` modifiers (8, 16, 24, 32, 48) when you need tighter or looser spacing. For a single row or a simple vertical stack, prefer **VStack** (or HStack) in new code; Grid is still used that way in many places and is fine to leave as-is until we refactor.
98
+ - **`Grid`** – Use for laying out several items in columns (e.g. multiple controls or cards). Default gap is 32px; use `columns` and `gutter` modifiers (8, 16, 24, 32, 48) when you need tighter or looser spacing. For a single row or a simple vertical stack, use **`Stack`** from `@wordpress/ui` in new code; Grid is still used that way in many places and is fine to leave as-is until we refactor.
81
99
  - **`SectionHeader`** – Use to start a new section; pair with a short description so the section’s goal is clear. Top margin (48px) and bottom (32px) create clear separation from previous content and the section body.
100
+ - **`Drawer`** – Panel that slides in from the right edge for editing one item without leaving the list. Compound: `Drawer.Root`, `Header`, `Title`, `CloseIcon`, `Content`, `Divider`, `Footer`, `Action`. `isDirty` on the root makes every way of closing it ask before discarding edits. See [src/drawer/README.md](src/drawer/README.md).
82
101
  - **`StatCard`** – Use for a single headline figure with a label above it and a description below. Compound: `StatCard.Root` wraps `Label`, `Body` (holding `Value` and an optional `Secondary`) and `Footer`, with `Delta` riding in the `Value`'s `suffix` for a change beside the figure. Format the figure yourself and pass a string; a `null`, `undefined` or blank `value` gets the shared null glyph rather than a misleading zero. The figure is sized by a container query, so give the cards a definite width (a Grid track, a `flex: 1` item) and equal widths across a row to keep one type scale. See [src/stat-card/README.md](src/stat-card/README.md).
83
102
 
84
103
  ### Form Components
@@ -92,17 +111,25 @@ When building a screen, use the **spacing scale** (8px unit: 16, 24, 32, 48, 64)
92
111
  - **`CustomSelectControl`** - Custom select dropdown component
93
112
  - **`FormTokenField`** - Token input field for tags/categories; prefer the Newspack component over the core `FormTokenField` because it also supports a `description` prop for help text like other controls.
94
113
  - **`ImageUpload`** - Image upload and selection component
114
+ - **`PageControl`** - Picks one page through an autocomplete search
95
115
  - **`RadioControl`** - Radio button group control
116
+ - **`ReorderModal`** - Modal for putting a short list of items in order, by dragging or with move buttons; applies on Save
117
+ - **`SelectControl`** - Deprecated; use core `SelectControl`, or `__experimentalToggleGroupControl` for grouped or button-style choices
96
118
  - **`TextControl`** - Text input with Newspack styling and required field support
97
119
 
98
120
  ### Content Components
99
121
 
122
+ - **`CardFeature`** – A feature to enable or configure, with a state-driven button and an optional badge and "More" menu. At most two per row. See [src/card-feature/README.md](src/card-feature/README.md).
123
+ - **`CardForm`**, **`CardSettingsGroup`**, **`CardSortableList`** – Cards that reveal a form, collapse a group of settings, or reorder a list. Each has a README in its folder.
100
124
  - **`ActionCard`** – Use when one concept (e.g. a feature or setting) can be toggled on/off and may have extra content below. Internal padding (24px default; 16px/8px for isMedium/isSmall) and 24px between regions keep hierarchy clear; expandable content uses 24px top padding and 24px between siblings.
101
125
  - **`CollapsibleGroup`** / **`CollapsibleGroup.Item`** – A stack of independently collapsible items, separated by dividers and flush with the surrounding column. Not a W3C accordion: the items do not coordinate.
102
126
  - **`Notice`** – Being retired in favour of core’s `Notice` from `@wordpress/components`, which announces itself to assistive technology. Reach for core’s in new work; ours stays for the screens still on it. Where ours is used, vertical margin is 32px so notices don’t collide with cards, and one primary message per area reads best.
127
+ - **`DataViews`** – `@wordpress/dataviews` with Newspack styling, for list screens.
103
128
  - **`ProgressBar`** – Progress indicator.
129
+ - **`StatusIndicator`** – Glyph plus label for a Status column in a list, with a shared vocabulary (`active`, `scheduled`, `draft`, `error`, and so on). Use it instead of a badge in every row. See [src/status-indicator/README.md](src/status-indicator/README.md).
104
130
  - **`StepsList`** / **`StepsListItem`** – Step-by-step list components.
105
131
  - **`StyleCard`** – Style preview card.
132
+ - **`TableCard`** – A table or DataViews inside a `@wordpress/ui` `Card`, edge to edge, with a heading and an actions slot. See [src/table-card/README.md](src/table-card/README.md).
106
133
  - **`Waiting`** – Loading state indicator.
107
134
 
108
135
  ### Wizard Components
@@ -121,6 +148,7 @@ When building a screen, use the **spacing scale** (8px unit: 16, 24, 32, 48, 64)
121
148
  - Used in newer wizards like Audience Management
122
149
  - Passes props: `renderPrimaryButton`, plus all original component props
123
150
  - **`Wizard`** - Main wizard container with tabbed navigation and data fetching
151
+ - **`WizardBanner`** - Fill whose children render above the wizard's sections, for a screen-wide message
124
152
 
125
153
  ### Plugin Management Components
126
154
 
@@ -130,22 +158,26 @@ When building a screen, use the **spacing scale** (8px unit: 16, 24, 32, 48, 64)
130
158
 
131
159
  ### Utility Components
132
160
 
161
+ - **`ConfirmDialog`** - Confirmation modal, with a destructive variant; can also block router navigation. See [src/confirm-dialog/README.md](src/confirm-dialog/README.md)
133
162
  - **`DebugBadge`** - Floating indicator that Newspack debug mode is on. Takes no props and renders nothing unless the site defines `WP_NEWSPACK_DEBUG`
134
163
  - **`GlobalNotices`** - Global notice system component
135
- - **`InfoButton`** - Reveals supplementary context from a `description` prop. Anything a reader needs in order to use a control belongs in visible help text instead
164
+ - **`InfoButton`** - Reveals supplementary context from a `description` prop, on `@wordpress/ui` `Popover` so it also opens on touch. Use it rather than a `Tooltip` for descriptions. Anything a reader needs in order to use a control belongs in visible help text instead
136
165
  - **`Modal`** - Modal dialog component
166
+ - **`IntegrationIcon`** - Logo for a third-party integration, picked by `provider`. It is `aria-hidden` and renders nothing for an unknown provider, so keep the provider's name in visible text beside it
137
167
  - **`NewspackIcon`** - Newspack icon wrapper component
138
- - **`Popover`** - Popover component
168
+ - **`Popover`** - Legacy popover wrapper (class component); use `Popover` from `@wordpress/ui` in new code (see [From @wordpress/ui](#from-wordpressui) for its parts)
139
169
  - **`WebPreview`** - Web preview iframe component
140
170
 
141
171
  ### Settings Components
142
172
 
143
173
  - **`Settings`** - Settings container component
144
- - **`SortableNewsletterListControl`** - Sortable newsletter list selector
174
+ - **`SortableNewsletterListControl`** - Sortable newsletter list selector. Not exported from the barrel; import it from its own folder
145
175
 
146
176
  ### Utilities & Hooks
147
177
 
148
178
  - **`hooks`** - Custom React hooks (e.g., `useObjectState`, `usePrompt`, `useOnClickOutside`)
179
+ - **`useConfirmDialog`** - Hook form of `ConfirmDialog`: returns `{ confirmDialog, requestConfirm, cancelConfirm }`
180
+ - **`useUnsavedChangesDialog`** - Asks before the user leaves a screen with unsaved changes, by link or by closing the tab. Render the `confirmDialog` it returns, or links do nothing while it is active; one active instance per screen
149
181
  - **`Router`** - Proxied React Router import (use instead of direct `react-router-dom` import)
150
182
  - Note: This package currently uses [React Router v5](https://v5.reactrouter.com/). Please refer to v5 documentation for API details.
151
183
  - **`utils`** - Utility functions (e.g., `confirmAction`, color utilities)
@@ -246,7 +278,7 @@ This section shows how to use components **by context** (backend, blocks, fronte
246
278
 
247
279
  ### Backend/Admin UI
248
280
 
249
- **Rule:** Use Newspack components as the primary choice, falling back to WordPress components when needed.
281
+ **Rule:** Use `@wordpress/ui` primitives and Newspack components, falling back to WordPress components when needed. The examples below show existing screens, several on the legacy Newspack `Card`; new code uses `Card` from `@wordpress/ui`, imported as `Card as UICard` in a file that still needs ours.
250
282
 
251
283
  **Common import pattern:**
252
284
  ```jsx
@@ -518,9 +550,7 @@ When Newspack components don't provide what you need, use these WordPress compon
518
550
 
519
551
  ### Layout
520
552
 
521
- - **`__experimentalHStack as HStack`** – Horizontal stack (in use, e.g. Audience > Subscriptions)
522
- - **`__experimentalVStack as VStack`** – Vertical stack (preferred for new layout when you need vertical stacking; use same import pattern as HStack)
523
- - **`Flex`** / **`FlexItem`** – Flex layout (used in Nextdoor sidebar; consider HStack/VStack for new code when appropriate)
553
+ - Use **`Stack`** from `@wordpress/ui` (see [From @wordpress/ui](#from-wordpressui)). `__experimentalHStack`, `__experimentalVStack` and `Flex` / `FlexItem` are still in older screens; replace them when you rework that layout, and don't add new ones.
524
554
 
525
555
  ### Panels and structure (blocks and admin)
526
556
 
@@ -540,11 +570,11 @@ When Newspack components don't provide what you need, use these WordPress compon
540
570
  ### Feedback and overlays
541
571
 
542
572
  - **`Spinner`** – Loading spinner
543
- - **`Notice`** – Inline notice (success/error/warning); prefer this over the Newspack `Notice`, which is being retired
573
+ - **`Notice`** – Inline notice (success/error/warning); prefer this over the Newspack `Notice`, which is being retired, and over `@wordpress/ui`'s `Notice`, which we have not adopted
544
574
  - **`Placeholder`** – Empty state in blocks
545
575
  - **`Modal`** – Modal dialog
546
- - **`Popover`** – Popover (e.g. webhooks endpoint actions, corrections modal)
547
- - **`Tooltip`** – Tooltip (e.g. site statuses, info)
576
+ - **`Popover`** – Popover (e.g. webhooks endpoint actions, corrections modal); prefer `Popover` from `@wordpress/ui` in new code, which is a set of parts rather than a drop-in
577
+ - **`Tooltip`** – Tooltip for a short label on hover (e.g. site statuses). It opens on hover and keyboard focus but never on touch, so use `InfoButton` for descriptions
548
578
 
549
579
  ### Block editor UI
550
580
 
@@ -562,29 +592,23 @@ When Newspack components don't provide what you need, use these WordPress compon
562
592
 
563
593
  ### Importing experimental components
564
594
 
565
- Experimental components (e.g. `HStack`, `VStack`, `NumberControl`, `ToggleGroupControl`, `Heading`) live under `@wordpress/components` and may be prefixed with `__experimental`. Use the same import style as the rest of the codebase and add an eslint disable for unsafe APIs when required:
595
+ Experimental components (e.g. `NumberControl`, `ToggleGroupControl`, `Heading`) live under `@wordpress/components` and may be prefixed with `__experimental`. Use the same import style as the rest of the codebase and add an eslint disable for unsafe APIs when required:
566
596
 
567
597
  ```jsx
568
598
  import {
569
- __experimentalHStack as HStack, // eslint-disable-line @wordpress/no-unsafe-wp-apis
570
599
  __experimentalNumberControl as NumberControl, // eslint-disable-line @wordpress/no-unsafe-wp-apis
571
- __experimentalVStack as VStack, // eslint-disable-line @wordpress/no-unsafe-wp-apis
572
600
  ExternalLink,
573
601
  } from '@wordpress/components';
574
602
  ```
575
603
 
576
604
  **Example – form controls and layout:**
577
605
  ```jsx
578
- import {
579
- CheckboxControl,
580
- ExternalLink,
581
- __experimentalHStack as HStack, // eslint-disable-line @wordpress/no-unsafe-wp-apis
582
- RangeControl,
583
- } from '@wordpress/components';
584
- import { ActionCard, Card } from '../../../../../packages/components/src';
606
+ import { CheckboxControl, RangeControl } from '@wordpress/components';
607
+ import { Stack } from '@wordpress/ui';
608
+ import { ActionCard } from '../../../../../packages/components/src';
585
609
 
586
610
  <ActionCard title="Settings">
587
- <HStack>
611
+ <Stack gap="lg">
588
612
  <RangeControl
589
613
  label={ __( 'Value', 'newspack-plugin' ) }
590
614
  value={ config.value }
@@ -595,7 +619,7 @@ import { ActionCard, Card } from '../../../../../packages/components/src';
595
619
  checked={ config.enabled }
596
620
  onChange={ value => updateConfig( 'enabled', value ) }
597
621
  />
598
- </HStack>
622
+ </Stack>
599
623
  </ActionCard>
600
624
  ```
601
625
 
@@ -627,11 +651,28 @@ Spacing is based on an **8px unit**. Use these values so new styles match existi
627
651
 
628
652
  **In code:** Card uses `margin: 32px 0` and `padding: 16px 48px` (32px 64px at 744px+). ActionCard uses 24px for region padding and 24px between regions; region-children use `padding: 0 24px 24px` (0 32px 32px for is-medium). Grid uses `grid-gap: 32px` and `margin: 32px 0` by default, with optional gutter classes (`__gutter-8`, `__gutter-16`, etc.). When adding new components or overrides, prefer these values (or 8px multiples) instead of ad-hoc spacing.
629
653
 
630
- ### Layout: when to use HStack, VStack, Grid
654
+ ### Layout: when to use Stack or Grid
655
+
656
+ - **`Stack`** from `@wordpress/ui` – A few related items in a row (e.g. label + control), or a single column of items, lists of settings, or stacked sections. Use `gap` for the spacing instead of margins on the children. A column needs `direction="column"`; without it, `Stack` lays out as a row.
657
+ - **Grid (Newspack)** – A set of items in columns (e.g. multiple cards or form groups). Default 32px gap; use `columns` and gutter modifiers. Use when the layout is genuinely a grid of items (multiple columns). There are many existing examples where Grid is used as a single row. That is fine to leave, but new code uses `Stack` for it.
658
+
659
+ **Two-column sections** are the standard layout for a section of a settings or edit screen: what the section is on the left, its fields on the right. Settings tabs use it, and so do the Access Control editors (gates, metering, content gifting, institutions), the integration and experimental tool configure views, and the pricing rule and product forms. Use it for any new screen made of named groups of settings:
660
+
661
+ ```jsx
662
+ <>
663
+ <Grid columns={ 2 } gutter={ 32 } noMargin>
664
+ <SectionHeader heading={ 2 } noMargin title={ … } description={ … } />
665
+ <Stack direction="column" gap="xl">
666
+ { /* fields */ }
667
+ </Stack>
668
+ </Grid>
669
+ <Divider alignment="full-width" variant="tertiary" />
670
+ </>
671
+ ```
672
+
673
+ The `Grid` collapses to one column below 744px, so the header sits above its fields on narrow screens. Fields drop their own bottom margin so the `Stack` gap is the only spacing: Newspack `TextControl` takes `withMargin={ false }` plus `__nextHasNoMarginBottom` and `__next40pxDefaultSize`; core `ToggleControl` and `CheckboxControl` take `__nextHasNoMarginBottom`. Content that needs the full width (logs, card pickers, tables) stacks its `SectionHeader` above it instead. Some existing editors predate this: their right column is a `VStack` (`spacing={ 4 }` or `{ 6 }`) and their `SectionHeader` has no `noMargin`. New and reworked sections follow the example. A grid of cards that each open their own screen is a different pattern and has no `SectionHeader` column.
631
674
 
632
- - **HStack** – A few related items in a row (e.g. label + control, or two related controls). Use when the relationship is “these belong together horizontally.”
633
- - **VStack** – Stack blocks vertically with consistent spacing. **Prefer VStack** for a single column of items, lists of settings, or stacked sections when you want vertical rhythm without custom margins. For new code, favour VStack over using Grid as a single row.
634
- - **Grid (Newspack)** – A set of items in columns (e.g. multiple cards or form groups). Default 32px gap; use `columns` and gutter modifiers. Use when the layout is genuinely a grid of items (multiple columns). There are many existing examples where Grid is used as a single row—that’s not wrong, but we’d use VStack (or HStack) for that in new code and may update those over time.
675
+ **Settings tabs** are built from two-column sections. Save sits in the page header, published with `setHeaderData( { actions } )` from the wizard store and disabled until something changes. The header keeps whichever callback it was handed, so read the latest handler from a ref; passing the save function directly saves stale state. Pair it with `useUnsavedChangesDialog`. See `plugins/newspack-plugin/src/wizards/newspack/views/settings/seo/index.tsx`.
635
676
 
636
677
  Prefer these patterns (and the spacing scale above) over one-off margins so layout stays consistent with Card, ActionCard, and SectionHeader.
637
678
 
@@ -656,14 +697,14 @@ Prefer these values over new breakpoints so behaviour stays consistent with Card
656
697
 
657
698
  Common composition patterns keep screens predictable. Use these as a reference when building new wizards or settings:
658
699
 
659
- **Settings screen (Wizard-based):**
700
+ **Setup screen (Wizard-based):**
660
701
  ```
661
702
  Wizard
662
703
  GlobalNotices
663
704
  SectionHeader ← 48px top margin
664
705
  Card ← 32px margin
665
706
  ActionCard ← 24px padding, optional toggle
666
- Grid or VStack ← 32px gap
707
+ Grid or Stack ← 32px gap (Grid default; Stack gap="2xl")
667
708
  TextControl / SelectControl / etc.
668
709
  Divider ← 32px / 48px margin
669
710
  ActionCard
@@ -684,7 +725,7 @@ withWizardScreen
684
725
  Button
685
726
  ```
686
727
 
687
- **Form group:** Use `Grid columns={4}` (or VStack) with TextControl, SelectControl, CheckboxControl, etc. inside a Card or ActionCard; spacing between controls follows the [spacing scale](#spacing-scale-design-system) (e.g. 16px for related rows).
728
+ **Form group:** Use `Grid columns={4}` (or `Stack`) with TextControl, SelectControl, CheckboxControl, etc. inside a Card or ActionCard; spacing between controls follows the [spacing scale](#spacing-scale-design-system) (e.g. 16px for related rows).
688
729
 
689
730
  ### Component states
690
731
 
@@ -721,6 +762,7 @@ When adding new interactive components, preserve focus visibility and use the sa
721
762
 
722
763
  - **[newspack-colors](../colors/)** – Color palette used by components (via WordPress design system)
723
764
  - **[newspack-icons](../icons/)** – Custom icons used in components
765
+ - **[@wordpress/ui](https://www.npmjs.com/package/@wordpress/ui)** – WordPress design system components (`Stack`, `Card`, `Badge`, `Text` and more); first choice for primitives
724
766
  - **[@wordpress/components](https://www.npmjs.com/package/@wordpress/components)** – WordPress component library (fallback when Newspack components don’t exist)
725
767
  - **[@wordpress/base-styles](https://www.npmjs.com/package/@wordpress/base-styles)** – WordPress Design System styles and colors
726
768
 
@@ -94,6 +94,7 @@ var Breadcrumbs = function Breadcrumbs(_ref3) {
94
94
  render: /*#__PURE__*/(0, _jsxRuntime.jsx)("ul", {}),
95
95
  direction: "row",
96
96
  align: "center",
97
+ wrap: "wrap",
97
98
  className: "newspack-breadcrumbs__list",
98
99
  children: [preceding.map(function (item, index) {
99
100
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)("li", {
@@ -7,8 +7,8 @@
7
7
  padding: 0;
8
8
 
9
9
  > li {
10
- flex-shrink: 0;
11
10
  margin: 0;
11
+ min-width: 0;
12
12
 
13
13
  a {
14
14
  color: wp-colors.$gray-900;
@@ -20,11 +20,6 @@
20
20
  }
21
21
  }
22
22
  }
23
-
24
- > li:last-child {
25
- flex-shrink: 1;
26
- min-width: 0;
27
- }
28
23
  }
29
24
 
30
25
  .newspack-breadcrumbs__count {
@@ -39,9 +34,7 @@
39
34
  }
40
35
 
41
36
  .newspack-breadcrumbs__list h1.newspack-breadcrumbs__current {
42
- overflow: hidden;
43
- text-overflow: ellipsis;
44
- white-space: nowrap;
37
+ overflow-wrap: break-word;
45
38
  padding: 0;
46
- line-height: normal;
39
+ line-height: var(--wpds-typography-line-height-md, #{wp-vars.$grid-unit-30});
47
40
  }
@@ -221,7 +221,7 @@
221
221
  color: inherit;
222
222
  text-decoration: none;
223
223
  &:hover {
224
- text-decoration: underline;
224
+ color: var(--wp-admin-theme-color);
225
225
  }
226
226
  }
227
227
  }
@@ -8,23 +8,23 @@ exports["default"] = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
10
10
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
11
+ var _classnames = _interopRequireDefault(require("classnames"));
11
12
  var _components = require("@wordpress/components");
12
13
  var _element = require("@wordpress/element");
13
14
  var _ui = require("@wordpress/ui");
14
- var _ = require("../");
15
+ var _card = _interopRequireDefault(require("../card"));
16
+ var _tooltipBadge = _interopRequireDefault(require("../tooltip-badge"));
15
17
  require("./style.scss");
16
- var _classnames = _interopRequireDefault(require("classnames"));
17
18
  var _jsxRuntime = require("react/jsx-runtime");
18
19
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
19
20
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /**
20
21
  * Card - Sortable list component.
21
22
  */ /**
23
+ * External dependencies
24
+ */ /**
22
25
  * WordPress dependencies.
23
- */ // eslint-disable-line @wordpress/no-unsafe-wp-apis
24
- /**
25
- * Internal dependencies
26
26
  */ /**
27
- * External dependencies
27
+ * Internal dependencies
28
28
  */
29
29
  var DROP_ANIMATION_DURATION = 400; // ms — must match $drop-duration in style.scss
30
30
  var BUTTON_MOVE_DURATION = 200; // ms — must match $shift-duration in style.scss
@@ -347,13 +347,14 @@ var CardSortableList = function CardSortableList(_ref) {
347
347
  return 0;
348
348
  };
349
349
  var isDragging = draggingIndex !== null;
350
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalVStack, {
350
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ui.Stack, {
351
+ direction: "column",
352
+ gap: "lg",
351
353
  ref: listRef,
352
354
  className: (0, _classnames["default"])('newspack-card--core--sortable-list', disabled && 'newspack-card--core--sortable-list__is-disabled', isDragging && 'newspack-card--core--sortable-list__is-dragging'),
353
355
  style: measurements ? {
354
356
  height: measurements.lockedHeight
355
357
  } : undefined,
356
- spacing: 4,
357
358
  children: sortedItems.map(function (item, index) {
358
359
  var translateY = getTranslateY(index);
359
360
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Disabled, {
@@ -385,10 +386,10 @@ var CardSortableList = function CardSortableList(_ref) {
385
386
  onDragEnd: handleDragEnd,
386
387
  appendToOwnerDocument: true,
387
388
  children: function children(_ref2) {
388
- var _item$badge, _item$badge$intent;
389
+ var _item$badge, _item$badge$intent, _item$secondaryBadge, _item$secondaryBadge$;
389
390
  var onDraggableStart = _ref2.onDraggableStart,
390
391
  onDraggableEnd = _ref2.onDraggableEnd;
391
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_.Card, {
392
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_card["default"], {
392
393
  isSmall: true,
393
394
  draggable: true,
394
395
  onDragStart: onDraggableStart,
@@ -400,7 +401,14 @@ var CardSortableList = function CardSortableList(_ref) {
400
401
  children: [item.title, ((_item$badge = item.badge) === null || _item$badge === void 0 ? void 0 : _item$badge.label) && /*#__PURE__*/(0, _jsxRuntime.jsx)(_ui.Badge, {
401
402
  intent: (_item$badge$intent = item.badge.intent) !== null && _item$badge$intent !== void 0 ? _item$badge$intent : 'none',
402
403
  children: item.badge.label
403
- })]
404
+ }), ((_item$secondaryBadge = item.secondaryBadge) === null || _item$secondaryBadge === void 0 ? void 0 : _item$secondaryBadge.label) && (item.secondaryBadge.tooltip ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_tooltipBadge["default"], {
405
+ label: item.secondaryBadge.label,
406
+ tooltip: item.secondaryBadge.tooltip,
407
+ intent: item.secondaryBadge.intent
408
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_ui.Badge, {
409
+ intent: (_item$secondaryBadge$ = item.secondaryBadge.intent) !== null && _item$secondaryBadge$ !== void 0 ? _item$secondaryBadge$ : 'none',
410
+ children: item.secondaryBadge.label
411
+ }))]
404
412
  }), item.description && /*#__PURE__*/(0, _jsxRuntime.jsx)("p", {
405
413
  children: item.description
406
414
  })]
@@ -413,7 +421,10 @@ var CardSortableList = function CardSortableList(_ref) {
413
421
  }, item.onToggleChange !== undefined && {
414
422
  actionType: 'toggle',
415
423
  isActive: item.toggleChecked,
416
- onToggle: item.onToggleChange
424
+ onToggle: item.onToggleChange,
425
+ // Names the toggle for assistive tech. The card hides this
426
+ // label, since the header already shows the title.
427
+ title: item.title
417
428
  }), item.actions !== undefined && {
418
429
  actions: item.actions
419
430
  })
@@ -47,4 +47,25 @@ describe('CardSortableList', function () {
47
47
  // An unguarded Badge would still emit an empty span, so assert on element children.
48
48
  expect(container.querySelector('h3').children).toHaveLength(0);
49
49
  });
50
+ it('names each toggle after its item', function () {
51
+ (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_["default"], {
52
+ items: [{
53
+ id: 1,
54
+ title: 'Homepage',
55
+ toggleChecked: true,
56
+ onToggleChange: function onToggleChange() {}
57
+ }, {
58
+ id: 2,
59
+ title: 'About',
60
+ toggleChecked: false,
61
+ onToggleChange: function onToggleChange() {}
62
+ }]
63
+ }));
64
+ expect(_react.screen.getByRole('checkbox', {
65
+ name: 'Homepage'
66
+ })).toBeChecked();
67
+ expect(_react.screen.getByRole('checkbox', {
68
+ name: 'About'
69
+ })).not.toBeChecked();
70
+ });
50
71
  });
@@ -6,6 +6,14 @@ $drop-duration: 400ms; /* must match DROP_ANIMATION_DURATION in index.tsx */
6
6
  &__item {
7
7
  cursor: grab;
8
8
 
9
+ /*
10
+ * Keep a card's title in the case it was written in. The block editor
11
+ * sidebar uppercases every h3 (`.interface-complementary-area h3`).
12
+ */
13
+ .newspack-card--core__header-content h3 {
14
+ text-transform: none;
15
+ }
16
+
9
17
  /*
10
18
  * Animate items sliding to fill/make space around the dragged item.
11
19
  */
@@ -6,14 +6,13 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports["default"] = void 0;
8
8
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
- var _components = require("@wordpress/components");
10
9
  var _element = require("@wordpress/element");
11
10
  var _i18n = require("@wordpress/i18n");
11
+ var _ui = require("@wordpress/ui");
12
12
  var _jsxRuntime = require("react/jsx-runtime");
13
13
  /**
14
14
  * WordPress dependencies.
15
15
  */
16
- // eslint-disable-line @wordpress/no-unsafe-wp-apis
17
16
 
18
17
  /**
19
18
  * Internal dependencies.
@@ -63,11 +62,10 @@ var Body = function Body(_ref) {
63
62
  mutation.disconnect();
64
63
  };
65
64
  }, [node]);
66
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalVStack, {
65
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ui.Stack, {
67
66
  ref: setNode,
68
- className: "newspack-drawer__body",
69
- spacing: 0,
70
- justify: "flex-start"
67
+ direction: "column",
68
+ className: "newspack-drawer__body"
71
69
  // A bare div is role=generic, where ARIA prohibits an author name.
72
70
  ,
73
71
  role: isScrollable ? 'group' : undefined,
@@ -5,14 +5,12 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports["default"] = void 0;
8
- var _components = require("@wordpress/components");
9
- var _element = require("@wordpress/element");
8
+ var _ui = require("@wordpress/ui");
10
9
  var _classnames = _interopRequireDefault(require("classnames"));
11
10
  var _jsxRuntime = require("react/jsx-runtime");
12
11
  /**
13
12
  * WordPress dependencies.
14
13
  */
15
- // eslint-disable-line @wordpress/no-unsafe-wp-apis
16
14
 
17
15
  /**
18
16
  * External dependencies.
@@ -22,51 +20,23 @@ var _jsxRuntime = require("react/jsx-runtime");
22
20
  * Internal dependencies.
23
21
  */
24
22
 
25
- // VStack drops non-elements, a lone string aside. A run shares one wrapper so
26
- // `Edited by { name }` is one row, not three.
27
- var asRows = function asRows(children) {
28
- if ('string' === typeof children) {
29
- return children;
30
- }
31
- var rows = [];
32
- var text = [];
33
- var flushText = function flushText() {
34
- if (text.some(function (part) {
35
- return '' !== String(part).trim();
36
- })) {
37
- rows.push(/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
38
- children: text
39
- }, "text-".concat(rows.length)));
40
- }
41
- text = [];
42
- };
43
- _element.Children.toArray(children).forEach(function (child) {
44
- if ((0, _element.isValidElement)(child)) {
45
- flushText();
46
- rows.push(child);
47
- } else {
48
- text.push(child);
49
- }
50
- });
51
- flushText();
52
- return rows;
53
- };
54
23
  var Content = function Content(_ref) {
55
24
  var _ref$padding = _ref.padding,
56
25
  padding = _ref$padding === void 0 ? 6 : _ref$padding,
57
26
  _ref$gap = _ref.gap,
58
- gap = _ref$gap === void 0 ? 4 : _ref$gap,
27
+ gap = _ref$gap === void 0 ? 'lg' : _ref$gap,
59
28
  className = _ref.className,
60
29
  children = _ref.children;
61
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalVStack, {
62
- className: (0, _classnames["default"])('newspack-drawer__content', className),
63
- spacing: gap
30
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ui.Stack, {
31
+ direction: "column",
32
+ gap: gap,
33
+ className: (0, _classnames["default"])('newspack-drawer__content', className)
64
34
  // A custom property, not inline padding, so the stylesheet's seam rules win.
65
35
  ,
66
36
  style: {
67
37
  '--newspack-drawer-content-padding': "".concat(padding * 4, "px")
68
38
  },
69
- children: asRows(children)
39
+ children: children
70
40
  });
71
41
  };
72
42
  var _default = exports["default"] = Content;