diff --git a/packages/ui/CHANGELOG.md b/packages/ui/CHANGELOG.md index 5745f0339cbad3..a8812e66f749fd 100644 --- a/packages/ui/CHANGELOG.md +++ b/packages/ui/CHANGELOG.md @@ -41,6 +41,7 @@ ### Internal +- Improve Storybook "Show code" snippets for design system component stories by using explicit `render` functions with direct child composition ([#80129](https://github.com/WordPress/gutenberg/pull/80129)). - Add an explicit return type to an internal overlay focus helper so the published type definitions stay self-contained ([#79684](https://github.com/WordPress/gutenberg/pull/79684)). - Enforce CSS Module class selector naming for component-library packages ([#79504](https://github.com/WordPress/gutenberg/pull/79504)). - Update `@base-ui/react` from `1.5.0` to [`1.6.0`](https://github.com/mui/base-ui/releases/tag/v1.6.0) ([#79408](https://github.com/WordPress/gutenberg/pull/79408)). diff --git a/packages/ui/src/alert-dialog/stories/index.story.tsx b/packages/ui/src/alert-dialog/stories/index.story.tsx index 5df7d23259be3e..1c6005a6a81e14 100644 --- a/packages/ui/src/alert-dialog/stories/index.story.tsx +++ b/packages/ui/src/alert-dialog/stories/index.story.tsx @@ -37,17 +37,15 @@ type Story = StoryObj< typeof AlertDialog.Root >; * is blocked. */ export const Default: Story = { - args: { - children: ( - <> - Move to trash - - - ), - }, + render: ( {} ) => ( + + Move to trash + + + ), }; /** @@ -55,38 +53,34 @@ export const Default: Story = { * The confirm button uses error/danger coloring. */ export const Irreversible: Story = { - args: { - children: ( - <> - Delete permanently - - - ), - }, + render: ( {} ) => ( + + Delete permanently + + + ), }; /** * Example with custom button labels for both confirm and cancel buttons. */ export const CustomLabels: Story = { - args: { - children: ( - <> - Send feedback - - - ), - }, + render: ( {} ) => ( + + Send feedback + + + ), }; /** @@ -95,29 +89,27 @@ export const CustomLabels: Story = { * accessibility (`aria-describedby`); `children` adds supplementary detail. */ export const WithCustomContent: Story = { - args: { - children: ( - <> - Remove pages - ( + + Remove pages + +
    -
      - }>About us - }>Contact - }>Privacy policy -
    - - - ), - }, + }>About us + }>Contact + }>Privacy policy +
+
+
+ ), }; /** @@ -139,22 +131,20 @@ export const WithCustomContent: Story = { */ export const WithCustomZIndex: Story = { name: 'With Custom z-index', - args: { - children: ( - <> - Move to trash - - } - /> - - ), - }, + render: ( {} ) => ( + + Move to trash + + } + /> + + ), }; const menuPopupStyles: React.CSSProperties = { @@ -188,7 +178,7 @@ const menuItemStyles: React.CSSProperties = { * component (not ready yet). */ export const MenuTrigger: Story = { - render: () => { + render: ( {} ) => { const [ menuOpen, setMenuOpen ] = useState( false ); return ( <> @@ -397,9 +387,11 @@ function ScrollableContent() { * independently. */ export const Scrollable: Story = { - args: { - children: , - }, + render: ( {} ) => ( + + + + ), }; /** diff --git a/packages/ui/src/badge/stories/usage-guidelines.story.tsx b/packages/ui/src/badge/stories/usage-guidelines.story.tsx index fcdbedaca5f8f8..a9851a670d147d 100644 --- a/packages/ui/src/badge/stories/usage-guidelines.story.tsx +++ b/packages/ui/src/badge/stories/usage-guidelines.story.tsx @@ -25,7 +25,7 @@ export default meta; type Story = StoryObj< typeof Badge >; export const AllIntents: Story = { - render: () => ( + render: ( {} ) => ( <> high medium @@ -39,7 +39,7 @@ export const AllIntents: Story = { }; export const High: Story = { - render: () => ( + render: ( {} ) => ( <> Payment declined Security issue @@ -48,7 +48,7 @@ export const High: Story = { }; export const Medium: Story = { - render: () => ( + render: ( {} ) => ( <> Approval required Review needed @@ -57,7 +57,7 @@ export const Medium: Story = { }; export const Low: Story = { - render: () => ( + render: ( {} ) => ( <> Pending Queued @@ -66,7 +66,7 @@ export const Low: Story = { }; export const Informational: Story = { - render: () => ( + render: ( {} ) => ( <> Scheduled Beta @@ -75,7 +75,7 @@ export const Informational: Story = { }; export const Draft: Story = { - render: () => ( + render: ( {} ) => ( <> Draft Unpublished @@ -84,7 +84,7 @@ export const Draft: Story = { }; export const Stable: Story = { - render: () => ( + render: ( {} ) => ( <> Healthy Active @@ -93,7 +93,7 @@ export const Stable: Story = { }; export const None: Story = { - render: () => ( + render: ( {} ) => ( <> Inactive Expired @@ -102,7 +102,7 @@ export const None: Story = { }; export const CommentStatus: Story = { - render: () => ( + render: ( {} ) => ( <> Approved Approval required @@ -111,7 +111,7 @@ export const CommentStatus: Story = { }; export const PageStatus: Story = { - render: () => ( + render: ( {} ) => ( <> Published Pending @@ -123,7 +123,7 @@ export const PageStatus: Story = { }; export const PluginStatus: Story = { - render: () => ( + render: ( {} ) => ( <> Active Inactive @@ -132,7 +132,7 @@ export const PluginStatus: Story = { }; export const TextOnlyBadges: Story = { - render: () => ( + render: ( {} ) => ( <> Active Review needed @@ -142,7 +142,7 @@ export const TextOnlyBadges: Story = { }; export const WithAdjacentContentIcon: Story = { - render: () => ( + render: ( {} ) => ( @@ -159,7 +159,7 @@ export const WithAdjacentContentIcon: Story = { }; export const IncorrectBadgeWithIcon: Story = { - render: () => ( + render: ( {} ) => ( <> { /* @ts-expect-error Demonstrating incorrect Badge usage with icon children. */ } diff --git a/packages/ui/src/button/stories/index.story.tsx b/packages/ui/src/button/stories/index.story.tsx index cd29297509d160..0c9285bd998377 100644 --- a/packages/ui/src/button/stories/index.story.tsx +++ b/packages/ui/src/button/stories/index.story.tsx @@ -154,15 +154,12 @@ export const AllTonesAndVariants: Story = { export const WithIcon: Story = { ...Default, - args: { - ...Default.args, - children: ( - <> - - Button - - ), - }, + render: ( { children: _children, ...args } ) => ( + + ), }; export const Loading: Story = { diff --git a/packages/ui/src/button/stories/usage-guidelines.story.tsx b/packages/ui/src/button/stories/usage-guidelines.story.tsx index 662bed331536f0..f099a8f7d1a846 100644 --- a/packages/ui/src/button/stories/usage-guidelines.story.tsx +++ b/packages/ui/src/button/stories/usage-guidelines.story.tsx @@ -26,7 +26,7 @@ type Story = StoryObj; * ` @@ -49,7 +49,7 @@ export const UseButtonForActions: Story = { * the user is going more clearly than a button-shaped control. */ export const UseLinkForInlineNavigation: Story = { - render: () => ( + render: ( {} ) => ( }> { createInterpolateElement( 'Read the for more details, or .', @@ -78,7 +78,7 @@ export const UseLinkForInlineNavigation: Story = { * styling set clearer expectations than a button-shaped control. */ export const UseLinkButtonForNavigation: Story = { - render: () => ( + render: ( {} ) => ( }> Standalone navigation calls to action can use `LinkButton` when diff --git a/packages/ui/src/card/stories/index.story.tsx b/packages/ui/src/card/stories/index.story.tsx index 9535dd953489bf..2989a1661d7e2f 100644 --- a/packages/ui/src/card/stories/index.story.tsx +++ b/packages/ui/src/card/stories/index.story.tsx @@ -51,30 +51,26 @@ export default meta; type Story = StoryObj< typeof Card.Root >; export const Default: Story = { - args: { - children: ( - <> - - Card title - - - - This is the main content area. It can contain any - elements. This is the main content area. It can contain - any elements. This is the main content area. It can - contain any elements. This is the main content area. It - can contain any elements. This is the main content area. - It can contain any elements. This is the main content - area. It can contain any elements. - - - This is the main content area. It can contain any - elements. - - - - ), - }, + render: ( {} ) => ( + + + Card title + + + + This is the main content area. It can contain any elements. + This is the main content area. It can contain any elements. + This is the main content area. It can contain any elements. + This is the main content area. It can contain any elements. + This is the main content area. It can contain any elements. + This is the main content area. It can contain any elements. + + + This is the main content area. It can contain any elements. + + + + ), }; /** @@ -82,8 +78,8 @@ export const Default: Story = { * with no padding around it. */ export const FullBleedCoverOnly: Story = { - args: { - children: ( + render: ( {} ) => ( +
- ), - }, + + ), }; /** @@ -105,26 +101,24 @@ export const FullBleedCoverOnly: Story = { * bottom edges while the header retains its normal padding. */ export const FullBleedCoverWithHeader: Story = { - args: { - children: ( - <> - - Card title - - - -
- - - - ), - }, + render: ( {} ) => ( + + + Card title + + + +
+ + + + ), }; /** @@ -132,40 +126,38 @@ export const FullBleedCoverWithHeader: Story = { * edge-to-edge. Useful for images, dividers, or embedded content. */ export const WithFullBleed: Story = { - args: { - children: ( - <> - - Featured image - - }> - -
- - Content below the full-bleed area. - - - ), - }, + render: ( {} ) => ( + + + Featured image + + }> + +
+ + Content below the full-bleed area. + + + ), }; /** * A minimal card with only a header. */ export const HeaderOnly: Story = { - args: { - children: ( + render: ( {} ) => ( + Simple card - ), - }, + + ), }; /** @@ -174,30 +166,28 @@ export const HeaderOnly: Story = { * that follows inside the header is padded normally. */ export const FullBleedHeroWithTitle: Story = { - args: { - children: ( - <> - }> - -
- - Hero image card - - - - The image above bleeds to the card's top and side - edges. - - - - ), - }, + render: ( {} ) => ( + + }> + +
+ + Hero image card + + + + The image above bleeds to the card's top and side + edges. + + + + ), }; /** @@ -206,29 +196,27 @@ export const FullBleedHeroWithTitle: Story = { * below. */ export const FullBleedHeroOnly: Story = { - args: { - children: ( - <> - - -
- - - - - The image above bleeds to the card's top and side - edges. - - - - ), - }, + render: ( {} ) => ( + + + +
+ + + + + The image above bleeds to the card's top and side + edges. + + + + ), }; /** @@ -237,17 +225,14 @@ export const FullBleedHeroOnly: Story = { * `Card.Title` renders as an `

`. */ export const CustomSemantics: Story = { - args: { - render:
, - children: ( - <> - - }>Section heading - - - Semantically meaningful card content. - - - ), - }, + render: ( {} ) => ( + }> + + }>Section heading + + + Semantically meaningful card content. + + + ), }; diff --git a/packages/ui/src/collapsible-card/stories/index.story.tsx b/packages/ui/src/collapsible-card/stories/index.story.tsx index 1eb66d1a01ce2c..d45d3884a7645b 100644 --- a/packages/ui/src/collapsible-card/stories/index.story.tsx +++ b/packages/ui/src/collapsible-card/stories/index.story.tsx @@ -50,26 +50,22 @@ type Story = StoryObj< typeof CollapsibleCard.Root >; * A collapsible card that is open by default. */ export const Default: Story = { - args: { - children: ( - <> - - - Collapsible card (closed by default) - - - - - This is the collapsible content area. It can contain any - elements, just like a regular Card.Content. - - - When collapsed, only the header and chevron are visible. - - - - ), - }, + render: ( {} ) => ( + + + Collapsible card (closed by default) + + + + This is the collapsible content area. It can contain any + elements, just like a regular Card.Content. + + + When collapsed, only the header and chevron are visible. + + + + ), }; /** @@ -79,40 +75,32 @@ export const InitiallyOpened: Story = { // `defaultOpen` (uncontrolled) and `open` (controlled) should not be // used together — disable the `open` control to avoid confusion. argTypes: { open: { control: false } }, - args: { - ...Default.args, - defaultOpen: true, - children: ( - <> - - Collapsed by default - - - This content was hidden until you expanded it. - - - ), - }, + render: ( {} ) => ( + + + Collapsed by default + + + This content was hidden until you expanded it. + + + ), }; /** * A disabled collapsible card cannot be toggled by the user. */ export const Disabled: Story = { - args: { - ...Default.args, - disabled: true, - children: ( - <> - - Disabled card - - - The header is not interactive when disabled. - - - ), - }, + render: ( {} ) => ( + + + Disabled card + + + The header is not interactive when disabled. + + + ), }; /** @@ -121,7 +109,7 @@ export const Disabled: Story = { */ export const Stacked: Story = { parameters: { controls: { disable: true } }, - render: () => ( + render: ( {} ) => (
( + render: ( {} ) => (
( @@ -325,27 +312,24 @@ export const ComparedToCard: Story = { */ export const FullBleedCoverWithHeader: Story = { argTypes: { open: { control: false } }, - args: { - defaultOpen: true, - children: ( - <> - - Card title - - - -
- - - - ), - }, + render: ( {} ) => ( + + + Card title + + + +
+ + + + ), }; /** @@ -355,28 +339,25 @@ export const FullBleedCoverWithHeader: Story = { */ export const WithFullBleed: Story = { argTypes: { open: { control: false } }, - args: { - defaultOpen: true, - children: ( - <> - - Featured image - - } - > - -
- - Content below the full-bleed area. - - - ), - }, + render: ( {} ) => ( + + + Featured image + + } + > + +
+ + Content below the full-bleed area. + + + ), }; diff --git a/packages/ui/src/collapsible/stories/index.story.tsx b/packages/ui/src/collapsible/stories/index.story.tsx index 730c583553daa9..7dc7cc1fef033e 100644 --- a/packages/ui/src/collapsible/stories/index.story.tsx +++ b/packages/ui/src/collapsible/stories/index.story.tsx @@ -22,45 +22,37 @@ export default meta; type Story = StoryObj< typeof Collapsible.Root >; export const Default: Story = { - args: { - children: ( - <> - Toggle - -

Collapsible content here.

-
- - ), - }, + render: ( {} ) => ( + + Toggle + +

Collapsible content here.

+
+
+ ), }; export const DefaultOpen: Story = { argTypes: { open: { control: false } }, - args: { - defaultOpen: true, - children: ( - <> - Toggle - -

This panel is open by default.

-
- - ), - }, + render: ( {} ) => ( + + Toggle + +

This panel is open by default.

+
+
+ ), }; export const Disabled: Story = { - args: { - disabled: true, - children: ( - <> - Toggle (disabled) - -

This content cannot be toggled.

-
- - ), - }, + render: ( {} ) => ( + + Toggle (disabled) + +

This content cannot be toggled.

+
+
+ ), }; /** @@ -71,27 +63,25 @@ export const Disabled: Story = { * match — improving discoverability without sacrificing the collapsed layout. */ export const HiddenUntilFound: Story = { - render: function HiddenUntilFound() { - return ( -
-

- Use the browser's find-in-page (Ctrl/Cmd+F) to search - for "hidden treasure". The collapsed panel will - automatically expand to reveal the match. -

- - Expand to reveal - -

- This is the hidden treasure that can be found via - the browser's built-in page search even while - the panel is collapsed. -

-
-
-
- ); - }, + render: ( {} ) => ( +
+

+ Use the browser's find-in-page (Ctrl/Cmd+F) to search for + "hidden treasure". The collapsed panel will + automatically expand to reveal the match. +

+ + Expand to reveal + +

+ This is the hidden treasure that can be found via the + browser's built-in page search even while the panel + is collapsed. +

+
+
+
+ ), }; export const Controlled: Story = { @@ -99,7 +89,7 @@ export const Controlled: Story = { open: { control: false }, defaultOpen: { control: false }, }, - render: function Controlled() { + render: function Controlled( {} ) { const [ open, setOpen ] = useState( false ); return ( diff --git a/packages/ui/src/dialog/stories/index.story.tsx b/packages/ui/src/dialog/stories/index.story.tsx index 551c21739bc7d1..9490cfaaa494ad 100644 --- a/packages/ui/src/dialog/stories/index.story.tsx +++ b/packages/ui/src/dialog/stories/index.story.tsx @@ -43,29 +43,27 @@ type Story = StoryObj< typeof Dialog.Root >; * what happens when clicking the close icon. */ export const _Default: Story = { - args: { - children: ( - <> - Open Dialog - - - Welcome - - - - - This dialog demonstrates best practices for - informational dialogs. It includes a close icon - because dismissing it is safe and expected. - - - - Got it - - - - ), - }, + render: ( {} ) => ( + + Open Dialog + + + Welcome + + + + + This dialog demonstrates best practices for + informational dialogs. It includes a close icon because + dismissing it is safe and expected. + + + + Got it + + + + ), }; const ALL_SIZES = [ 'small', 'medium', 'large', 'stretch', 'full' ] as const; @@ -135,9 +133,11 @@ function SizePlaygroundContent() { } export const AllSizes: Story = { - args: { - children: , - }, + render: ( {} ) => ( + + + + ), }; /** @@ -158,35 +158,33 @@ export const AllSizes: Story = { */ export const WithCustomZIndex: Story = { name: 'With Custom z-index', - args: { - children: ( - <> - Open Dialog - - } - > - - Custom z-index - - - - - The backdrop and popup render at `z-index: 9999` via - the `--wp-ui-dialog-z-index` CSS custom property, - set on `Dialog.Portal` through the `portal` prop. - - - - Got it - - - - ), - }, + render: ( {} ) => ( + + Open Dialog + + } + > + + Custom z-index + + + + + The backdrop and popup render at `z-index: 9999` via the + `--wp-ui-dialog-z-index` CSS custom property, set on + `Dialog.Portal` through the `portal` prop. + + + + Got it + + + + ), }; function StickyToggle( { @@ -307,9 +305,11 @@ function ScrollableContent() { * dialog and stay in sync. */ export const Scrollable: Story = { - args: { - children: , - }, + render: ( {} ) => ( + + + + ), }; /** @@ -320,29 +320,26 @@ export const Scrollable: Story = { * keeps its `

` element while being visually hidden. */ export const WithVisuallyHiddenTitle: Story = { - args: { - children: ( - <> - Open Dialog - - - }> - Accessible dialog heading - - - - -

- This dialog has a visually hidden title. Inspect the - DOM or use a screen reader to verify the heading is - present. -

-
- - Got it - -
- - ), - }, + render: ( {} ) => ( + + Open Dialog + + + }> + Accessible dialog heading + + + + +

+ This dialog has a visually hidden title. Inspect the DOM + or use a screen reader to verify the heading is present. +

+
+ + Got it + +
+
+ ), }; diff --git a/packages/ui/src/drawer/stories/index.story.tsx b/packages/ui/src/drawer/stories/index.story.tsx index 657fb35f64e06a..d860c9e75795a4 100644 --- a/packages/ui/src/drawer/stories/index.story.tsx +++ b/packages/ui/src/drawer/stories/index.story.tsx @@ -42,27 +42,25 @@ type Story = StoryObj< typeof Drawer.Root >; * experiment with `swipeDirection` and `modal`. */ export const _Default: Story = { - args: { - children: ( - <> - Open Drawer - - - Navigation - - - - - Browse through the available sections below. - - - - Done - - - - ), - }, + render: ( {} ) => ( + + Open Drawer + + + Navigation + + + + + Browse through the available sections below. + + + + Done + + + + ), }; const directions = [ @@ -128,13 +126,6 @@ export const Controlled: Story = { const [ open, setOpen ] = useState( false ); return ( - { args.children } - - ); - }, - args: { - children: ( - <> Open Controlled Drawer @@ -151,8 +142,8 @@ export const Controlled: Story = { Close - - ), + + ); }, argTypes: { open: { control: false }, @@ -167,33 +158,26 @@ export const Controlled: Story = { * Users can interact with content behind the drawer while it is open. */ export const NonModal: Story = { - args: { - swipeDirection: 'right', - modal: false, - children: ( - <> - Open Non-Modal Drawer - - - Non-Modal - - - - - This drawer does not trap focus and allows - interaction with the rest of the page while open. - - - - Close - - - - ), - }, - render: function NonModalRender( args ) { - return { args.children }; - }, + render: ( {} ) => ( + + Open Non-Modal Drawer + + + Non-Modal + + + + + This drawer does not trap focus and allows interaction + with the rest of the page while open. + + + + Close + + + + ), }; const ALL_SIZES: NonNullable< @@ -285,36 +269,34 @@ function DirectionSelector( { */ export const WithCustomZIndex: Story = { name: 'With Custom z-index', - args: { - children: ( - <> - Open Drawer - - } - > - - Custom z-index - - - - - The backdrop, viewport, and popup render at - `z-index: 9999` via the `--wp-ui-drawer-z-index` CSS - custom property, set on `Drawer.Portal` through the - `portal` prop. - - - - Got it - - - - ), - }, + render: ( {} ) => ( + + Open Drawer + + } + > + + Custom z-index + + + + + The backdrop, viewport, and popup render at `z-index: + 9999` via the `--wp-ui-drawer-z-index` CSS custom + property, set on `Drawer.Portal` through the `portal` + prop. + + + + Got it + + + + ), }; /** diff --git a/packages/ui/src/empty-state/stories/index.story.tsx b/packages/ui/src/empty-state/stories/index.story.tsx index d2a404e773e84e..e10016cce50ab0 100644 --- a/packages/ui/src/empty-state/stories/index.story.tsx +++ b/packages/ui/src/empty-state/stories/index.story.tsx @@ -31,47 +31,43 @@ export default meta; type Story = StoryObj< typeof EmptyState.Root >; export const Default: Story = { - args: { - children: ( - <> - - No results found - - Try adjusting your search or filter to find what you're - looking for. - - - - - - - ), - }, + render: ( {} ) => ( + + + No results found + + Try adjusting your search or filter to find what you're + looking for. + + + + + + + ), }; export const WithCustomVisual: Story = { - args: { - children: ( - <> - - - - - - All caught up! - - You've completed all your tasks. Great work! - - - - - - ), - }, + render: ( {} ) => ( + + + + + + + All caught up! + + You've completed all your tasks. Great work! + + + + + + ), }; diff --git a/packages/ui/src/form/primitives/autocomplete/stories/index.story.tsx b/packages/ui/src/form/primitives/autocomplete/stories/index.story.tsx index c4cb05265f8ed2..7514ffe584647d 100644 --- a/packages/ui/src/form/primitives/autocomplete/stories/index.story.tsx +++ b/packages/ui/src/form/primitives/autocomplete/stories/index.story.tsx @@ -52,29 +52,29 @@ type Story = StoryObj< typeof Autocomplete.Root >; export const Default: Story = { args: { items: URLS, - children: ( - <> - - - No matching items. - - - - { ( item: FixtureItem ) => ( - - { item.value } - - ) } - - - - - - ), }, + render: ( { items = URLS } ) => ( + + + + No matching items. + + + + { ( item: FixtureItem ) => ( + + { item.value } + + ) } + + + + + + ), }; /** @@ -226,55 +226,55 @@ export const Inline: Story = { export const WithSearchIconAndClearButton: Story = { args: { items: URLS, - children: ( - <> - - - - - } - suffix={ - - - - } - /> - } - /> - - - No matching items. - - - - { ( item: FixtureItem ) => ( - - { item.value } - - ) } - - - - - - ), }, + render: ( { items = URLS } ) => ( + + + + + + } + suffix={ + + + + } + /> + } + /> + + + No matching items. + + + + { ( item: FixtureItem ) => ( + + { item.value } + + ) } + + + + + + ), }; /** * Experimental: Textarea with inline autocomplete triggered by `@`. */ export const TextareaInlineAutocomplete: Story = { - render: function Template() { + render: function Template( {} ) { const textareaRef = useRef< HTMLTextAreaElement >( null ); const [ value, setValue ] = useState( '' ); const [ open, setOpen ] = useState( false ); @@ -424,34 +424,34 @@ export const WithCustomZIndex: Story = { name: 'With Custom z-index', args: { items: URLS, - children: ( - <> - - - } - > - - - - { ( item: FixtureItem ) => ( - - { item.value } - - ) } - - - - - - ), }, + render: ( { items = URLS } ) => ( + + + + } + > + + + + { ( item: FixtureItem ) => ( + + { item.value } + + ) } + + + + + + ), }; /** @@ -461,39 +461,39 @@ export const WithCustomZIndex: Story = { export const Grouped: Story = { args: { items: GROUPED_COMMANDS, - children: ( - <> - - - No matching items. - - - - { ( group: FixtureGroup ) => ( - - - { group.label } - - - { ( item: FixtureItem ) => ( - - { item.value } - - ) } - - - ) } - - - - - - ), }, + render: ( { items = GROUPED_COMMANDS } ) => ( + + + + No matching items. + + + + { ( group: FixtureGroup ) => ( + + + { group.label } + + + { ( item: FixtureItem ) => ( + + { item.value } + + ) } + + + ) } + + + + + + ), }; diff --git a/packages/ui/src/form/primitives/combobox/stories/index.story.tsx b/packages/ui/src/form/primitives/combobox/stories/index.story.tsx index fd40d1ddf1005f..67639a47e4b3c5 100644 --- a/packages/ui/src/form/primitives/combobox/stories/index.story.tsx +++ b/packages/ui/src/form/primitives/combobox/stories/index.story.tsx @@ -43,65 +43,65 @@ const inputWrapperStyle = { export const Default: Story = { args: { items: ITEMS, - children: ( - <> - - -
- -
- No results found. - - - - { ( item: FixtureItem ) => ( - - { item.label } - - ) } - - - -
- - ), }, + render: ( { items = ITEMS } ) => ( + + + +
+ +
+ No results found. + + + + { ( item: FixtureItem ) => ( + + { item.label } + + ) } + + + +
+
+ ), }; export const Compact: Story = { args: { defaultValue: ITEMS[ 0 ], items: ITEMS, - children: ( - <> - - -
- -
- No results found. - - - - { ( item: FixtureItem ) => ( - - { item.label } - - ) } - - - -
- - ), }, + render: ( { items = ITEMS, defaultValue } ) => ( + + + +
+ +
+ No results found. + + + + { ( item: FixtureItem ) => ( + + { item.label } + + ) } + + + +
+
+ ), }; /** @@ -116,34 +116,31 @@ export const DetachedInline: Story = { items: ITEMS, multiple: true, inline: true, - children: ( - <> - -
- No results found. - - - { ( item: FixtureItem ) => ( - - { item.label } - - ) } - - -
- - ), }, + render: ( { items = ITEMS, multiple, inline } ) => ( + + +
+ No results found. + + + { ( item: FixtureItem ) => ( + + { item.label } + + ) } + + +
+
+ ), }; export const Creatable: Story = { @@ -280,67 +277,67 @@ export const WithCustomTriggerAndItem: Story = { args: { items: ITEMS, defaultValue: ITEMS[ 0 ], - children: ( - <> - - { ( item: FixtureItem ) => ( - ( + + + { ( item: FixtureItem ) => ( + + - - { item.label } - - ) } - - -
- -
- - - - { ( item: FixtureItem ) => ( - + { item.label } +
+ ) } +
+ +
+ +
+ + + + { ( item: FixtureItem ) => ( + +
-
{ item.label } +
- - ) } - - - - - - ), - }, + 99 in stock + +
+
+ ) } +
+
+
+
+ + ), }; /** @@ -362,37 +359,37 @@ export const WithCustomZIndex: Story = { args: { defaultValue: ITEMS[ 0 ], items: ITEMS, - children: ( - <> - - - } - > -
- -
- - - - { ( item: FixtureItem ) => ( - - { item.label } - - ) } - - - -
- - ), }, + render: ( { items = ITEMS, defaultValue } ) => ( + + + + } + > +
+ +
+ + + + { ( item: FixtureItem ) => ( + + { item.label } + + ) } + + + +
+
+ ), }; diff --git a/packages/ui/src/form/primitives/field/stories/index.story.tsx b/packages/ui/src/form/primitives/field/stories/index.story.tsx index 22d278501b12e9..762631c3bd0b73 100644 --- a/packages/ui/src/form/primitives/field/stories/index.story.tsx +++ b/packages/ui/src/form/primitives/field/stories/index.story.tsx @@ -29,19 +29,15 @@ export default meta; * you can simply place your control in the `render` prop of `Field.Control`. */ export const Default: StoryObj< typeof Field.Root > = { - args: { - children: ( - <> - Label - } - /> - - The accessible description. - - - ), - }, + render: ( {} ) => ( + + Label + } + /> + The accessible description. + + ), }; const MyNonRefForwardingControl = ( @@ -113,16 +109,14 @@ export const UsingAriaLabelledby: StoryObj< typeof Field.Root > = { * hidden but remains accessible to screen readers. */ export const HiddenLabel: StoryObj< typeof Field.Root > = { - args: { - children: ( - <> - Label - } - /> - - ), - }, + render: ( {} ) => ( + + Label + } + /> + + ), }; /** @@ -136,15 +130,13 @@ export const HiddenLabel: StoryObj< typeof Field.Root > = { * so the readout is not unnecessarily verbose for screen reader users. */ export const WithDetails: StoryObj< typeof Field.Root > = { - args: { - children: ( - <> - Label - } - /> - { DETAILS_EXAMPLE } - - ), - }, + render: ( {} ) => ( + + Label + } + /> + { DETAILS_EXAMPLE } + + ), }; diff --git a/packages/ui/src/form/primitives/fieldset/stories/index.story.tsx b/packages/ui/src/form/primitives/fieldset/stories/index.story.tsx index 3ca119c6e69fcb..5d4a5fca54dded 100644 --- a/packages/ui/src/form/primitives/fieldset/stories/index.story.tsx +++ b/packages/ui/src/form/primitives/fieldset/stories/index.story.tsx @@ -23,22 +23,20 @@ export default meta; type Story = StoryObj< typeof Fieldset.Root >; export const Default: Story = { - args: { - children: ( - <> - Legend - { [ 'Apples', 'Bananas' ].map( ( fruit ) => ( - // eslint-disable-next-line jsx-a11y/label-has-associated-control - - ) ) } - - This is a description for the entire fieldset. - - - ), - }, + render: ( {} ) => ( + + Legend + { [ 'Apples', 'Bananas' ].map( ( fruit ) => ( + // eslint-disable-next-line jsx-a11y/label-has-associated-control + + ) ) } + + This is a description for the entire fieldset. + + + ), }; /** @@ -46,19 +44,17 @@ export const Default: Story = { * hidden but remains accessible to screen readers. */ export const HiddenLegend: Story = { - args: { - children: ( - <> - Legend - { [ 'Apples', 'Bananas' ].map( ( fruit ) => ( - // eslint-disable-next-line jsx-a11y/label-has-associated-control - - ) ) } - - ), - }, + render: ( {} ) => ( + + Legend + { [ 'Apples', 'Bananas' ].map( ( fruit ) => ( + // eslint-disable-next-line jsx-a11y/label-has-associated-control + + ) ) } + + ), }; /** @@ -72,18 +68,16 @@ export const HiddenLegend: Story = { * so the readout is not unnecessarily verbose for screen reader users. */ export const WithDetails: Story = { - args: { - children: ( - <> - Legend - { [ 'Apples', 'Bananas' ].map( ( fruit ) => ( - // eslint-disable-next-line jsx-a11y/label-has-associated-control - - ) ) } - { DETAILS_EXAMPLE } - - ), - }, + render: ( {} ) => ( + + Legend + { [ 'Apples', 'Bananas' ].map( ( fruit ) => ( + // eslint-disable-next-line jsx-a11y/label-has-associated-control + + ) ) } + { DETAILS_EXAMPLE } + + ), }; diff --git a/packages/ui/src/form/primitives/select/stories/index.story.tsx b/packages/ui/src/form/primitives/select/stories/index.story.tsx index 7f71dfd86766ff..92a68585a0e471 100644 --- a/packages/ui/src/form/primitives/select/stories/index.story.tsx +++ b/packages/ui/src/form/primitives/select/stories/index.story.tsx @@ -23,37 +23,67 @@ export default meta; type Story = StoryObj< typeof Select.Root >; -const defaultItems = Array.from( { length: 6 }, ( _, index ) => ( { - value: `item-${ index + 1 }`, - label: `Item ${ index + 1 }`, -} ) ); +type SelectStoryItem = { + value: string | null; + label: string; + disabled?: boolean; +}; + +type SelectStoryArgs = { + items?: readonly SelectStoryItem[]; + defaultValue?: SelectStoryItem | string | null; + disabled?: boolean; +}; + +function resolveItems( + items: unknown, + fallback: readonly SelectStoryItem[] +): SelectStoryItem[] { + return Array.isArray( items ) + ? ( items as SelectStoryItem[] ) + : [ ...fallback ]; +} + +const defaultItems: SelectStoryItem[] = Array.from( + { length: 6 }, + ( _, index ) => ( { + value: `item-${ index + 1 }`, + label: `Item ${ index + 1 }`, + } ) +); export const Default: Story = { args: { items: defaultItems, - children: ( - <> + }, + render: ( args ) => { + const items = resolveItems( args.items, defaultItems ); + return ( + - { defaultItems.map( ( item ) => ( + { items.map( ( item ) => ( { item.label } ) ) } - - ), + + ); }, }; export const Compact: Story = { args: { ...Default.args, - children: ( - <> + }, + render: ( args ) => { + const items = resolveItems( args.items, defaultItems ); + return ( + - { defaultItems.map( ( item ) => ( + { items.map( ( item ) => ( ) ) } - - ), + + ); }, }; @@ -78,24 +108,24 @@ export const Compact: Story = { */ export const Minimal: Story = { args: { - children: ( - <> - - - { Array.from( { length: 6 }, ( _, index ) => ( - - { `${ index + 1 }` } - - ) ) } - - - ), defaultValue: '1', }, + render: ( { defaultValue } ) => ( + + + + { Array.from( { length: 6 }, ( _, index ) => ( + + { `${ index + 1 }` } + + ) ) } + + + ), }; /** @@ -105,22 +135,25 @@ export const Minimal: Story = { export const WithCustomPlaceholder: Story = { args: { items: defaultItems, - children: ( - <> + }, + render: ( args ) => { + const items = resolveItems( args.items, defaultItems ); + return ( + - { defaultItems.map( ( item ) => ( + { items.map( ( item ) => ( { item.label } ) ) } - - ), + + ); }, }; -const nullValueOptionItems = [ +const nullValueOptionItems: SelectStoryItem[] = [ { value: null, label: 'Select theme' }, { value: 'system', label: 'System default' }, { value: 'light', label: 'Light' }, @@ -135,11 +168,14 @@ const nullValueOptionItems = [ export const WithNullValueOption: Story = { args: { items: nullValueOptionItems, - children: ( - <> + }, + render: ( args ) => { + const items = resolveItems( args.items, nullValueOptionItems ); + return ( + - { nullValueOptionItems.map( ( item ) => ( + { items.map( ( item ) => ( ) ) } - - ), + + ); }, }; @@ -162,25 +198,28 @@ export const WithNullValueOption: Story = { export const Labeling: Story = { args: { ...Default.args, - children: ( - <> + }, + render: ( args ) => { + const items = resolveItems( args.items, defaultItems ); + return ( + - { defaultItems.map( ( item ) => ( + { items.map( ( item ) => ( { item.label } ) ) } - - ), + + ); }, }; const longItemValue = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'; -const overflowItems = [ +const overflowItems: SelectStoryItem[] = [ { value: 'long-item', label: longItemValue, @@ -194,43 +233,55 @@ const overflowItems = [ export const WithOverflow: Story = { args: { items: overflowItems, - children: ( - <> + defaultValue: overflowItems[ 0 ], + }, + render: ( args ) => { + const { defaultValue } = args as SelectStoryArgs; + const items = resolveItems( args.items, overflowItems ); + return ( + - { overflowItems.map( ( item ) => ( + { items.map( ( item ) => ( { item.label } ) ) } - - ), - defaultValue: overflowItems[ 0 ], + + ); }, }; export const Disabled: Story = { args: { ...Default.args, - children: ( - <> + defaultValue: defaultItems[ 0 ], + disabled: true, + }, + render: ( args ) => { + const { defaultValue, disabled } = args as SelectStoryArgs; + const items = resolveItems( args.items, defaultItems ); + return ( + - { defaultItems.map( ( item ) => ( + { items.map( ( item ) => ( { item.label } ) ) } - - ), - defaultValue: defaultItems[ 0 ], - disabled: true, + + ); }, }; -const disabledItemItems = [ +const disabledItemItems: SelectStoryItem[] = [ { value: 'item-1', label: 'Item 1', @@ -245,11 +296,16 @@ const disabledItemItems = [ export const WithDisabledItem: Story = { args: { items: disabledItemItems, - children: ( - <> + defaultValue: disabledItemItems[ 0 ], + }, + render: ( args ) => { + const { defaultValue } = args as SelectStoryArgs; + const items = resolveItems( args.items, disabledItemItems ); + return ( + - { disabledItemItems.map( ( item ) => ( + { items.map( ( item ) => ( ) ) } - - ), - defaultValue: disabledItemItems[ 0 ], + + ); }, }; -const customOptions = [ +const customOptions: SelectStoryItem[] = [ { value: 'user-1', label: 'User 1 (Admin)', @@ -283,8 +338,13 @@ const customOptions = [ export const WithCustomTriggerAndItem: Story = { args: { items: customOptions, - children: ( - <> + defaultValue: customOptions[ 0 ], + }, + render: ( args ) => { + const { defaultValue } = args as SelectStoryArgs; + const items = resolveItems( args.items, customOptions ); + return ( + { ( item ) => ( - { customOptions.map( ( item ) => ( + { items.map( ( item ) => ( { item.label } ) ) } - - ), - defaultValue: customOptions[ 0 ], + + ); }, }; @@ -339,8 +398,11 @@ export const WithCustomZIndex: Story = { name: 'With Custom z-index', args: { ...Default.args, - children: ( - <> + }, + render: ( args ) => { + const items = resolveItems( args.items, defaultItems ); + return ( + } > - { defaultItems.map( ( item ) => ( + { items.map( ( item ) => ( { item.label } ) ) } - - ), + + ); }, }; diff --git a/packages/ui/src/form/select-control/stories/index.story.tsx b/packages/ui/src/form/select-control/stories/index.story.tsx index 93a3f0dccaebde..2959e075355c1d 100644 --- a/packages/ui/src/form/select-control/stories/index.story.tsx +++ b/packages/ui/src/form/select-control/stories/index.story.tsx @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import { SelectControl } from '../'; +import type { SelectItem } from '../types'; import { WITH_DETAILS_DESCRIPTION, DETAILS_EXAMPLE, @@ -20,7 +21,7 @@ export default meta; type Story = StoryObj< typeof SelectControl >; -const defaultItems = [ +const defaultItems: SelectItem[] = [ { value: '1', label: 'Item 1', @@ -52,7 +53,7 @@ export const WithCustomPlaceholder: Story = { }, }; -const nullValueOptionItems = [ +const nullValueOptionItems: SelectItem[] = [ { value: null, label: 'Select theme', @@ -102,7 +103,7 @@ export const WithDetails: Story = { }, }; -const disabledOptionItems = [ +const disabledOptionItems: SelectItem[] = [ { value: '1', label: 'Item 1', @@ -123,7 +124,7 @@ export const WithDisabledOption: Story = { }, }; -const userOptions: React.ComponentProps< typeof SelectControl >[ 'items' ] = [ +const userOptions: SelectItem[] = [ { value: '1', label: 'User 1 (Admin)', @@ -175,21 +176,25 @@ export const WithCustomTriggerAndItems: Story = { label: 'Label', description: 'This is the description.', triggerContent: ( item ) => , - children: ( - <> - { userOptions.map( ( item ) => ( - - - - ) ) } - - ), defaultValue: userOptions[ 0 ], }, + render: ( { items = userOptions, triggerContent, ...args } ) => ( + + { items.map( ( item ) => ( + + + + ) ) } + + ), }; /** @@ -202,19 +207,19 @@ export const WithCustomTriggerAndItems: Story = { export const WithItemsArrayAndPartialCustomization: Story = { args: { ...Default.args, - children: ( - <> - { Default.args?.items?.map( ( item ) => ( - - ✨ { item.label } - - ) ) } - - ), }, + render: ( { items = defaultItems, ...args } ) => ( + + { items.map( ( item ) => ( + + ✨ { item.label } + + ) ) } + + ), }; diff --git a/packages/ui/src/link-button/stories/index.story.tsx b/packages/ui/src/link-button/stories/index.story.tsx index e827710d0d008b..8a87112e3ace64 100644 --- a/packages/ui/src/link-button/stories/index.story.tsx +++ b/packages/ui/src/link-button/stories/index.story.tsx @@ -135,15 +135,12 @@ export const AllTonesAndVariants: Story = { export const WithIcon: Story = { ...Default, - args: { - ...Default.args, - children: ( - <> - - Link button - - ), - }, + render: ( { children: _children, ...args } ) => ( + + + Link button + + ), }; export const OpenInNewTab: Story = { diff --git a/packages/ui/src/notice/stories/index.story.tsx b/packages/ui/src/notice/stories/index.story.tsx index e047056accc67b..a9327155aa7064 100644 --- a/packages/ui/src/notice/stories/index.story.tsx +++ b/packages/ui/src/notice/stories/index.story.tsx @@ -25,140 +25,167 @@ export default meta; type Story = StoryObj< typeof Notice.Root >; export const Default: Story = { - args: { - children: ( - <> - Notice Title - - Description text with details about this notification. - - - Primary button - - Secondary button - - Link - - - - ), - }, + render: ( {} ) => ( + + Notice Title + + Description text with details about this notification. + + + Primary button + + Secondary button + + Link + + + + ), }; export const Info: Story = { - ...Default, - args: { - ...Default.args, - intent: 'info', - }, + render: ( {} ) => ( + + Notice Title + + Description text with details about this notification. + + + Primary button + + Secondary button + + Link + + + + ), }; export const Warning: Story = { - ...Default, - args: { - ...Default.args, - intent: 'warning', - }, + render: ( {} ) => ( + + Notice Title + + Description text with details about this notification. + + + Primary button + + Secondary button + + Link + + + + ), }; export const Success: Story = { - ...Default, - args: { - ...Default.args, - intent: 'success', - }, + render: ( {} ) => ( + + Notice Title + + Description text with details about this notification. + + + Primary button + + Secondary button + + Link + + + + ), }; export const Error: Story = { - ...Default, - args: { - ...Default.args, - intent: 'error', - }, + render: ( {} ) => ( + + Notice Title + + Description text with details about this notification. + + + Primary button + + Secondary button + + Link + + + + ), }; /** * Omit Notice.CloseIcon to make the notice non-dismissable. */ export const NonDismissible: Story = { - args: { - intent: 'warning', - children: ( - <> - Action Required - - This notice cannot be dismissed by the user. - - - Take Action - Visit link - - - ), - }, + render: ( {} ) => ( + + Action Required + + This notice cannot be dismissed by the user. + + + Take Action + Visit link + + + ), }; /** * Pass `icon={ null }` to hide the default decorative icon. */ export const WithoutIcon: Story = { - args: { - intent: 'info', - icon: null, - children: ( - <> - No Icon - - This notice has no decorative icon displayed. - - - - ), - }, + render: ( {} ) => ( + + No Icon + + This notice has no decorative icon displayed. + + + + ), }; export const WithoutActions: Story = { - args: { - intent: 'info', - children: ( - <> - Simple Notice - - A dismissable notice without any action buttons or links. - - - - ), - }, + render: ( {} ) => ( + + Simple Notice + + A dismissable notice without any action buttons or links. + + + + ), }; /** * Title only, no description or actions. */ export const TitleOnly: Story = { - args: { - children: ( - <> - Just a title - - - ), - }, + render: ( {} ) => ( + + Just a title + + + ), }; /** * Description only, no title or actions. */ export const DescriptionOnly: Story = { - args: { - intent: 'info', - children: ( - <> - - Just a description without title or actions. - - - - ), - }, + render: ( {} ) => ( + + + Just a description without title or actions. + + + + ), }; diff --git a/packages/ui/src/popover/stories/index.story.tsx b/packages/ui/src/popover/stories/index.story.tsx index d10c3d47ba04b9..1323587ab67b27 100644 --- a/packages/ui/src/popover/stories/index.story.tsx +++ b/packages/ui/src/popover/stories/index.story.tsx @@ -36,29 +36,22 @@ export default meta; type Story = StoryObj< typeof Popover.Root >; export const Default: Story = { - argTypes: { - children: { control: { type: 'text' } }, - }, - args: { - children: ( - <> - Open Popover - - - - Popover title - - - Popover description - - - - ), - }, + render: ( {} ) => ( + + Open Popover + + + + Popover title + + Popover description + + + ), }; /** @@ -66,25 +59,21 @@ export const Default: Story = { * from the popup content when an arrow indicator is not desired. */ export const NoArrow: Story = { - args: { - children: ( - <> - Open Popover - - - Popover title - - - Popover description - - - - ), - }, + render: ( {} ) => ( + + Open Popover + + + Popover title + + Popover description + + + ), }; /** @@ -95,7 +84,7 @@ export const NoArrow: Story = { */ export const Positioning: Story = { parameters: { controls: { disable: true } }, - render: function Render() { + render: function Render( {} ) { const sides = [ 'top', 'right', 'bottom', 'left' ] as const; const aligns = [ 'start', 'center', 'end' ] as const; @@ -150,41 +139,39 @@ export const Positioning: Story = { * close action — matching the Dialog close-icon pattern. */ export const WithCloseButton: Story = { - args: { - children: ( - <> - Settings - - -
- Settings - - } - /> -
- - Configure your notification preferences and display - settings. - -
- - ), - }, + render: ( {} ) => ( + + Settings + + +
+ Settings + + } + /> +
+ + Configure your notification preferences and display + settings. + +
+
+ ), }; /** @@ -201,27 +188,7 @@ export const Controlled: Story = { onOpenChange: { control: false }, defaultOpen: { control: false }, }, - args: { - children: ( - <> - Toggle Popover - - - - Controlled Popover - - - This popover is controlled by external state. - - - - ), - }, - render: function Render( args ) { + render: function Render( {} ) { const [ isOpen, setIsOpen ] = useState( false ); const checkboxId = useId(); const checkboxRef = useRef< HTMLInputElement >( null ); @@ -236,7 +203,6 @@ export const Controlled: Story = { } } > { if ( @@ -256,7 +222,22 @@ export const Controlled: Story = { setIsOpen( nextOpen ); } } - /> + > + Toggle Popover + + + + Controlled Popover + + + This popover is controlled by external state. + + +