Components Manifest

AlertDialog.Root

design-system-components-alertdialog · ../packages/ui/src/alert-dialog/stories/index.story.tsx
A badge component for displaying labels with semantic intent.
Prop types 4 prop types
Component: ../packages/ui/src/badge/badge.tsx::Badge
Props:
/**
 * The text to display in the badge.
 */
children: string

/**
 * CSS class name to apply to the component.
 */
className?: string

/**
 * The semantic intent of the badge, communicating its meaning through color.
 * 
 * @default "none"
 */
intent?: | 'high'
| 'medium'
| 'low'
| 'stable'
| 'informational'
| 'draft'
| 'none' = 'none'

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: | ComponentRenderFn< HTMLAttributesWithRef >
| React.ReactElement< Record< string, unknown > >
Imports
import { AlertDialog, Text } from "@wordpress/ui";
import { Menu } from "@base-ui/react/menu";
Default story ok
Standard confirmation dialog for reversible actions. The dialog can be dismissed via Escape key or the cancel/confirm buttons. Backdrop click is blocked.
const Default = () => <AlertDialog.Root>(<>
        <AlertDialog.Trigger>Move to trash</AlertDialog.Trigger>
        <AlertDialog.Popup
            title="Move to trash?"
            description="This post will be moved to trash. You can restore it later."
        />
    </>)</AlertDialog.Root>;
Irreversible story ok
Confirmation dialog for irreversible actions that cannot be undone. The confirm button uses error/danger coloring.
const Irreversible = () => <AlertDialog.Root>(<>
        <AlertDialog.Trigger>Delete permanently</AlertDialog.Trigger>
        <AlertDialog.Popup
            intent="irreversible"
            title="Delete permanently?"
            description="This action cannot be undone. All data will be lost."
            confirmButtonText="Delete permanently"
        />
    </>)</AlertDialog.Root>;
Custom Labels story ok
Example with custom button labels for both confirm and cancel buttons.
const CustomLabels = () => <AlertDialog.Root>(<>
        <AlertDialog.Trigger>Send feedback</AlertDialog.Trigger>
        <AlertDialog.Popup
            title="Send feedback?"
            description="Your feedback helps us improve. Would you like to send it now?"
            confirmButtonText="Send feedback"
            cancelButtonText="Not now"
        />
    </>)</AlertDialog.Root>;
With Custom Content story ok
Use `children` to render custom content between the description and the action buttons. The `description` should be self-contained for accessibility (`aria-describedby`); `children` adds supplementary detail.
const WithCustomContent = () => <AlertDialog.Root>(<>
        <AlertDialog.Trigger>Remove pages</AlertDialog.Trigger>
        <AlertDialog.Popup
            title="Remove 3 pages?"
            description="These pages will be moved to trash."
            confirmButtonText="Delete pages"
        >
            <ul
                style={ {
                    margin: 0,
                    paddingInlineStart: 'var(--wpds-dimension-gap-lg)',
                } }
            >
                <Text render={ <li /> }>About us</Text>
                <Text render={ <li /> }>Contact</Text>
                <Text render={ <li /> }>Privacy policy</Text>
            </ul>
        </AlertDialog.Popup>
    </>)</AlertDialog.Root>;
Menu Trigger story ok
Example showing composition with a menu. The `AlertDialog.Trigger` is composed with Base UI's `Menu.Item` using the `render` prop, allowing the menu item to directly trigger the alert dialog. Note: the example currently uses the `Menu` component from BaseUI, although consumers should not use BaseUI directly and instead use the DS `Menu` component (not ready yet).
const MenuTrigger = () => {
    const [ menuOpen, setMenuOpen ] = useState( false );
    return (
        <>
            <Menu.Root onOpenChange={ setMenuOpen } open={ menuOpen }>
                <Menu.Trigger>Actions ▾</Menu.Trigger>
                <Menu.Portal>
                    <Menu.Positioner>
                        <Menu.Popup style={ menuPopupStyles }>
                            <Menu.Item style={ menuItemStyles }>
                                Edit
                            </Menu.Item>
                            <AlertDialog.Root
                                onConfirm={ () => {
                                    setMenuOpen( false );
                                    action( 'onConfirm' )();
                                } }
                            >
                                <Menu.Item
                                    render={
                                        <AlertDialog.Trigger
                                            // Quick fix to remove `button`-specific styles.
                                            // This shouldn't be an issue once we use the DS `Menu`
                                            // component, which will come with item styles.
                                            render={ <div /> }
                                        />
                                    }
                                    style={ menuItemStyles }
                                    closeOnClick={ false }
                                >
                                    Delete...
                                    <AlertDialog.Popup
                                        intent="irreversible"
                                        title="Delete permanently?"
                                        description="This action cannot be undone. All data will be lost."
                                        confirmButtonText="Delete permanently"
                                    />
                                </Menu.Item>
                            </AlertDialog.Root>
                        </Menu.Popup>
                    </Menu.Positioner>
                </Menu.Portal>
            </Menu.Root>
        </>
    );
};
Async Confirm story ok
Async confirm flow. The consumer returns a promise from `onConfirm`. The dialog automatically manages the pending state: buttons are disabled and a spinner appears on the confirm button. Toggle between success and failure to test both outcomes. On failure, the consumer catches the error and returns `{ close: false, error: '...' }`. The component displays the message below the action buttons and announces it to screen readers. The error is automatically cleared on the next confirm attempt or when the dialog reopens.
const AsyncConfirm = () => {
    const [ shouldFail, setShouldFail ] = useState( false );
    const successId = useId();
    const failureId = useId();

    return (
        <>
            <fieldset>
                <legend>Async task outcome</legend>
                <label htmlFor={ successId }>
                    <input
                        id={ successId }
                        type="radio"
                        name="async-outcome"
                        checked={ ! shouldFail }
                        onChange={ () => setShouldFail( false ) } />Success (closes dialog)
                                        </label>
                <label htmlFor={ failureId } style={ { marginInlineStart: 12 } }>
                    <input
                        id={ failureId }
                        type="radio"
                        name="async-outcome"
                        checked={ shouldFail }
                        onChange={ () => setShouldFail( true ) } />Failure (dialog stays open, shows error)
                                        </label>
            </fieldset>
            <br />
            <AlertDialog.Root
                onConfirm={ async () => {
                    action( 'onConfirm' )();
                    try {
                        await sleep( 2000 );
                        if ( shouldFail ) {
                            throw new Error( 'Task failed' );
                        }
                    } catch {
                        return {
                            close: false,
                            error: 'Something went wrong. Please try again.',
                        };
                    }
                    return undefined;
                } }>
                <AlertDialog.Trigger>Delete permanently
                                        </AlertDialog.Trigger>
                <AlertDialog.Popup
                    intent="irreversible"
                    title="Delete permanently?"
                    description="This action cannot be undone. All data will be lost."
                    confirmButtonText="Delete permanently" />
            </AlertDialog.Root>
        </>
    );
};
Controlled story ok
The `AlertDialog.Trigger` element is not necessary when the open state is controlled externally. This is useful when the dialog needs to be opened from code or from a non-standard trigger element.
const Controlled = () => {
    const [ isOpen, setIsOpen ] = useState( false );

    return (
        <>
            <button onClick={ () => setIsOpen( true ) }>Open Dialog</button>
            <AlertDialog.Root
                open={ isOpen }
                onOpenChange={ ( open, eventDetails ) => {
                    setIsOpen( open );
                    args.onOpenChange?.( open, eventDetails );
                } }>
                <AlertDialog.Popup
                    title="Move to trash?"
                    description="This post will be moved to trash. You can restore it later." />
            </AlertDialog.Root>
        </>
    );
};

AlignmentControl

blockeditor-alignmentcontrol · ../packages/block-editor/src/components/alignment-control/stories/index.story.jsx
The `AlignmentControl` component renders a dropdown menu that displays alignment options for the selected block. This component is mostly used for blocks that display text, such as Heading, Paragraph, Post Author, Post Comments, Verse, Quote, Post Title, etc... And the available alignment options are `left`, `center` or `right` alignment. If you want to use the alignment control in a toolbar, you should use the `AlignmentToolbar` component instead.
Imports
import { AlignmentControl } from "@wordpress/block-editor";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState();

    return (
        <AlignmentControl
            onChange={ ( ...changeArgs ) => {
                onChange( ...changeArgs );
                setValue( ...changeArgs );
            } }
            value={ value } />
    );
};

AlignmentMatrixControl

components-alignmentmatrixcontrol · ../packages/components/src/alignment-matrix-control/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 3 prop types
Component: ../packages/components/src/alignment-matrix-control/index.tsx
Props:
defaultValue?: any = 'center center'

label?: any = __( 'Alignment Matrix Control' )

width?: any = 92
Imports
import { AlignmentMatrixControl, HStack } from "@wordpress/components";
import { Icon } from "@wordpress/icons";
Default story ok
const Default = ( {
	defaultValue,
	onChange,
	...props
} ) => {
	const [ value, setValue ] =
		useState< AlignmentMatrixControlProps[ 'value' ] >();

	return (
		<AlignmentMatrixControl
			{ ...props }
			onChange={ ( ...changeArgs ) => {
				setValue( ...changeArgs );
				onChange?.( ...changeArgs );
			} }
			value={ value }
		/>
	);
};
Icon Subcomponent story ok
const IconSubcomponent = () => {
	return (
		<HStack justify="flex-start">
			<Icon icon={ <AlignmentMatrixControl.Icon value="top left" /> } />
			<Icon
				icon={ <AlignmentMatrixControl.Icon value="center center" /> }
			/>
		</HStack>
	);
};

AlignmentToolbar

blockeditor-alignmenttoolbar · ../packages/block-editor/src/components/alignment-control/stories/aliginment-toolbar.story.jsx
The `AlignmentToolbar` component renders a dropdown menu that displays alignment options for the selected block in `Toolbar`.
Imports
import { AlignmentToolbar } from "@wordpress/block-editor";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState();

    return (
        <AlignmentToolbar
            onChange={ ( ...changeArgs ) => {
                onChange( ...changeArgs );
                setValue( ...changeArgs );
            } }
            value={ value } />
    );
};

AnglePickerControl

components-anglepickercontrol · ../packages/components/src/angle-picker-control/stories/index.story.tsx
`AnglePickerControl` is a React component to render a UI that allows users to pick an angle. Users can choose an angle in a visual UI with the mouse by dragging an angle indicator inside a circle or by directly inserting the desired angle in a text field. ```jsx import { useState } from '@wordpress/element'; import { AnglePickerControl } from '@wordpress/components'; function Example() { const [ angle, setAngle ] = useState( 0 ); return ( <AnglePickerControl value={ angle } onChange={ setAngle } /> ); } ```
Imports
import { AnglePickerControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ angle, setAngle ] = useState< number >( 0 );

    const handleChange = ( newValue: number ) => {
		setAngle( newValue );
		onChange( newValue );
	};

    return <AnglePickerControl value={ angle } onChange={ handleChange } />;
};

Animate

components-animate · ../packages/components/src/animate/stories/index.story.tsx
Prop type error
File: /home/runner/work/gutenberg/gutenberg/packages/components/src/animate/index.tsx
Error:
No suitable component definition found.
You can debug your component file in this playground: https://react-docgen.dev/playground
Code:
/**
 * External dependencies
 */
import clsx from 'clsx';

/**
 * Internal dependencies
 */
import type { AnimateProps, GetAnimateOptions } from './types';

/**
 * @param type The animation type
 * @return Default origin
 */
function getDefaultOrigin( type?: GetAnimateOptions[ 'type' ] ) {
	return type === 'appear' ? 'top' : 'left';
}

/**
 * @param options
 *
 * @return ClassName that applies the animations
 */
export function getAnimateClassName( options: GetAnimateOptions ) {
	if ( options.type === 'loading' ) {
		return 'components-animate__loading';
	}

	const { type, origin = getDefaultOrigin( type ) } = options;

	if ( type === 'appear' ) {
		const [ yAxis, xAxis = 'center' ] = origin.split( ' ' );
		return clsx( 'components-animate__appear', {
			[ 'is-from-' + xAxis ]: xAxis !== 'center',
			[ 'is-from-' + yAxis ]: yAxis !== 'middle',
		} );
	}

	if ( type === 'slide-in' ) {
		return clsx( 'components-animate__slide-in', 'is-from-' + origin );
	}

	return undefined;
}

/**
 * Simple interface to introduce animations to components.
 *
 * ```jsx
 * import { Animate, Notice } from '@wordpress/components';
 *
 * const MyAnimatedNotice = () => (
 * 	<Animate type="slide-in" options={ { origin: 'top' } }>
 * 		{ ( { className } ) => (
 * 			<Notice className={ className } status="success">
 * 				<p>Animation finished.</p>
 * 			</Notice>
 * 		) }
 * 	</Animate>
 * );
 * ```
 */
export function Animate( { type, options = {}, children }: AnimateProps ) {
	return children( {
		className: getAnimateClassName( {
			type,
			...options,
		} as GetAnimateOptions ),
	} );
}

export default Animate;
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Animate, Notice } from "@wordpress/components";
Default story ok
const Default = ( props ) => (
	<Animate { ...props } />
);
Appear Top Left story ok
const AppearTopLeft = ( props ) => (
	<Animate { ...props } />
);
Appear Top Right story ok
const AppearTopRight = ( props ) => (
	<Animate { ...props } />
);
Appear Bottom Left story ok
const AppearBottomLeft = ( props ) => (
	<Animate { ...props } />
);
Appear Bottom Right story ok
const AppearBottomRight = ( props ) => (
	<Animate { ...props } />
);
Loading story ok
const Loading = ( props ) => (
	<Animate { ...props } />
);
Slide In story ok
const SlideIn = ( props ) => (
	<Animate { ...props } />
);

AspectRatioTool

blockeditor-dimensionstool-aspectratiotool · ../packages/block-editor/src/components/dimensions-tool/stories/aspect-ratio-tool.story.jsx
typedef: {Object} AspectRatioToolProps property: {string} panelId ID of the panel this tool is associated with.property: {string} value Current aspect ratio value.property: {AspectRatioToolPropsOnChange} onChange Callback to update the aspect ratio value.property: {SelectControlProps[]} options Aspect ratio options.property: {string} defaultValue Default aspect ratio value.property: {boolean} isShownByDefault Whether the tool is shown by default.
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 3 prop types
Component: ../packages/block-editor/src/components/dimensions-tool/aspect-ratio-tool.js::default
Props:
defaultValue?: any = 'auto'

isShownByDefault?: any = true

onChange?: any = () => {}
Imports
import { AspectRatioTool } from "@wordpress/block-editor";
import { Panel, __experimentalToolsPanel as ToolsPanel } from "@wordpress/components";
Default story ok
const Default = ( { panelId, onChange: onChangeProp, ...props } ) => {
	const [ value, setValue ] = useState( undefined );
	const resetAll = () => {
		setValue( undefined );
		onChangeProp( undefined );
	};
	return (
		<Panel>
			<ToolsPanel
				label="Aspect Ratio"
				panelId={ panelId }
				resetAll={ resetAll }
			>
				<AspectRatioTool
					panelId={ panelId }
					onChange={ ( nextValue ) => {
						setValue( nextValue );
						onChangeProp( nextValue );
					} }
					value={ value }
					{ ...props }
				/>
			</ToolsPanel>
		</Panel>
	);
};

Badge

components-badge · ../packages/components/src/badge/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 1 prop type
Component: ../packages/components/src/badge/index.tsx::default
Props:
intent?: any = 'default'
Imports
import { Badge } from "@wordpress/components";
Default story ok
const Default = () => <Badge>Code is Poetry</Badge>;
Info story ok
const Info = () => <Badge intent="info" />;
Success story ok
const Success = () => <Badge intent="success" />;
Warning story ok
const Warning = () => <Badge intent="warning" />;
Error story ok
const Error = () => <Badge intent="error" />;

Badge

design-system-components-badge-choosing-intent · ../packages/ui/src/badge/stories/choosing-intent.story.tsx
A badge component for displaying labels with semantic intent.
Prop types 4 prop types
Component: ../packages/ui/src/badge/badge.tsx::Badge
Props:
/**
 * The text to display in the badge.
 */
children: string

/**
 * CSS class name to apply to the component.
 */
className?: string

/**
 * The semantic intent of the badge, communicating its meaning through color.
 * 
 * @default "none"
 */
intent?: | 'high'
| 'medium'
| 'low'
| 'stable'
| 'informational'
| 'draft'
| 'none' = 'none'

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: | ComponentRenderFn< HTMLAttributesWithRef >
| React.ReactElement< Record< string, unknown > >
Imports
import { Badge, Stack } from "@wordpress/ui";
All Intents story ok
const AllIntents = () => (
    <>
        <Badge intent="high">high</Badge>
        <Badge intent="medium">medium</Badge>
        <Badge intent="low">low</Badge>
        <Badge intent="stable">stable</Badge>
        <Badge intent="informational">informational</Badge>
        <Badge intent="draft">draft</Badge>
        <Badge intent="none">none</Badge>
    </>
);
High story ok
const High = () => (
    <>
        <Badge intent="high">Payment declined</Badge>
        <Badge intent="high">Security issue</Badge>
    </>
);
Medium story ok
const Medium = () => (
    <>
        <Badge intent="medium">Approval required</Badge>
        <Badge intent="medium">Review needed</Badge>
    </>
);
Low story ok
const Low = () => (
    <>
        <Badge intent="low">Pending</Badge>
        <Badge intent="low">Queued</Badge>
    </>
);
Informational story ok
const Informational = () => (
    <>
        <Badge intent="informational">Scheduled</Badge>
        <Badge intent="informational">Beta</Badge>
    </>
);
Draft story ok
const Draft = () => (
    <>
        <Badge intent="draft">Draft</Badge>
        <Badge intent="draft">Unpublished</Badge>
    </>
);
Stable story ok
const Stable = () => (
    <>
        <Badge intent="stable">Healthy</Badge>
        <Badge intent="stable">Active</Badge>
    </>
);
None story ok
const None = () => (
    <>
        <Badge intent="none">Inactive</Badge>
        <Badge intent="none">Expired</Badge>
    </>
);
Comment Status story ok
const CommentStatus = () => (
    <>
        <Badge intent="none">Approved</Badge>
        <Badge intent="medium">Approval required</Badge>
    </>
);
Page Status story ok
const PageStatus = () => (
    <>
        <Badge intent="none">Published</Badge>
        <Badge intent="low">Pending</Badge>
        <Badge intent="draft">Draft</Badge>
        <Badge intent="informational">Scheduled</Badge>
        <Badge intent="informational">Private</Badge>
    </>
);
Plugin Status story ok
const PluginStatus = () => (
    <>
        <Badge intent="stable">Active</Badge>
        <Badge intent="none">Inactive</Badge>
    </>
);

Badge

design-system-components-badge · ../packages/ui/src/badge/stories/index.story.tsx
A badge component for displaying labels with semantic intent.
Prop types 4 prop types
Component: ../packages/ui/src/badge/badge.tsx::Badge
Props:
/**
 * The text to display in the badge.
 */
children: string

/**
 * CSS class name to apply to the component.
 */
className?: string

/**
 * The semantic intent of the badge, communicating its meaning through color.
 * 
 * @default "none"
 */
intent?: | 'high'
| 'medium'
| 'low'
| 'stable'
| 'informational'
| 'draft'
| 'none' = 'none'

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: | ComponentRenderFn< HTMLAttributesWithRef >
| React.ReactElement< Record< string, unknown > >
Imports
import { Badge } from "@wordpress/ui";
import { Fragment } from "@wordpress/element";
Default story ok
const Default = () => <Badge>Badge</Badge>;
High story ok
const High = () => <Badge intent="high" />;
Medium story ok
const Medium = () => <Badge intent="medium" />;
Low story ok
const Low = () => <Badge intent="low" />;
Stable story ok
const Stable = () => <Badge intent="stable" />;
Informational story ok
const Informational = () => <Badge intent="informational" />;
Draft story ok
const Draft = () => <Badge intent="draft" />;
None story ok
const None = () => <Badge intent="none" />;
All Intents story ok
const AllIntents = ( args ) => (
    <div
        style={ {
            display: 'grid',
            gridTemplateColumns: 'max-content min-content',
            gap: '1rem',
            color: 'var(--wpds-color-fg-content-neutral)',
        } }
    >
        { (
            [
                'high',
                'medium',
                'low',
                'stable',
                'informational',
                'draft',
                'none',
            ] as const
         ).map( ( intent ) => (
            <Fragment key={ intent }>
                <div
                    style={ {
                        paddingInlineEnd: '1rem',
                        display: 'flex',
                        alignItems: 'center',
                    } }
                >
                    { intent }
                </div>
                <div
                    style={ {
                        padding: '0.5rem 1rem',
                        display: 'flex',
                        alignItems: 'center',
                    } }
                >
                    <Badge { ...args } intent={ intent } />
                </div>
            </Fragment>
        ) ) }
    </div>
);

BaseControl

components-basecontrol · ../packages/components/src/base-control/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { BaseControl, Button } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	const { baseControlProps, controlProps } = useBaseControlProps( props );

	return (
		<BaseControl { ...baseControlProps }>
			<textarea style={ { display: 'block' } } { ...controlProps } />
		</BaseControl>
	);
};
With Help Text story ok
const WithHelpText = ( props ) => {
	const { baseControlProps, controlProps } = useBaseControlProps( props );

	return (
		<BaseControl { ...baseControlProps }>
			<textarea style={ { display: 'block' } } { ...controlProps } />
		</BaseControl>
	);
};
With Visual Label story ok
`BaseControl.VisualLabel` is used to render a purely visual label inside a `BaseControl` component. It should only be used in cases where the children being rendered inside `BaseControl` are already accessibly labeled, e.g., a button, but we want an additional visual label for that section equivalent to the labels `BaseControl` would otherwise use if the `label` prop was passed.
const WithVisualLabel = ( props ) => {
	BaseControl.VisualLabel.displayName = 'BaseControl.VisualLabel';

	return (
		<BaseControl { ...props }>
			<BaseControl.VisualLabel>Visual label</BaseControl.VisualLabel>
			<div>
				<Button __next40pxDefaultSize variant="secondary">
					Select an author
				</Button>
			</div>
		</BaseControl>
	);
};

BlockAlignmentMatrixControl

blockeditor-blockalignmentmatrixcontrol · ../packages/block-editor/src/components/block-alignment-matrix-control/stories/index.story.jsx
The alignment matrix control allows users to quickly adjust inner block alignment.
see: https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/block-alignment-matrix-control/README.md example: ```jsx function Example() { return ( <BlockControls> <BlockAlignmentMatrixControl label={ __( 'Change content position' ) } value="center" onChange={ ( nextPosition ) => setAttributes( { contentPosition: nextPosition } ) } /> </BlockControls> ); } ```param: {Object} props Component props.param: {string} props.label Label for the control. Defaults to 'Change matrix alignment'.param: {Function} props.onChange Function to execute upon change of matrix state.param: {string} props.value Content alignment location. One of: 'center', 'center center', 'center left', 'center right', 'top center', 'top left', 'top right', 'bottom center', 'bottom left', 'bottom right'.param: {boolean} props.isDisabled Whether the control should be disabled.return: {Element} The BlockAlignmentMatrixControl component.
Imports
import { BlockAlignmentMatrixControl } from "@wordpress/block-editor";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState();

    return (
        <BlockAlignmentMatrixControl
            value={ value }
            onChange={ ( ...changeArgs ) => {
                onChange( ...changeArgs );
                setValue( ...changeArgs );
            } } />
    );
};

BlockDraggable

blockeditor-blockdraggable · ../packages/block-editor/src/components/block-draggable/stories/index.story.jsx
Prop type error
We could not detect the component from your story file. Specify meta.component.
  4 | import BlockDraggableChip from '../draggable-chip';
  5 |
> 6 | export default { title: 'BlockEditor/BlockDraggable' };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  7 |
  8 | export const _default = () => {
  9 | 	// Create a wrapper box for the absolutely-positioned child component.

../packages/block-editor/src/components/block-draggable/stories/index.story.jsx:
/**
 * Internal dependencies
 */
import BlockDraggableChip from '../draggable-chip';

export default { title: 'BlockEditor/BlockDraggable' };

export const _default = () => {
	// Create a wrapper box for the absolutely-positioned child component.
	const wrapperStyle = { margin: '24px 0', position: 'relative' };
	return (
		<div style={ wrapperStyle }>
			<BlockDraggableChip count={ 2 } />
		</div>
	);
};
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { BlockDraggableChip } from "@wordpress/block-editor";
Default story ok
const _default = () => {
	// Create a wrapper box for the absolutely-positioned child component.
	const wrapperStyle = { margin: '24px 0', position: 'relative' };
	return (
		<div style={ wrapperStyle }>
			<BlockDraggableChip count={ 2 } />
		</div>
	);
};

BlockEditor

playground-block-editor · ./stories/playground/index.story.jsx
Prop type error
We could not detect the component from your story file. Specify meta.component.
   7 | import EditorZoomOut from './zoom-out';
   8 |
>  9 | export default {
     | ^
  10 | 	title: 'Playground/Block Editor',
  11 | 	parameters: {
  12 | 		sourceLink: 'storybook/stories/playground',

./stories/playground/index.story.jsx:
/**
 * Internal dependencies
 */
import EditorFullPage from './fullpage';
import EditorBox from './box';
import EditorWithUndoRedo from './with-undo-redo';
import EditorZoomOut from './zoom-out';

export default {
	title: 'Playground/Block Editor',
	parameters: {
		sourceLink: 'storybook/stories/playground',
	},
};

export const _default = () => {
	return <EditorFullPage />;
};

_default.parameters = {
	sourceLink: 'storybook/stories/playground/fullpage/index.jsx',
};

export const Box = () => {
	return <EditorBox />;
};

Box.parameters = {
	sourceLink: 'storybook/stories/playground/box/index.jsx',
};

export const UndoRedo = () => {
	return <EditorWithUndoRedo />;
};

UndoRedo.parameters = {
	sourceLink: 'storybook/stories/playground/with-undo-redo/index.jsx',
};

export const ZoomOut = ( props ) => {
	return <EditorZoomOut { ...props } />;
};

ZoomOut.parameters = {
	sourceLink: 'storybook/stories/playground/zoom-out/index.jsx',
};
ZoomOut.argTypes = {
	zoomLevel: { control: { type: 'range', min: 10, max: 100, step: 5 } },
};
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { EditorBox, EditorFullPage, EditorWithUndoRedo, EditorZoomOut } from "@wordpress/storybook";
Default story ok
const _default = () => {
	return <EditorFullPage />;
};
Box story ok
const Box = () => {
	return <EditorBox />;
};
Undo Redo story ok
const UndoRedo = () => {
	return <EditorWithUndoRedo />;
};
Zoom Out story ok
const ZoomOut = ( props ) => {
	return <EditorZoomOut { ...props } />;
};

BlockMover

blockeditor-blockmover · ../packages/block-editor/src/components/block-mover/stories/index.story.jsx
BlockMover component allows moving blocks inside the editor using up and down buttons.
Imports
import { BlockMover, ExperimentalBlockEditorProvider } from "@wordpress/block-editor";
import { Toolbar } from "@wordpress/components";
Default story ok
const Default = () => <BlockMover clientIds={[ blocks[ 0 ].innerBlocks[ 1 ].clientId ]} />;
Horizontal story ok
This story shows the block mover with horizontal orientation. It is necessary to render the blocks to update the block settings in the state.
const Horizontal = () => <BlockMover clientIds={[ blocks[ 1 ].innerBlocks[ 1 ].clientId ]} />;
Hide Drag Handle story ok
You can hide the drag handle by `hideDragHandle` attribute.
const HideDragHandle = () => <BlockMover hideDragHandle />;

BlockPatternsList

blockeditor-blockpatternslist · ../packages/block-editor/src/components/block-patterns-list/stories/index.story.jsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 1 prop type
Component: ../packages/block-editor/src/components/block-patterns-list/index.js::default
Props:
label?: any = __( 'Block patterns' )
Imports
import { BlockPatternsList, ExperimentalBlockEditorProvider } from "@wordpress/block-editor";
Default story ok
const Default = function Template( props ) {
    return (
        <ExperimentalBlockEditorProvider settings={ blockEditorSettings }>
            <BlockPatternsList { ...props } />
        </ExperimentalBlockEditorProvider>
    );
};

BlockTitle

blockeditor-blocktitle · ../packages/block-editor/src/components/block-title/stories/index.story.jsx
Prop type error
File: /home/runner/work/gutenberg/gutenberg/packages/block-editor/src/components/block-title/index.js
Error:
No suitable component definition found.
You can debug your component file in this playground: https://react-docgen.dev/playground
Code:
/**
 * Internal dependencies
 */

import useBlockDisplayTitle from './use-block-display-title';

/**
 * Renders the block's configured title as a string, or empty if the title
 * cannot be determined.
 *
 * @example
 *
 * ```jsx
 * <BlockTitle clientId="afd1cb17-2c08-4e7a-91be-007ba7ddc3a1" maximumLength={ 17 }/>
 * ```
 *
 * @param {Object}           props
 * @param {string}           props.clientId      Client ID of block.
 * @param {number|undefined} props.maximumLength The maximum length that the block title string may be before truncated.
 * @param {string|undefined} props.context       The context to pass to `getBlockLabel`.
 *
 * @return {React.JSX.Element} Block title.
 */
export default function BlockTitle( { clientId, maximumLength, context } ) {
	return useBlockDisplayTitle( { clientId, maximumLength, context } );
}
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { BlockTitle, ExperimentalBlockEditorProvider } from "@wordpress/block-editor";
Default story ok
const Default = () => <BlockTitle clientId={blocks[ 0 ].clientId} />;

BorderBoxControl

components-borderboxcontrol · ../packages/components/src/border-box-control/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { BorderBoxControl, Button } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	const { onChange, ...otherProps } = props;
	const [ borders, setBorders ] = useState< ( typeof props )[ 'value' ] >();

	const onChangeMerged: ComponentProps<
		typeof BorderBoxControl
	>[ 'onChange' ] = ( newBorders ) => {
		setBorders( newBorders );
		onChange( newBorders );
	};

	return (
		<>
			<BorderBoxControl
				__next40pxDefaultSize
				{ ...otherProps }
				onChange={ onChangeMerged }
				value={ borders }
			/>
			<hr
				style={ {
					marginTop: '100px',
					borderColor: '#ddd',
					borderStyle: 'solid',
					borderBottom: 'none',
				} }
			/>
			<p style={ { color: '#aaa', fontSize: '0.9em' } }>
				The BorderBoxControl is intended to be used within a component
				that will provide reset controls. The button below is only for
				convenience.
			</p>
			<Button
				__next40pxDefaultSize
				variant="primary"
				onClick={ () => onChangeMerged( undefined ) }
			>
				Reset
			</Button>
		</>
	);
};

BorderControl

components-bordercontrol · ../packages/components/src/border-control/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { BorderControl } from "@wordpress/components";
Default story ok
const Default = ( {
	onChange,
	...props
} ) => {
	const [ border, setBorder ] = useState< Border >();
	const onChangeMerged: ComponentProps<
		typeof BorderControl
	>[ 'onChange' ] = ( newBorder ) => {
		setBorder( newBorder );
		onChange( newBorder );
	};

	return (
		<BorderControl
			__next40pxDefaultSize
			onChange={ onChangeMerged }
			value={ border }
			{ ...props }
		/>
	);
};
With Slider story ok
Render a slider beside the control.
const WithSlider = ( {
	onChange,
	...props
} ) => {
	const [ border, setBorder ] = useState< Border >();
	const onChangeMerged: ComponentProps<
		typeof BorderControl
	>[ 'onChange' ] = ( newBorder ) => {
		setBorder( newBorder );
		onChange( newBorder );
	};

	return (
		<BorderControl
			__next40pxDefaultSize
			onChange={ onChangeMerged }
			value={ border }
			{ ...props }
		/>
	);
};
With Slider (Custom Width) story ok
When rendering with a slider, the `width` prop is useful to customize the width of the number input.
const WithSliderCustomWidth = ( {
	onChange,
	...props
} ) => {
	const [ border, setBorder ] = useState< Border >();
	const onChangeMerged: ComponentProps<
		typeof BorderControl
	>[ 'onChange' ] = ( newBorder ) => {
		setBorder( newBorder );
		onChange( newBorder );
	};

	return (
		<BorderControl
			__next40pxDefaultSize
			onChange={ onChangeMerged }
			value={ border }
			{ ...props }
		/>
	);
};
Is Compact story ok
Restrict the width of the control and prevent it from expanding to take up additional space. When `true`, the `width` prop will be ignored.
const IsCompact = ( {
	onChange,
	...props
} ) => {
	const [ border, setBorder ] = useState< Border >();
	const onChangeMerged: ComponentProps<
		typeof BorderControl
	>[ 'onChange' ] = ( newBorder ) => {
		setBorder( newBorder );
		onChange( newBorder );
	};

	return (
		<BorderControl
			__next40pxDefaultSize
			onChange={ onChangeMerged }
			value={ border }
			{ ...props }
		/>
	);
};
With Multiple Origins story ok
The `colors` object can contain multiple origins.
const WithMultipleOrigins = ( {
	onChange,
	...props
} ) => {
	const [ border, setBorder ] = useState< Border >();
	const onChangeMerged: ComponentProps<
		typeof BorderControl
	>[ 'onChange' ] = ( newBorder ) => {
		setBorder( newBorder );
		onChange( newBorder );
	};

	return (
		<BorderControl
			__next40pxDefaultSize
			onChange={ onChangeMerged }
			value={ border }
			{ ...props }
		/>
	);
};

BorderRadiusControl

blockeditor-borderradiuscontrol · ../packages/block-editor/src/components/border-radius-control/stories/index.story.jsx
Control to display border radius options.
param: {Object} props Component props.param: {Function} props.onChange Callback to handle onChange.param: {Object} props.values Border radius values.param: {Object} props.presets Border radius presets.return: {Element} Custom border radius control.
Imports
import { BorderRadiusControl } from "@wordpress/block-editor";
Default story ok
const Default = () => {
    const [ values, setValues ] = useState( args.values );

    return (
        <BorderRadiusControl
            values={ values }
            onChange={ ( ...changeArgs ) => {
                setValues( ...changeArgs );
                onChange( ...changeArgs );
            } } />
    );
};

BoxControl

components-boxcontrol · ../packages/components/src/box-control/stories/index.story.tsx
A control that lets users set values for top, right, bottom, and left. Can be used as an input control for values like `padding` or `margin`. ```jsx import { useState } from 'react'; import { BoxControl } from '@wordpress/components'; function Example() { const [ values, setValues ] = useState( { top: '50px', left: '10%', right: '10%', bottom: '50px', } ); return ( <BoxControl __next40pxDefaultSize values={ values } onChange={ setValues } /> ); }; ```
Prop types 12 prop types
Component: ../packages/components/src/box-control/index.tsx::default
Props:
/**
 * Start opting into the larger default height that will become the default size in a future version.
 * 
 * @default false
 */
__next40pxDefaultSize?: boolean = false

/**
 * If this property is true, a button to reset the box control is rendered.
 * 
 * @default true
 */
allowReset?: boolean = true

/**
 * The id to use as a base for the unique HTML id attribute of the control.
 */
id?: string

/**
 * Props for the internal `UnitControl` components.
 * 
 * @default { min: 0 }
 */
inputProps?: Omit<
	UnitControlProps,
	'label' | 'onChange' | 'onFocus' | 'units'
> = {
	min: 0,
}

/**
 * Heading label for the control.
 * 
 * @default __( 'Box Control' )
 */
label?: string = __( 'Box Control' )

/**
 * A callback function when an input value changes.
 */
onChange?: ( next: BoxControlValue ) => void = () => {}

/**
 * @deprecated Pass to the `inputProps` prop instead.
 * @ignore
 */
onMouseOut?: UnitControlProps[ 'onMouseOut' ]

/**
 * @deprecated Pass to the `inputProps` prop instead.
 * @ignore
 */
onMouseOver?: UnitControlProps[ 'onMouseOver' ]

/**
 * The `top`, `right`, `bottom`, and `left` box dimension values to use when the control is reset.
 * 
 * @default { top: undefined, right: undefined, bottom: undefined, left: undefined }
 */
resetValues?: {
	top?: string;
	right?: string;
	bottom?: string;
	left?: string;
} = {
	top: undefined,
	right: undefined,
	bottom: undefined,
	left: undefined,
}

/**
 * Collection of sides to allow control of. If omitted or empty, all sides will be available.
 * 
 * Allowed values are "top", "right", "bottom", "left", "vertical", and "horizontal".
 */
sides?: unknown

/**
 * If this property is true, when the box control is unlinked, vertical and horizontal controls
 * can be used instead of updating individual sides.
 * 
 * @default false
 */
splitOnAxis?: boolean = false

/**
 * The current values of the control, expressed as an object of `top`, `right`, `bottom`, and `left` values.
 */
values?: {
	top?: string;
	right?: string;
	bottom?: string;
	left?: string;
}
Imports
import { BoxControl } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	return <BoxControl __next40pxDefaultSize { ...props } />;
};
Controlled story ok
const Controlled = ( props ) => {
	const [ values, setValues ] = useState< ( typeof props )[ 'values' ] >();

	return (
		<BoxControl
			__next40pxDefaultSize
			values={ values }
			{ ...props }
			onChange={ ( nextValue ) => {
				setValues( nextValue );
				props.onChange?.( nextValue );
			} }
		/>
	);
};
Arbitrary Sides story ok
const ArbitrarySides = ( props ) => {
	const [ values, setValues ] = useState< ( typeof props )[ 'values' ] >();

	return (
		<BoxControl
			__next40pxDefaultSize
			values={ values }
			{ ...props }
			onChange={ ( nextValue ) => {
				setValues( nextValue );
				props.onChange?.( nextValue );
			} }
		/>
	);
};
Single Side story ok
const SingleSide = ( props ) => {
	const [ values, setValues ] = useState< ( typeof props )[ 'values' ] >();

	return (
		<BoxControl
			__next40pxDefaultSize
			values={ values }
			{ ...props }
			onChange={ ( nextValue ) => {
				setValues( nextValue );
				props.onChange?.( nextValue );
			} }
		/>
	);
};
Axial Controls story ok
const AxialControls = ( props ) => {
	const [ values, setValues ] = useState< ( typeof props )[ 'values' ] >();

	return (
		<BoxControl
			__next40pxDefaultSize
			values={ values }
			{ ...props }
			onChange={ ( nextValue ) => {
				setValues( nextValue );
				props.onChange?.( nextValue );
			} }
		/>
	);
};
Axial Controls With Single Side story ok
const AxialControlsWithSingleSide = ( props ) => {
	const [ values, setValues ] = useState< ( typeof props )[ 'values' ] >();

	return (
		<BoxControl
			__next40pxDefaultSize
			values={ values }
			{ ...props }
			onChange={ ( nextValue ) => {
				setValues( nextValue );
				props.onChange?.( nextValue );
			} }
		/>
	);
};
Control With Presets story ok
const ControlWithPresets = ( props ) => {
	const [ values, setValues ] = useState< ( typeof props )[ 'values' ] >();

	return (
		<BoxControl
			__next40pxDefaultSize
			values={ values }
			{ ...props }
			onChange={ ( nextValue ) => {
				setValues( nextValue );
				props.onChange?.( nextValue );
			} }
		/>
	);
};

Breadcrumbs

admin-ui-breadcrumbs · ../packages/admin-ui/src/breadcrumbs/stories/index.story.tsx
Renders a breadcrumb navigation trail. All items except the last one must provide a `to` prop for navigation. In development mode, an error is thrown when a non-last item is missing `to`. The last item represents the current page and its `to` prop is optional. Only the last item (when it has no `to` prop) is rendered as an `h1`.
param: props param: props.items The breadcrumb items to display.example: ```jsx <Breadcrumbs items={ [ { label: 'Home', to: '/' }, { label: 'Settings', to: '/settings' }, { label: 'General' }, ] } /> ```
Prop types 2 prop types
Component: ../packages/admin-ui/src/breadcrumbs/index.tsx::Breadcrumbs
Props:
/**
 * An array of items to display in the breadcrumb trail.
 * The last item is considered the current item and has an optional `to` prop.
 * All preceding items must have a `to` prop — in development mode,
 * an error is thrown when this requirement is not met.
 */
items: BreadcrumbItem[]

/**
 * A boolean to show/hide the current item in the trail.
 * Note that when `false` the current item is only visually hidden.
 */
showCurrentItem?: boolean
Imports
import { Breadcrumbs } from "@wordpress/admin-ui";
Single Item story ok
const SingleItem = () => <Breadcrumbs items={[ { label: 'Root breadcrumb' } ]} />;
Two Levels story ok
const TwoLevels = () => <Breadcrumbs
    items={[
        { label: 'Root breadcrumb', to: '/settings' },
        { label: 'Level 1 breadcrumb' },
    ]} />;
Three Levels story ok
const ThreeLevels = () => <Breadcrumbs
    items={[
        { label: 'Root breadcrumb', to: '/settings' },
        { label: 'Level 1 breadcrumb', to: '/settings/connectors' },
        { label: 'Level 2 breadcrumb' },
    ]} />;

Button

components-button · ../packages/components/src/button/stories/index.story.tsx
Lets users take actions and make choices with a single click or tap. ```jsx import { Button } from '@wordpress/components'; const Mybutton = () => ( <Button variant="primary" onClick={ handleClick } > Click here </Button> ); ```
Prop types 8 prop types
Component: ../packages/components/src/button/index.tsx::Button
Props:
/**
 * Whether to keep the button focusable when disabled.
 * 
 * @default false
 * @deprecated Use the `accessibleWhenDisabled` prop instead.
 * @ignore
 */
__experimentalIsFocusable?: boolean

/**
 * A visually hidden accessible description for the button.
 * 
 * @deprecated Use the `description` prop instead.
 * @ignore
 */
describedBy?: string

/**
 * Gives the button a default style.
 * 
 * @deprecated Use the `'secondary'` value on the `variant` prop instead.
 * @ignore
 */
isDefault?: boolean

/**
 * Gives the button a link style.
 * 
 * @deprecated Use the `'link'` value on the `variant` prop instead.
 * @ignore
 */
isLink?: boolean

/**
 * Gives the button a primary style.
 * 
 * @deprecated Use the `'primary'` value on the `variant` prop instead.
 * @ignore
 */
isPrimary?: boolean

/**
 * Gives the button a default style.
 * 
 * @deprecated Use the `'secondary'` value on the `variant` prop instead.
 * @ignore
 */
isSecondary?: boolean

/**
 * Decreases the size of the button.
 * 
 * @deprecated Use the `'small'` value on the `size` prop instead.
 * @ignore
 */
isSmall?: boolean

/**
 * Gives the button a text-based style.
 * 
 * @deprecated Use the `'tertiary'` value on the `variant` prop instead.
 * @ignore
 */
isTertiary?: boolean
Imports
import { Button } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	return <Button __next40pxDefaultSize { ...props }></Button>;
};
Primary story ok
Primary buttons stand out with bold color fills, making them distinct from the background. Since they naturally draw attention, each layout should contain only one primary button to guide users toward the most important action.
const Primary = ( props ) => {
	return <Button __next40pxDefaultSize { ...props }></Button>;
};
Secondary story ok
Secondary buttons complement primary buttons. Use them for standard actions that may appear alongside a primary action.
const Secondary = ( props ) => {
	return <Button __next40pxDefaultSize { ...props }></Button>;
};
Tertiary story ok
Tertiary buttons have minimal emphasis. Use them sparingly to subtly highlight an action.
const Tertiary = ( props ) => {
	return <Button __next40pxDefaultSize { ...props }></Button>;
};
Link story ok
Link buttons have low emphasis and blend into the page, making them suitable for supplementary actions, especially those involving navigation away from the current view.
const Link = ( props ) => {
	return <Button __next40pxDefaultSize { ...props }></Button>;
};
Is Destructive story ok
Use this variant for irreversible actions. Apply sparingly and only for actions with significant impact.
const IsDestructive = ( props ) => {
	return <Button __next40pxDefaultSize { ...props }></Button>;
};
Icon story ok
const Icon = ( props ) => {
	return <Button __next40pxDefaultSize { ...props }></Button>;
};
Grouped Icons story ok
function GroupedIcons() {
	return (
		<GroupContainer>
			<Button __next40pxDefaultSize icon={ formatBold } label="Bold" />
			<Button
				__next40pxDefaultSize
				icon={ formatItalic }
				label="Italic"
			/>
			<Button __next40pxDefaultSize icon={ link } label="Link" />
		</GroupContainer>
	);
}

Button

design-system-components-button · ../packages/ui/src/button/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 9 prop types
Component: ../packages/ui/src/button/button.tsx::Button
Props:
/**
 * Indicates the current "pressed" state of toggle buttons. This should only
 * be used with neutral minimal buttons.
 */
aria-pressed?: HTMLAttributes< HTMLButtonElement >[ 'aria-pressed' ]

/**
 * The content of the button.
 */
children?: ReactNode

/**
 * Whether the button is disabled.
 */
disabled?: boolean

/**
 * Whether the element should be focusable even when it is disabled.
 * 
 * @default true
 */
focusableWhenDisabled?: _ButtonProps[ 'focusableWhenDisabled' ] = true

/**
 * Whether the button is in a loading state, such as when an action is being
 * performed.
 * @default false
 */
loading?: boolean

/**
 * The text used for assistive technology to indicate the loading state.
 */
loadingAnnouncement?: string = __( 'Loading' )

/**
 * The size of the button.
 * 
 * - `'default'`: For normal text-label buttons, unless it is a toggle button.
 * - `'compact'`: For toggle buttons, icon buttons, and buttons when used in context of either.
 * - `'small'`: For icon buttons associated with more advanced or auxiliary features.
 * 
 * @default "default"
 */
size?: 'default' | 'compact' | 'small' = 'default'

/**
 * The tone of the button, describing a semantic color intent:
 * 
 * - `'brand': for the most prominent actions, using the brand colors.
 * - `'neutral'` for less prominent actions.
 * 
 * @default "brand"
 */
tone?: 'brand' | 'neutral' = 'brand'

/**
 * The variant of the button. Variants describe the visual style treatment
 * of the button.
 * 
 * @default "solid"
 */
variant?: 'solid' | 'outline' | 'minimal' | 'unstyled' = 'solid'
Imports
import { Button } from "@wordpress/ui";
import { Fragment } from "@wordpress/element";
Default story ok
const Default = () => <Button>Button</Button>;
Outline story ok
const Outline = () => <Button variant="outline" />;
Minimal story ok
const Minimal = () => <Button variant="minimal" />;
Compact story ok
const Compact = () => <Button size="compact" />;
Small story ok
const Small = () => <Button size="small" />;
Neutral story ok
const Neutral = () => <Button tone="neutral" />;
Neutral Outline story ok
const NeutralOutline = () => <Button tone="neutral" variant="outline" />;
Unstyled story ok
const Unstyled = () => <Button variant="unstyled" />;
All Tones And Variants story ok
const AllTonesAndVariants = ( args ) => (
    <div
        style={ {
            display: 'grid',
            gridTemplateColumns: 'max-content repeat(2, min-content)',
            color: 'var(--wpds-color-fg-content-neutral)',
        } }
    >
        <div></div>
        <div style={ { textAlign: 'center' } }>Resting</div>
        <div style={ { textAlign: 'center' } }>Disabled</div>
        { ( [ 'brand', 'neutral' ] as const ).map( ( tone ) => (
            <Fragment key={ tone }>
                { (
                    [ 'solid', 'outline', 'minimal', 'unstyled' ] as const
                 ).map( ( variant ) => (
                    <Fragment key={ variant }>
                        <div
                            style={ {
                                paddingInlineEnd: '1rem',
                                display: 'flex',
                                alignItems: 'center',
                            } }
                        >
                            { variant }, { tone }
                        </div>
                        <div
                            style={ {
                                padding: '0.5rem 1rem',
                                display: 'flex',
                                alignItems: 'center',
                            } }
                        >
                            <Button
                                { ...args }
                                tone={ tone }
                                variant={ variant }
                            />
                        </div>
                        <div
                            style={ {
                                padding: '0.5rem 1rem',
                                display: 'flex',
                                alignItems: 'center',
                            } }
                        >
                            <Button
                                { ...args }
                                tone={ tone }
                                variant={ variant }
                                disabled
                            />
                        </div>
                    </Fragment>
                ) ) }
            </Fragment>
        ) ) }
    </div>
);
With Icon story ok
const WithIcon = () => <Button>(<>
        <Button.Icon icon={ cog } />Button
                    </>)</Button>;
Loading story ok
const Loading = () => <Button loading loadingAnnouncement="Saving data" />;
Pressed story ok
The pressed state is only available for buttons with `tone="neutral"` and `variant="minimal"` and can be toggled via the `aria-pressed` HTML attribute.
const Pressed = () => <Button tone="neutral" variant="minimal" aria-pressed />;

ButtonGroup

components-buttongroup · ../packages/components/src/button-group/stories/index.story.tsx
ButtonGroup can be used to group any related buttons together. To emphasize related buttons, a group should share a common container. This component is deprecated. Use `ToggleGroupControl` instead.
Imports
import { Button, ButtonGroup } from "@wordpress/components";
Default story ok
const Default = () => <ButtonGroup>(<>
        <Button __next40pxDefaultSize variant="primary">
            Button 1
        </Button>
        <Button __next40pxDefaultSize>Button 2</Button>
    </>)</ButtonGroup>;

Card

components-card · ../packages/components/src/card/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import {
    Button,
    Card,
    CardBody,
    CardDivider,
    CardFooter,
    CardHeader,
    CardMedia,
    Heading,
    Text,
} from "@wordpress/components";
Default story ok
const Default = () => <Card>(<>
        <CardHeader>
            <Heading>CardHeader</Heading>
        </CardHeader>
        <CardBody>
            <Text>CardBody</Text>
        </CardBody>
        <CardBody>
            <Text>CardBody (before CardDivider)</Text>
        </CardBody>
        <CardDivider />
        <CardBody>
            <Text>CardBody (after CardDivider)</Text>
        </CardBody>
        <CardMedia>
            <img
                alt="Card Media"
                src="https://images.unsplash.com/photo-1566125882500-87e10f726cdc?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1867&q=80"
            />
        </CardMedia>
        <CardFooter>
            <Text>CardFooter</Text>
            <Button __next40pxDefaultSize variant="secondary">
                Action Button
            </Button>
        </CardFooter>
    </>)</Card>;
Full Bleed Content story ok
`CardMedia` provides a container for full-bleed content within a `Card`, such as images, video, or even just a background color. The corners will be rounded if necessary.
const FullBleedContent = () => <Card>(<CardMedia>
        <div style={ { padding: 16, background: 'beige' } }>
            Some full bleed content
        </div>
    </CardMedia>)</Card>;
Padding Variations story ok
The Card component supports three approaches to padding: 1. Default padding (medium) - no size prop needed 2. Token-based padding - using size tokens: xSmall, small, medium, large 3. Logical padding - customize each direction using logical properties Each component (Card, CardHeader, CardBody) can have its own padding configuration.
const PaddingVariations = () => (
    <div
        style={ { display: 'flex', flexDirection: 'column', gap: '32px' } }
    >
        { /* 1. Default Padding */ }
        <div>
            <Card>
                <CardHeader>
                    <Text>Header with default padding</Text>
                </CardHeader>
                <CardBody>
                    <Text>Body with default padding (medium)</Text>
                </CardBody>
            </Card>
        </div>

        <div>
            <Card>
                <CardHeader
                    size={ {
                        blockStart: 'large',
                        blockEnd: 'small',
                        inlineStart: 'xSmall',
                        inlineEnd: 'large',
                    } }
                >
                    <Text>
                        Header with logical padding (large blockStart, small
                        blockEnd, xSmall inlineStart, large inlineEnd)
                    </Text>
                </CardHeader>
                <CardBody
                    size={ {
                        blockStart: 'medium',
                        blockEnd: 'xSmall',
                        inlineStart: 'large',
                        inlineEnd: 'xSmall',
                    } }
                >
                    <Text>
                        Body with logical padding (medium blockStart, xSmall
                        blockEnd, large inlineStart, xSmall inlineEnd)
                    </Text>
                </CardBody>
            </Card>
        </div>
    </div>
);

Card.Root

design-system-components-card · ../packages/ui/src/card/stories/index.story.tsx
A visually contained surface that groups related content and actions. ```jsx import { Card } from '@wordpress/ui'; function MyComponent() { return ( <Card.Root> <Card.Header> <Card.Title>Heading</Card.Title> </Card.Header> <Card.Content> <p>Main content here.</p> </Card.Content> </Card.Root> ); } ```
Prop types 3 prop types
Component: ../packages/ui/src/card/root.tsx::Root
Props:
/**
 * The content to be rendered inside the card.
 */
children?: ReactNode

/**
 * CSS class name to apply to the component.
 */
className?: string

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: | ComponentRenderFn< HTMLAttributesWithRef >
| React.ReactElement< Record< string, unknown > >
Imports
import { Content, FullBleed, Header, Root, Title } from "@wordpress/ui";
Default story ok
const Default = () => <Card.Root>(<>
        <Card.Header>
            <Card.Title>Card title</Card.Title>
        </Card.Header>
        <Card.Content>
            <Text>
                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.
            </Text>
            <Text>
                This is the main content area. It can contain any
                elements.
            </Text>
        </Card.Content>
    </>)</Card.Root>;
With Full Bleed story ok
`Card.FullBleed` breaks out of the card's padding to span edge-to-edge. Useful for images, dividers, or embedded content.
const WithFullBleed = () => <Card.Root>(<>
        <Card.Header>
            <Card.Title>Featured image</Card.Title>
        </Card.Header>
        <Card.Content>
            <Card.FullBleed>
                <div
                    style={ {
                        height: 160,
                        background:
                            'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
                    } }
                />
            </Card.FullBleed>
            <Text>Content below the full-bleed area.</Text>
        </Card.Content>
    </>)</Card.Root>;
Header Only story ok
A minimal card with only a header.
const HeaderOnly = () => <Card.Root>(<Card.Header>
        <Card.Title>Simple card</Card.Title>
    </Card.Header>)</Card.Root>;
Custom Semantics story ok
Use the `render` prop to change the underlying HTML elements for better semantics. Here, `Card.Root` renders as a `<section>` and `Card.Title` renders as an `<h2>`.
const CustomSemantics = () => <Card.Root render={<section />}>(<>
        <Card.Header>
            <Card.Title render={ <h2 /> }>Section heading</Card.Title>
        </Card.Header>
        <Card.Content>
            <Text>Semantically meaningful card content.</Text>
        </Card.Content>
    </>)</Card.Root>;

CheckboxControl

components-checkboxcontrol · ../packages/components/src/checkbox-control/stories/index.story.tsx
Checkboxes allow the user to select one or more items from a set. ```jsx import { CheckboxControl } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyCheckboxControl = () => { const [ isChecked, setChecked ] = useState( true ); return ( <CheckboxControl label="Is author" help="Is the user a author or not?" checked={ isChecked } onChange={ setChecked } /> ); }; ```
Imports
import { CheckboxControl, HStack, VStack } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ isChecked, setChecked ] = useState( true );

    return (
        <CheckboxControl
            label="Is author"
            help="Is the user an author or not?"
            checked={ isChecked }
            onChange={ ( v ) => {
				setChecked( v );
				onChange( v );
			} } />
    );
};
Indeterminate story ok
const Indeterminate = () => {
    const [ fruits, setFruits ] = useState( { apple: false, orange: false } );

    const isAllChecked = Object.values( fruits ).every( Boolean );
    const isIndeterminate =
		Object.values( fruits ).some( Boolean ) && ! isAllChecked;

    return (
        <VStack>
            <CheckboxControl
                label="Select all"
                checked={ isAllChecked }
                indeterminate={ isIndeterminate }
                onChange={ ( v ) => {
					setFruits( {
						apple: v,
						orange: v,
					} );
					onChange( v );
				} } />
            <CheckboxControl
                label="Apple"
                checked={ fruits.apple }
                onChange={ ( apple ) =>
					setFruits( ( prevState ) => ( {
						...prevState,
						apple,
					} ) )
				} />
            <CheckboxControl
                label="Orange"
                checked={ fruits.orange }
                onChange={ ( orange ) =>
					setFruits( ( prevState ) => ( {
						...prevState,
						orange,
					} ) )
				} />
        </VStack>
    );
};
With Custom Label story ok
For more complex designs, a custom `<label>` element can be associated with the checkbox by leaving the `label` prop undefined and using the `id` and `htmlFor` props instead. Because the label element also functions as a click target for the checkbox, [do not place interactive elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label#interactive_content) such as links or buttons inside the `<label>` node. Similarly, a custom description can be added by omitting the `help` prop and using the `aria-describedby` prop instead.
const WithCustomLabel = () => {
    const [ isChecked, setChecked ] = useState( true );

    return (
        <HStack justify="flex-start" alignment="top" spacing={ 0 }>
            <CheckboxControl
                checked={ isChecked }
                onChange={ ( v ) => {
					setChecked( v );
					onChange( v );
				} }
                // Disable reason: For simplicity of the code snippet.
                // eslint-disable-next-line no-restricted-syntax
                id="my-checkbox-with-custom-label"
                aria-describedby="my-custom-description" />
            <VStack>
                <label htmlFor="my-checkbox-with-custom-label">My custom label
                                    </label>
                { /* eslint-disable-next-line no-restricted-syntax */ }
                <div id="my-custom-description" style={ { fontSize: 13 } }>A custom description.
                                    </div>
            </VStack>
        </HStack>
    );
};

CircularOptionPicker

components-circularoptionpicker · ../packages/components/src/circular-option-picker/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { CircularOptionPicker } from "@wordpress/components";
Default story ok
const Default = ( props ) => (
	<CircularOptionPicker { ...props } />
);
As Buttons story ok
const AsButtons = ( props ) => (
	<CircularOptionPicker { ...props } />
);
With Looping Disabled story ok
const WithLoopingDisabled = ( props ) => (
	<CircularOptionPicker { ...props } />
);
With ButtonAction story ok
const WithButtonAction = ( props ) => (
	<CircularOptionPicker { ...props } />
);
With DropdownLinkAction story ok
const WithDropdownLinkAction = ( props ) => (
	<CircularOptionPicker { ...props } />
);

Collapsible.Root

design-system-components-collapsible · ../packages/ui/src/collapsible/stories/index.story.tsx
Groups all parts of the collapsible. `Collapsible` is a collection of React components that combine to render a collapsible panel controlled by a button.
Prop types 3 prop types
Component: ../packages/ui/src/collapsible/root.tsx::Root
Props:
/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

/**
 * CSS class name to apply to the component.
 */
className?: string

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: | ComponentRenderFn< HTMLAttributesWithRef >
| React.ReactElement< Record< string, unknown > >
Imports
import { Panel, Root, Trigger } from "@wordpress/ui";
Default story ok
const Default = () => <Collapsible.Root>(<>
        <Collapsible.Trigger>Toggle</Collapsible.Trigger>
        <Collapsible.Panel>
            <p>Collapsible content here.</p>
        </Collapsible.Panel>
    </>)</Collapsible.Root>;
Default Open story ok
const DefaultOpen = () => <Collapsible.Root defaultOpen>(<>
        <Collapsible.Trigger>Toggle</Collapsible.Trigger>
        <Collapsible.Panel>
            <p>This panel is open by default.</p>
        </Collapsible.Panel>
    </>)</Collapsible.Root>;
Disabled story ok
const Disabled = () => <Collapsible.Root disabled>(<>
        <Collapsible.Trigger>Toggle (disabled)</Collapsible.Trigger>
        <Collapsible.Panel>
            <p>This content cannot be toggled.</p>
        </Collapsible.Panel>
    </>)</Collapsible.Root>;
Hidden Until Found story ok
When `hiddenUntilFound` is set on `Collapsible.Panel`, the collapsed content remains in the DOM using the `hidden="until-found"` HTML attribute instead of being removed entirely. This lets the browser's native page search (Ctrl/Cmd+F) find text inside collapsed panels and automatically expand them to reveal the match — improving discoverability without sacrificing the collapsed layout.
const HiddenUntilFound = function HiddenUntilFound() {
    return (
        <div>
            <p>
                Use the browser&apos;s find-in-page (Ctrl/Cmd+F) to search
                for &quot;hidden treasure&quot;. The collapsed panel will
                automatically expand to reveal the match.
            </p>
            <Collapsible.Root>
                <Collapsible.Trigger>Expand to reveal</Collapsible.Trigger>
                <Collapsible.Panel hiddenUntilFound>
                    <p>
                        This is the hidden treasure that can be found via
                        the browser&apos;s built-in page search even while
                        the panel is collapsed.
                    </p>
                </Collapsible.Panel>
            </Collapsible.Root>
        </div>
    );
};
Controlled story ok
const Controlled = function Controlled() {
    const [ open, setOpen ] = useState( false );
    return (
        <Collapsible.Root open={ open } onOpenChange={ setOpen }>
            <Collapsible.Trigger>
                { open ? 'Close' : 'Open' }
            </Collapsible.Trigger>
            <Collapsible.Panel>
                <p>Controlled collapsible panel.</p>
            </Collapsible.Panel>
        </Collapsible.Root>
    );
};

CollapsibleCard.Root

design-system-components-collapsiblecard · ../packages/ui/src/collapsible-card/stories/index.story.tsx
A card that can be expanded and collapsed. When collapsed, only the header is visible. ```jsx import { CollapsibleCard, Card } from '@wordpress/ui'; function MyComponent() { return ( <CollapsibleCard.Root defaultOpen> <CollapsibleCard.Header> <Card.Title>Heading</Card.Title> </CollapsibleCard.Header> <CollapsibleCard.Content> <p>Collapsible content here.</p> </CollapsibleCard.Content> </CollapsibleCard.Root> ); } ```
Prop types 7 prop types
Component: ../packages/ui/src/collapsible-card/root.tsx::Root
Props:
/**
 * The content to be rendered inside the collapsible card.
 * Should include `CollapsibleCard.Header` and `CollapsibleCard.Content`.
 */
children?: ReactNode

/**
 * CSS class name to apply to the component.
 */
className?: string

/**
 * Whether the collapsible panel is initially open (uncontrolled).
 * @default false
 */
defaultOpen?: boolean

/**
 * Whether the component should ignore user interaction.
 * @default false
 */
disabled?: boolean

/**
 * Event handler called when the panel is opened or closed.
 */
onOpenChange?: ( open: boolean ) => void

/**
 * Whether the collapsible panel is currently open (controlled).
 * 
 * To render an uncontrolled collapsible card, use `defaultOpen` instead.
 */
open?: boolean

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: | ComponentRenderFn< HTMLAttributesWithRef >
| React.ReactElement< Record< string, unknown > >
Imports
import { Content, Header, Root, Title, HeaderDescription, Stack } from "@wordpress/ui";
Default story ok
A collapsible card that is open by default.
const Default = () => <CollapsibleCard.Root>(<>
        <CollapsibleCard.Header>
            <Card.Title>
                Collapsible card (closed by default)
            </Card.Title>
        </CollapsibleCard.Header>
        <CollapsibleCard.Content>
            <Text>
                This is the collapsible content area. It can contain any
                elements, just like a regular Card.Content.
            </Text>
            <Text>
                When collapsed, only the header and chevron are visible.
            </Text>
        </CollapsibleCard.Content>
    </>)</CollapsibleCard.Root>;
Initially Opened story ok
A collapsible card that starts collapsed.
const InitiallyOpened = () => <CollapsibleCard.Root defaultOpen>(<>
        <CollapsibleCard.Header>
            <Card.Title>Collapsed by default</Card.Title>
        </CollapsibleCard.Header>
        <CollapsibleCard.Content>
            <Text>This content was hidden until you expanded it.</Text>
        </CollapsibleCard.Content>
    </>)</CollapsibleCard.Root>;
Disabled story ok
A disabled collapsible card cannot be toggled by the user.
const Disabled = () => <CollapsibleCard.Root disabled>(<>
        <CollapsibleCard.Header>
            <Card.Title>Disabled card</Card.Title>
        </CollapsibleCard.Header>
        <CollapsibleCard.Content>
            <Text>The header is not interactive when disabled.</Text>
        </CollapsibleCard.Content>
    </>)</CollapsibleCard.Root>;
Stacked story ok
Multiple collapsible cards stacked vertically, simulating a typical settings-panel or FAQ-style layout.
const Stacked = () => (
    <div
        style={ {
            display: 'flex',
            flexDirection: 'column',
            gap: 'var(--wpds-dimension-gap-lg)',
        } }
    >
        { [
            'General',
            'Advanced',
            'Accessibility',
            'Performance',
            'Privacy',
            'Notifications',
        ].map( ( title ) => (
            <CollapsibleCard.Root key={ title }>
                <CollapsibleCard.Header>
                    <Card.Title>{ title }</Card.Title>
                </CollapsibleCard.Header>
                <CollapsibleCard.Content>
                    <Text>
                        Configure all { title.toLowerCase() } settings for
                        your site. Changes here affect how your site behaves
                        across all pages and posts.
                    </Text>
                    <Text>
                        Review each option carefully before saving. Some
                        changes may require a page reload to take effect.
                        Hover over individual options for more details about
                        what they control.
                    </Text>
                    <Text>
                        If you&apos;re unsure about a setting, you can
                        always reset to defaults using the button at the
                        bottom of this section. Your previous configuration
                        will be saved as a backup.
                    </Text>
                </CollapsibleCard.Content>
            </CollapsibleCard.Root>
        ) ) }
    </div>
);
With Header Description story ok
A collapsible card with a `HeaderDescription` that provides supplementary information (e.g. status, summary) as an `aria-describedby` relationship.
const WithHeaderDescription = ( { open, defaultOpen, onOpenChange, disabled, ...restArgs } ) => (
    <CollapsibleCard.Root
        open={ open }
        defaultOpen={ defaultOpen }
        onOpenChange={ onOpenChange }
        disabled={ disabled }
        { ...restArgs }
    >
        <CollapsibleCard.Header>
            <Stack justify="space-between">
                <Card.Title>Settings</Card.Title>
                <CollapsibleCard.HeaderDescription>
                    <span
                        style={ {
                            fontSize: 'var(--wpds-font-size-sm)',
                            color: 'var(--wpds-color-fg-content-neutral-weak)',
                        } }
                    >
                        3 items configured
                    </span>
                </CollapsibleCard.HeaderDescription>
            </Stack>
        </CollapsibleCard.Header>
        <CollapsibleCard.Content>
            <Text>
                The header description provides supplementary context to the
                trigger button. Assistive technologies will announce the
                description alongside the button label.
            </Text>
        </CollapsibleCard.Content>
    </CollapsibleCard.Root>
);
Compared To Card story ok
Visual comparison: a `CollapsibleCard` (open) next to a regular `Card` to verify identical spacing and layout.
const ComparedToCard = ( { open, defaultOpen, onOpenChange, disabled, ...restArgs } ) => (
    <div
        style={ {
            display: 'flex',
            flexDirection: 'column',
            gap: 'var( --wpds-dimension-gap-lg )',
        } }
    >
        <CollapsibleCard.Root
            open={ open }
            defaultOpen={ defaultOpen }
            onOpenChange={ onOpenChange }
            disabled={ disabled }
            { ...restArgs }
        >
            <CollapsibleCard.Header>
                <Card.Title>CollapsibleCard (open)</Card.Title>
            </CollapsibleCard.Header>
            <CollapsibleCard.Content>
                <Text>
                    Content should align with the regular card below.
                </Text>
            </CollapsibleCard.Content>
        </CollapsibleCard.Root>
        <Card.Root { ...restArgs }>
            <Card.Header>
                <Card.Title>Regular Card</Card.Title>
            </Card.Header>
            <Card.Content>
                <Text>
                    Content should align with the collapsible card above.
                </Text>
            </Card.Content>
        </Card.Root>
    </div>
);

ColorGen

design-system-theme-theme-provider-color-scales · ../packages/theme/src/color-ramps/stories/index.story.tsx
Prop type error
No component file found for the "ColorGen" component.
  19 | };
  20 |
> 21 | const meta: Meta< typeof ColorGen > = {
     | ^
  22 | 	title: 'Design System/Theme/Theme Provider/Color Scales',
  23 | 	component: ColorGen,
  24 | 	argTypes: {

../packages/theme/src/color-ramps/stories/index.story.tsx:
/**
 * External dependencies
 */
import type { Meta, StoryObj } from '@storybook/react-vite';

/**
 * Internal dependencies
 */
import { RampTable } from './ramp-table';
import { buildBgRamp, buildAccentRamp, checkAccessibleCombinations } from '..';
import { DEFAULT_SEED_COLORS } from '../lib/constants';

const ColorGen = ( props: {
	background: string;
	primary: string;
	children: React.ReactNode;
} ) => {
	return <div>{ props.children }</div>;
};

const meta: Meta< typeof ColorGen > = {
	title: 'Design System/Theme/Theme Provider/Color Scales',
	component: ColorGen,
	argTypes: {
		background: {
			control: { type: 'color', presetColors: [ '#1e1e1e', '#f8f8f8' ] },
		},
		primary: {
			control: {
				type: 'color',
				presetColors: [ '#3858e9', '#069e08', '#873eff' ],
			},
		},
	},
	parameters: {
		controls: { expanded: true },
		docs: { canvas: { sourceState: 'shown' } },
	},
};
export default meta;

export const Default: StoryObj< typeof ColorGen > = {
	render: ( args ) => {
		const bgSeed = args.background ?? DEFAULT_SEED_COLORS.bg;
		const primarySeed = args.primary ?? DEFAULT_SEED_COLORS.primary;
		const bgRamp = buildBgRamp( bgSeed );

		const bgRampObj = {
			seed: {
				name: 'surface2' as const,
				value: bgSeed,
			},
			ramp: bgRamp.ramp,
		};

		const primaryRampObj = {
			seed: {
				name: 'bgFill1' as const,
				value: primarySeed,
			},
			ramp: buildAccentRamp( primarySeed, bgRamp ).ramp,
		};
		const infoRampObj = {
			seed: {
				name: 'bgFill1' as const,
				value: DEFAULT_SEED_COLORS.info,
			},
			ramp: buildAccentRamp( DEFAULT_SEED_COLORS.info, bgRamp ).ramp,
		};
		const successRampObj = {
			seed: {
				name: 'bgFill1' as const,
				value: DEFAULT_SEED_COLORS.success,
			},
			ramp: buildAccentRamp( DEFAULT_SEED_COLORS.success, bgRamp ).ramp,
		};
		const warningRampObj = {
			seed: {
				name: 'bgFill1' as const,
				value: DEFAULT_SEED_COLORS.warning,
			},
			ramp: buildAccentRamp( DEFAULT_SEED_COLORS.warning, bgRamp ).ramp,
		};
		const cautionRampObj = {
			seed: {
				name: 'bgFill1' as const,
				value: DEFAULT_SEED_COLORS.caution,
			},
			ramp: buildAccentRamp( DEFAULT_SEED_COLORS.caution, bgRamp ).ramp,
		};
		const errorRampObj = {
			seed: {
				name: 'bgFill1' as const,
				value: DEFAULT_SEED_COLORS.error,
			},
			ramp: buildAccentRamp( DEFAULT_SEED_COLORS.error, bgRamp ).ramp,
		};

		const unmetTargets = checkAccessibleCombinations( {
			bgRamp,
		} );

		return (
			<div
				style={ {
					display: 'flex',
					flexDirection: 'column',
					gap: '32px',
				} }
			>
				<RampTable
					ramps={ [
						bgRampObj,
						primaryRampObj,
						infoRampObj,
						successRampObj,
						warningRampObj,
						cautionRampObj,
						errorRampObj,
					] }
				/>

				{ unmetTargets.length === 0 ? (
					<p>All accessibility targets met</p>
				) : (
					<ul>
						{ unmetTargets.map(
							(
								{
									bgName,
									bgColor,
									fgName,
									fgColor,
									unmetContrast,
									achievedContrast,
								},
								i
							) => (
								<li key={ i }>
									{ fgName } (
									<span
										style={ {
											width: 20,
											height: 20,
											backgroundColor: fgColor,
											display: 'inline-block',
										} }
									/>
									{ fgColor }) over { bgName } (
									<span
										style={ {
											width: 20,
											height: 20,
											backgroundColor: bgColor,
											display: 'inline-block',
										} }
									/>
									{ bgColor }) did not meet { unmetContrast },
									achieved just { achievedContrast }
								</li>
							)
						) }
					</ul>
				) }
			</div>
		);
	},
	args: {},
};

export const SampleCombinations: StoryObj< typeof ColorGen > = {
	render: () => {
		const combinations = [
			// WordPress (light / dark)
			{
				background: '#f8f8f8',
				primary: '#3858e9',
			},
			{
				background: '#1e1e1e',
				primary: '#3858e9',
			},
			// WP Classic
			{
				background: '#1d2327',
				primary: '#2271b1',
			},
			// WP Light
			{
				background: '#e5e5e5',
				primary: '#d64e07',
			},
			// WP Blue
			{
				background: '#096484',
				primary: '#52accc',
			},
			// WP Coffee
			{
				background: '#46403c',
				primary: '#c7a589',
			},
			// WP Ectoplasm
			{
				background: '#413256',
				primary: '#a3b745',
			},
			// WP Ocean
			{
				background: '#627c83',
				primary: '#9ebaa0',
			},
			// Sunrise
			{
				background: '#b43c38',
				primary: '#dd823b',
			},
		];

		const ramps = combinations.map( ( { background, primary } ) => {
			const bgRamp = buildBgRamp( background );

			const bgRampObj = {
				seed: {
					name: 'surface2' as const,
					value: background,
				},
				ramp: bgRamp.ramp,
				warnings: bgRamp.warnings,
			};

			const primaryRamp = buildAccentRamp( primary, bgRamp );
			const primaryRampObj = {
				seed: {
					name: 'bgFill1' as const,
					value: primary,
				},
				ramp: primaryRamp.ramp,
				warnings: primaryRamp.warnings,
			};

			return [ bgRampObj, primaryRampObj ];
		} );

		return (
			<div
				style={ { display: 'flex', flexDirection: 'column', gap: 16 } }
			>
				{ ramps.map( ( r, i ) => (
					<RampTable key={ i } ramps={ r } />
				) ) }
			</div>
		);
	},
	argTypes: {
		background: {
			control: false,
		},
		primary: {
			control: false,
		},
	},
};
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { RampTable } from "@wordpress/theme";
Default story ok
const Default = ( args ) => {
    const bgSeed = args.background ?? DEFAULT_SEED_COLORS.bg;
    const primarySeed = args.primary ?? DEFAULT_SEED_COLORS.primary;
    const bgRamp = buildBgRamp( bgSeed );

    const bgRampObj = {
        seed: {
            name: 'surface2' as const,
            value: bgSeed,
        },
        ramp: bgRamp.ramp,
    };

    const primaryRampObj = {
        seed: {
            name: 'bgFill1' as const,
            value: primarySeed,
        },
        ramp: buildAccentRamp( primarySeed, bgRamp ).ramp,
    };
    const infoRampObj = {
        seed: {
            name: 'bgFill1' as const,
            value: DEFAULT_SEED_COLORS.info,
        },
        ramp: buildAccentRamp( DEFAULT_SEED_COLORS.info, bgRamp ).ramp,
    };
    const successRampObj = {
        seed: {
            name: 'bgFill1' as const,
            value: DEFAULT_SEED_COLORS.success,
        },
        ramp: buildAccentRamp( DEFAULT_SEED_COLORS.success, bgRamp ).ramp,
    };
    const warningRampObj = {
        seed: {
            name: 'bgFill1' as const,
            value: DEFAULT_SEED_COLORS.warning,
        },
        ramp: buildAccentRamp( DEFAULT_SEED_COLORS.warning, bgRamp ).ramp,
    };
    const cautionRampObj = {
        seed: {
            name: 'bgFill1' as const,
            value: DEFAULT_SEED_COLORS.caution,
        },
        ramp: buildAccentRamp( DEFAULT_SEED_COLORS.caution, bgRamp ).ramp,
    };
    const errorRampObj = {
        seed: {
            name: 'bgFill1' as const,
            value: DEFAULT_SEED_COLORS.error,
        },
        ramp: buildAccentRamp( DEFAULT_SEED_COLORS.error, bgRamp ).ramp,
    };

    const unmetTargets = checkAccessibleCombinations( {
        bgRamp,
    } );

    return (
        <div
            style={ {
                display: 'flex',
                flexDirection: 'column',
                gap: '32px',
            } }
        >
            <RampTable
                ramps={ [
                    bgRampObj,
                    primaryRampObj,
                    infoRampObj,
                    successRampObj,
                    warningRampObj,
                    cautionRampObj,
                    errorRampObj,
                ] }
            />

            { unmetTargets.length === 0 ? (
                <p>All accessibility targets met</p>
            ) : (
                <ul>
                    { unmetTargets.map(
                        (
                            {
                                bgName,
                                bgColor,
                                fgName,
                                fgColor,
                                unmetContrast,
                                achievedContrast,
                            },
                            i
                        ) => (
                            <li key={ i }>
                                { fgName } (
                                <span
                                    style={ {
                                        width: 20,
                                        height: 20,
                                        backgroundColor: fgColor,
                                        display: 'inline-block',
                                    } }
                                />
                                { fgColor }) over { bgName } (
                                <span
                                    style={ {
                                        width: 20,
                                        height: 20,
                                        backgroundColor: bgColor,
                                        display: 'inline-block',
                                    } }
                                />
                                { bgColor }) did not meet { unmetContrast },
                                achieved just { achievedContrast }
                            </li>
                        )
                    ) }
                </ul>
            ) }
        </div>
    );
};
Sample Combinations story ok
const SampleCombinations = () => {
    const combinations = [
        // WordPress (light / dark)
        {
            background: '#f8f8f8',
            primary: '#3858e9',
        },
        {
            background: '#1e1e1e',
            primary: '#3858e9',
        },
        // WP Classic
        {
            background: '#1d2327',
            primary: '#2271b1',
        },
        // WP Light
        {
            background: '#e5e5e5',
            primary: '#d64e07',
        },
        // WP Blue
        {
            background: '#096484',
            primary: '#52accc',
        },
        // WP Coffee
        {
            background: '#46403c',
            primary: '#c7a589',
        },
        // WP Ectoplasm
        {
            background: '#413256',
            primary: '#a3b745',
        },
        // WP Ocean
        {
            background: '#627c83',
            primary: '#9ebaa0',
        },
        // Sunrise
        {
            background: '#b43c38',
            primary: '#dd823b',
        },
    ];

    const ramps = combinations.map( ( { background, primary } ) => {
        const bgRamp = buildBgRamp( background );

        const bgRampObj = {
            seed: {
                name: 'surface2' as const,
                value: background,
            },
            ramp: bgRamp.ramp,
            warnings: bgRamp.warnings,
        };

        const primaryRamp = buildAccentRamp( primary, bgRamp );
        const primaryRampObj = {
            seed: {
                name: 'bgFill1' as const,
                value: primary,
            },
            ramp: primaryRamp.ramp,
            warnings: primaryRamp.warnings,
        };

        return [ bgRampObj, primaryRampObj ];
    } );

    return (
        <div
            style={ { display: 'flex', flexDirection: 'column', gap: 16 } }
        >
            { ramps.map( ( r, i ) => (
                <RampTable key={ i } ramps={ r } />
            ) ) }
        </div>
    );
};

ColorIndicator

components-colorindicator · ../packages/components/src/color-indicator/stories/index.story.tsx
ColorIndicator is a React component that renders a specific color in a circle. It's often used to summarize a collection of used colors in a child component. ```jsx import { ColorIndicator } from '@wordpress/components'; const MyColorIndicator = () => <ColorIndicator colorValue="#0073aa" />; ```
Imports
import { ColorIndicator } from "@wordpress/components";
Default story ok
const Default = () => <ColorIndicator colorValue="#0073aa" />;

ColorPalette

components-colorpalette · ../packages/components/src/color-palette/stories/index.story.tsx
Allows the user to pick a color from a list of pre-defined color entries. ```jsx import { ColorPalette } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyColorPalette = () => { const [ color, setColor ] = useState ( '#f00' ) const colors = [ { name: 'red', color: '#f00' }, { name: 'white', color: '#fff' }, { name: 'blue', color: '#00f' }, ]; return ( <ColorPalette colors={ colors } value={ color } onChange={ ( color ) => setColor( color ) } /> ); } ); ```
Imports
import { ColorPalette } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ color, setColor ] = useState< string | undefined >( value );

    return (
        <ColorPalette
            colors={[
                { name: 'Red', color: '#f00' },
                { name: 'White', color: '#fff' },
                { name: 'Blue', color: '#00f' },
            ]}
            value={ color }
            onChange={ ( newColor ) => {
				setColor( newColor );
				onChange?.( newColor );
			} } />
    );
};
Initial Value story ok
const InitialValue = () => {
    const [ color, setColor ] = useState< string | undefined >( value );

    return (
        <ColorPalette
            colors={[
                { name: 'Red', color: '#f00' },
                { name: 'White', color: '#fff' },
                { name: 'Blue', color: '#00f' },
            ]}
            value={ color }
            onChange={ ( newColor ) => {
				setColor( newColor );
				onChange?.( newColor );
			} } />
    );
};
Multiple Origins story ok
const MultipleOrigins = () => {
    const [ color, setColor ] = useState< string | undefined >( value );

    return (
        <ColorPalette
            colors={[
                {
                    name: 'Primary colors',
                    colors: [
                        { name: 'Red', color: '#f00' },
                        { name: 'Yellow', color: '#ff0' },
                        { name: 'Blue', color: '#00f' },
                    ],
                },
                {
                    name: 'Secondary colors',
                    colors: [
                        { name: 'Orange', color: '#f60' },
                        { name: 'Green', color: '#0f0' },
                        { name: 'Purple', color: '#60f' },
                    ],
                },
            ]}
            value={ color }
            onChange={ ( newColor ) => {
				setColor( newColor );
				onChange?.( newColor );
			} } />
    );
};
CSS Variables story ok
const CSSVariables = () => <div
    style={ {
        '--red': '#f00',
        '--yellow': '#ff0',
        '--blue': '#00f',
    } }>
    <Template
        colors={[
			{ name: 'Red', color: 'var(--red)' },
			{ name: 'Yellow', color: 'var(--yellow)' },
			{ name: 'Blue', color: 'var(--blue)' },
		]} />
</div>;

ColorPaletteControl

blockeditor-colorpalettecontrol · ../packages/block-editor/src/components/color-palette/stories/control.story.jsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { ColorPaletteControl } from "@wordpress/block-editor";
Default story ok
const Default = () => {
    const [ color, setColor ] = useState( args.value );

    return (
        <div style={ { maxWidth: '280px' } }>
            <ColorPaletteControl
                label="Text Color"
                disableCustomColors={false}
                colors={[
                    { name: 'Black', color: '#000000', slug: 'black' },
                    { name: 'Gray', color: '#555555', slug: 'gray' },
                    { name: 'White', color: '#ffffff', slug: 'white' },
                    { name: 'Red', color: '#cf2e2e', slug: 'red' },
                    { name: 'Blue', color: '#0693e3', slug: 'blue' },
                ]}
                value={ color }
                onChange={ ( newColor ) => {
                    setColor( newColor );
                    onChange( newColor );
                } } />
        </div>
    );
};

ColorPicker

components-colorpicker · ../packages/components/src/color-picker/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { ColorPicker } from "@wordpress/components";
Default story ok
const Default = () => <ColorPicker onChange={fn()} />;

ComboboxControl

components-comboboxcontrol · ../packages/components/src/combobox-control/stories/index.story.tsx
`ComboboxControl` is an enhanced version of a [`SelectControl`](../select-control/README.md) with the addition of being able to search for options using a search input. ```jsx import { ComboboxControl } from '@wordpress/components'; import { useState } from '@wordpress/element'; const options = [ { value: 'small', label: 'Small', }, { value: 'normal', label: 'Normal', disabled: true, }, { value: 'large', label: 'Large', disabled: false, }, ]; function MyComboboxControl() { const [ fontSize, setFontSize ] = useState(); const [ filteredOptions, setFilteredOptions ] = useState( options ); return ( <ComboboxControl __next40pxDefaultSize label="Font Size" value={ fontSize } onChange={ setFontSize } options={ filteredOptions } onFilterValueChange={ ( inputValue ) => setFilteredOptions( options.filter( ( option ) => option.label .toLowerCase() .startsWith( inputValue.toLowerCase() ) ) ) } /> ); } ```
Prop types 12 prop types
Component: ../packages/components/src/combobox-control/index.tsx::default
Props:
/**
 * Custom renderer invoked for each option in the suggestion list.
 * The render prop receives as its argument an object containing, under the `item` key,
 * the single option's data (directly from the array of data passed to the `options` prop).
 */
__experimentalRenderItem?: ( args: {
	item: ComboboxControlOption;
} ) => React.ReactNode

/**
 * Deprecated. Use `__next40pxDefaultSize` instead.
 * 
 * @default false
 * @deprecated
 * @ignore
 */
__next36pxDefaultSize?: boolean

/**
 * Start opting into the larger default height that will become the default size in a future version.
 * 
 * @default false
 */
__next40pxDefaultSize?: boolean

/**
 * Show a reset button to clear the input.
 * 
 * @default true
 */
allowReset?: boolean

/**
 * Automatically expand the dropdown when the control is focused.
 * If the control is clicked, the dropdown will expand regardless of this prop.
 * 
 * @default true
 */
expandOnFocus?: boolean

/**
 * Show a spinner (and hide the suggestions dropdown) while data
 * about the matching suggestions (ie the `options` prop) is loading
 * 
 * @default false
 */
isLoading?: boolean

/**
 * Customizable UI messages.
 */
messages?: {
	/**
	 * The message to announce to screen readers when a suggestion is selected.
	 *
	 * @default `__( 'Item selected.' )`
	 */
	selected: string;
}

/**
 * Function called with the selected value changes.
 */
onChange?: ( value: ComboboxControlProps[ 'value' ] ) => void

/**
 * Function called when the control's search input value changes. The argument contains the next input value.
 * 
 * @default noop
 */
onFilterValueChange?: ( value: string ) => void

/**
 * The options that can be chosen from.
 */
options: ComboboxControlOption[]

/**
 * If passed, the combobox input will show a placeholder string if no values are present.
 */
placeholder?: string

/**
 * The current value of the control.
 */
value?: string | null
Imports
import { ComboboxControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ value, setValue ] =
		useState< ComboboxControlProps[ 'value' ] >( null );

    return (
        <>
            <ComboboxControl
                __next40pxDefaultSize
                onFilterValueChange={fn()}
                label="Country"
                options={countryOptions}
                help="Help text to describe the control."
                value={ value }
                onChange={ ( ...changeArgs ) => {
					setValue( ...changeArgs );
					onChange?.( ...changeArgs );
				} } />
        </>
    );
};
With Custom Render Item story ok
The rendered output of each suggestion can be customized by passing a render function to the `__experimentalRenderItem` prop. (This is still an experimental feature and is subject to change.)
const WithCustomRenderItem = () => {
    const [ value, setValue ] =
		useState< ComboboxControlProps[ 'value' ] >( null );

    return (
        <>
            <ComboboxControl
                __next40pxDefaultSize
                onFilterValueChange={fn()}
                label="Author"
                options={[
                    {
                        value: 'parsley',
                        label: 'Parsley Montana',
                        age: 48,
                        country: 'Germany',
                    },
                    {
                        value: 'cabbage',
                        label: 'Cabbage New York',
                        age: 44,
                        country: 'France',
                    },
                    {
                        value: 'jake',
                        label: 'Jake Weary',
                        age: 41,
                        country: 'United Kingdom',
                    },
                ]}
                __experimentalRenderItem={( { item } ) => {
                    const { label, age, country } = item;
                    return (
                        <div>
                            <div style={ { marginBottom: '0.2rem' } }>{ label }</div>
                            <small>
                                Age: { age }, Country: { country }
                            </small>
                        </div>
                    );
                }}
                value={ value }
                onChange={ ( ...changeArgs ) => {
					setValue( ...changeArgs );
					onChange?.( ...changeArgs );
				} } />
        </>
    );
};
With Disabled Options story ok
You can disable options in the list by setting the `disabled` property to true for individual items in the option object.
const WithDisabledOptions = () => {
    const [ value, setValue ] =
		useState< ComboboxControlProps[ 'value' ] >( null );

    return (
        <>
            <ComboboxControl
                __next40pxDefaultSize
                onFilterValueChange={fn()}
                options={optionsWithDisabledOptions}
                value={ value }
                onChange={ ( ...changeArgs ) => {
					setValue( ...changeArgs );
					onChange?.( ...changeArgs );
				} } />
        </>
    );
};
Not Expand On Focus story ok
By default, the combobox expands when focused. You can disable this behavior by setting the `expandOnFocus` prop to `false`. This is useful when you want to show the suggestions only when the user interacts with the input.
const NotExpandOnFocus = () => {
    const [ value, setValue ] =
		useState< ComboboxControlProps[ 'value' ] >( null );

    return (
        <>
            <ComboboxControl
                __next40pxDefaultSize
                onFilterValueChange={fn()}
                options={countryOptions}
                expandOnFocus={false}
                value={ value }
                onChange={ ( ...changeArgs ) => {
					setValue( ...changeArgs );
					onChange?.( ...changeArgs );
				} } />
        </>
    );
};

Composite

components-composite · ../packages/components/src/composite/stories/index.story.tsx
Renders a widget based on the WAI-ARIA [`composite`](https://w3c.github.io/aria/#composite) role, which provides a single tab stop on the page and arrow key navigation through the focusable descendants.
example: ```jsx import { Composite } from '@wordpress/components'; <Composite> <Composite.Item>Item 1</Composite.Item> <Composite.Item>Item 2</Composite.Item> </Composite> ```
Prop types 7 prop types
Component: ../packages/components/src/composite/index.tsx::Composite
Props:
disabled?: any = false

focusLoop?: any = false

focusShift?: any = false

focusWrap?: any = false

orientation?: any = 'both'

rtl?: any = isRTL()

virtualFocus?: any = false
Imports
import { Composite, Provider as SlotFillProvider, Tooltip } from "@wordpress/components";
Default story ok
const Default = () => <Composite>(<>
        <Composite.Item>Item one</Composite.Item>
        <Composite.Item>Item two</Composite.Item>
        <Composite.Item>Item three</Composite.Item>
    </>)</Composite>;
Groups story ok
const Groups = () => <Composite>(<>
        <Composite.Group>
            <Composite.GroupLabel>Group one</Composite.GroupLabel>
            <Composite.Item>Item 1.1</Composite.Item>
            <Composite.Item>Item 1.2</Composite.Item>
        </Composite.Group>
        <Composite.Group>
            <Composite.GroupLabel>Group two</Composite.GroupLabel>
            <Composite.Item>Item 2.1</Composite.Item>
            <Composite.Item>Item 2.1</Composite.Item>
        </Composite.Group>
    </>)</Composite>;
Grid story ok
const Grid = () => <Composite role="grid" aria-label="Composite">(<>
        <Composite.Row role="row">
            <Composite.Item role="gridcell">Item A1</Composite.Item>
            <Composite.Item role="gridcell">Item A2</Composite.Item>
            <Composite.Item role="gridcell">Item A3</Composite.Item>
        </Composite.Row>
        <Composite.Row role="row">
            <Composite.Item role="gridcell">Item B1</Composite.Item>
            <Composite.Item role="gridcell">Item B2</Composite.Item>
            <Composite.Item role="gridcell">Item B3</Composite.Item>
        </Composite.Row>
        <Composite.Row role="row">
            <Composite.Item role="gridcell">Item C1</Composite.Item>
            <Composite.Item role="gridcell">Item C2</Composite.Item>
            <Composite.Item role="gridcell">Item C3</Composite.Item>
        </Composite.Row>
    </>)</Composite>;
Hover story ok
const Hover = () => <Composite>(<>
        <Composite.Hover render={ <Composite.Item /> }>
            Hover item one
        </Composite.Hover>
        <Composite.Hover render={ <Composite.Item /> }>
            Hover item two
        </Composite.Hover>
        <Composite.Hover render={ <Composite.Item /> }>
            Hover item three
        </Composite.Hover>
    </>)</Composite>;
Typeahead story ok
const Typeahead = () => <Composite render={<Composite.Typeahead />}>(<>
        <Composite.Item>Apple</Composite.Item>
        <Composite.Item>Banana</Composite.Item>
        <Composite.Item>Peach</Composite.Item>
    </>)</Composite>;
With Slot Fill story ok
const WithSlotFill = () => <Composite>(<>
        <Composite.Item>Item one (direct child)</Composite.Item>
        <Slot />
        <Composite.Item>Item four (direct child)</Composite.Item>
    </>)</Composite>;
With Tooltips story ok
Combining the `Tooltip` and `Composite` component has a few caveats. And while there are a few ways to compose these two components, our recommendation is to render `Composite.Item` as a child of `Tooltip`. ```jsx // 🔴 Does not work <Composite.Item render={ <Tooltip text="Tooltip"> <button>Item</button> </Tooltip> } /> // 🟢 Good <Tooltip text="Tooltip one"> <Composite.Item> Item one </Composite.Item> </Tooltip> ```
const WithTooltips = () => <Composite>(<>
        <Tooltip text="Tooltip one">
            <Composite.Item>Item one</Composite.Item>
        </Tooltip>
        <Tooltip text="Tooltip two">
            <Composite.Item>Item two</Composite.Item>
        </Tooltip>
        <Tooltip text="Tooltip three">
            <Composite.Item>Item three</Composite.Item>
        </Tooltip>
    </>)</Composite>;

ConfirmDialog

components-confirmdialog · ../packages/components/src/confirm-dialog/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Button, ConfirmDialog } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ isOpen, setIsOpen ] = useState( false );

    const handleConfirm: typeof onConfirm = ( confirmArgs ) => {
		onConfirm( confirmArgs );
		setIsOpen( false );
	};

    const handleCancel: typeof onCancel = ( cancelArgs ) => {
		onCancel?.( cancelArgs );
		setIsOpen( false );
	};

    return (
        <>
            <Button
                __next40pxDefaultSize
                variant="primary"
                onClick={ () => setIsOpen( true ) }>Open ConfirmDialog
                            </Button>
            <ConfirmDialog isOpen={ isOpen } onConfirm={ handleConfirm } onCancel={ handleCancel }>
                Would you like to privately publish the post now?
            </ConfirmDialog>
        </>
    );
};
With Custom Button Labels story ok
const WithCustomButtonLabels = () => {
    const [ isOpen, setIsOpen ] = useState( false );

    const handleConfirm: typeof onConfirm = ( confirmArgs ) => {
		onConfirm( confirmArgs );
		setIsOpen( false );
	};

    const handleCancel: typeof onCancel = ( cancelArgs ) => {
		onCancel?.( cancelArgs );
		setIsOpen( false );
	};

    return (
        <>
            <Button
                __next40pxDefaultSize
                variant="primary"
                onClick={ () => setIsOpen( true ) }>Open ConfirmDialog
                            </Button>
            <ConfirmDialog
                cancelButtonText="No thanks"
                confirmButtonText="Yes please!"
                isOpen={ isOpen }
                onConfirm={ handleConfirm }
                onCancel={ handleCancel }>
                { args.children }
            </ConfirmDialog>
        </>
    );
};

CustomGradientPicker

components-customgradientpicker · ../packages/components/src/custom-gradient-picker/stories/index.story.tsx
CustomGradientPicker is a React component that renders a UI for specifying linear or radial gradients. Radial gradients are displayed in the picker as a slice of the gradient from the center to the outside. ```jsx import { CustomGradientPicker } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyCustomGradientPicker = () => { const [ gradient, setGradient ] = useState(); return ( <CustomGradientPicker value={ gradient } onChange={ setGradient } /> ); }; ```
Prop types 5 prop types
Component: ../packages/components/src/custom-gradient-picker/index.tsx::CustomGradientPicker
Props:
/**
 * Whether this is rendered in the sidebar.
 * 
 * @default false
 */
__experimentalIsRenderedInSidebar?: boolean = false

/**
 * Start opting in to the new margin-free styles that will become the default
 * in a future version, currently scheduled to be WordPress 6.4. (The prop
 * can be safely removed once this happens.)
 * 
 * @default false
 * @deprecated Default behavior since WP 6.5. Prop can be safely removed.
 * @ignore
 */
__nextHasNoMargin?: boolean

/**
 * Whether to enable alpha transparency options in the picker.
 * 
 * @default true
 */
enableAlpha?: boolean = true

/**
 * The function called when a new gradient has been defined. It is passed to
 * the `currentGradient` as an argument.
 */
onChange: ( currentGradient: string ) => void

/**
 * The current value of the gradient. Pass a css gradient string (See default value for example).
 * Optionally pass in a `null` value to specify no gradient is currently selected.
 * 
 * @default 'linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)'
 */
value?: string | null
Imports
import { CustomGradientPicker } from "@wordpress/components";
Default story ok
const Default = ( { onChange, ...props } ) => {
	const [ gradient, setGradient ] = useState< string >();
	return (
		<CustomGradientPicker
			{ ...props }
			value={ gradient }
			onChange={ ( newGradient ) => {
				setGradient( newGradient );
				onChange( newGradient );
			} }
		/>
	);
};

CustomSelectControl

components-customselectcontrol · ../packages/components/src/custom-select-control/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 17 prop types
Component: ../packages/components/src/custom-select-control/index.tsx::default
Props:
/**
 * Use the `showSelectedHint` property instead.
 * @deprecated
 * @ignore
 */
__experimentalShowSelectedHint?: boolean

/**
 * Start opting into the larger default height that will become the default size in a future version.
 * 
 * @default false
 */
__next40pxDefaultSize?: boolean

/**
 * Opt-in prop for an unconstrained width style which became the default in
 * WordPress 6.5. The prop is no longer needed and can be safely removed.
 * 
 * @deprecated
 * @ignore
 */
__nextUnconstrainedWidth?: boolean

/**
 * Do not throw a warning for the deprecated 36px default size.
 * For internal components of other components that already throw the warning.
 * 
 * @ignore
 */
__shouldNotWarnDeprecated36pxSize?: boolean

/**
 * Optional classname for the component.
 */
className?: string

/**
 * Description for the select trigger button used by assistive technology.
 * If no value is passed, the text "Currently selected: selectedItem.name"
 * will be used fully translated.
 */
describedBy?: string

/**
 * Hide the label visually, while keeping available to assistive technology.
 */
hideLabelFromVision?: boolean

/**
 * Label for the control.
 */
label: string

/**
 * A handler for `blur` events on the trigger button.
 * 
 * @ignore
 */
onBlur?: FocusEventHandler< HTMLButtonElement >

/**
 * Function called with the control's internal state changes. The `selectedItem`
 * property contains the next selected item.
 */
onChange?: ( newValue: CustomSelectChangeObject< NoInfer< T > > ) => void

/**
 * A handler for `focus` events on the trigger button.
 * 
 * @ignore
 */
onFocus?: FocusEventHandler< HTMLButtonElement >

/**
 * A handler for `mouseout` events on the trigger button.
 * 
 * @ignore
 */
onMouseOut?: MouseEventHandler< HTMLButtonElement >

/**
 * A handler for `mouseover` events on the trigger button.
 * 
 * @ignore
 */
onMouseOver?: MouseEventHandler< HTMLButtonElement >

/**
 * The list of options that can be chosen from.
 */
options: ReadonlyArray< T >

/**
 * Show the hint of the selected item in the trigger button.
 * 
 * @default false
 */
showSelectedHint?: boolean

/**
 * The size of the control.
 * 
 * @default 'default'
 */
size?: 'default' | 'small' | '__unstable-large'

/**
 * Can be used to externally control the value of the control.
 */
value?: NoInfer< T >
Imports
import { CustomSelectControl } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	const [ value, setValue ] = useState( props.options[ 0 ] );

	const onChange: React.ComponentProps<
		typeof CustomSelectControl
	>[ 'onChange' ] = ( changeObject ) => {
		setValue( changeObject.selectedItem );
		props.onChange?.( changeObject );
	};

	return (
		<CustomSelectControl
			__next40pxDefaultSize
			{ ...props }
			onChange={ onChange }
			value={ value }
		/>
	);
};
With Long Labels story ok
const WithLongLabels = ( props ) => {
	const [ value, setValue ] = useState( props.options[ 0 ] );

	const onChange: React.ComponentProps<
		typeof CustomSelectControl
	>[ 'onChange' ] = ( changeObject ) => {
		setValue( changeObject.selectedItem );
		props.onChange?.( changeObject );
	};

	return (
		<CustomSelectControl
			__next40pxDefaultSize
			{ ...props }
			onChange={ onChange }
			value={ value }
		/>
	);
};
With Hints story ok
const WithHints = ( props ) => {
	const [ value, setValue ] = useState( props.options[ 0 ] );

	const onChange: React.ComponentProps<
		typeof CustomSelectControl
	>[ 'onChange' ] = ( changeObject ) => {
		setValue( changeObject.selectedItem );
		props.onChange?.( changeObject );
	};

	return (
		<CustomSelectControl
			__next40pxDefaultSize
			{ ...props }
			onChange={ onChange }
			value={ value }
		/>
	);
};

CustomSelectControlV2

components-customselectcontrol-v2 · ../packages/components/src/custom-select-control-v2/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { CustomSelectControlV2 } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	const [ value, setValue ] = useState< string | readonly string[] >();
	return (
		<CustomSelectControlV2
			{ ...props }
			onChange={ ( nextValue ) => {
				setValue( nextValue );
				props.onChange?.( nextValue );
			} }
			value={ value }
		/>
	);
};
Multiple Selection story ok
Multiple selection can be enabled by using an array for the `value` and `defaultValue` props. The argument type of the `onChange` function will also change accordingly.
const MultipleSelection = ( props ) => {
	const [ value, setValue ] = useState< string | readonly string[] >();
	return (
		<CustomSelectControlV2
			{ ...props }
			onChange={ ( nextValue ) => {
				setValue( nextValue );
				props.onChange?.( nextValue );
			} }
			value={ value }
		/>
	);
};
Custom Selected Value story ok
The `renderSelectedValue` prop can be used to customize how the selected value is rendered in the dropdown trigger.
const CustomSelectedValue = ( props ) => {
	const [ value, setValue ] = useState< string | readonly string[] >();
	return (
		<CustomSelectControlV2
			{ ...props }
			onChange={ ( nextValue ) => {
				setValue( nextValue );
				props.onChange?.( nextValue );
			} }
			value={ value }
		/>
	);
};

DataForm

dataviews-dataform-content · ../packages/dataviews/src/dataform/stories/content.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 5 prop types
Component: ../packages/dataviews/src/dataform/index.tsx::default
Props:
data: Item

fields: Field< Item >[]

form: {
	layout?: Layout;
	fields?: Array< FormField | string >;
}

onChange: ( value: Record< string, any > ) => void

validity?: Record< string, FieldValidity > | undefined
Imports
import { DataForm } from "@wordpress/dataviews";
import { Stack } from "@wordpress/ui";
Labels story ok
const Labels = () => {
    const [ data, setData ] = useState< SampleData >( {
        name: '',
        email: '',
        phone: '',
    } );

    const fields: Field< SampleData >[] = useMemo(
        () => [
            {
                id: 'name',
                label: 'Name',
                type: 'text',
            },
            {
                id: 'email',
                label: 'Email',
                type: 'email',
            },
            {
                id: 'phone',
                label: 'Phone number',
                type: 'telephone',
            },
        ],
        []
    );

    const form: Form = useMemo(
        () => ( {
            layout: { type: 'regular' },
            fields: [ 'name', 'email', 'phone' ],
        } ),
        []
    );

    return (
        <Stack direction="column" gap="lg">
            <DataForm< SampleData >
                data={ data }
                fields={ fields }
                form={ form }
                onChange={ ( edits ) =>
                    setData( ( prev ) => ( { ...prev, ...edits } ) )
                }
            />
        </Stack>
    );
};
Help Text story ok
const HelpText = () => {
    const [ data, setData ] = useState< HelpTextData >( {
        name: '',
        email: '',
        phone: '',
    } );

    const fields: Field< HelpTextData >[] = useMemo(
        () => [
            {
                id: 'name',
                label: 'Name',
                type: 'text',
                placeholder: 'Jane Doe',
                description:
                    'Enter your full legal name as it appears on official documents.',
            },
            {
                id: 'email',
                label: 'Email',
                type: 'email',
                placeholder: 'you@example.com',
                description:
                    'We will use this to send you important account notifications and updates.',
            },
            {
                id: 'phone',
                label: 'Phone number',
                type: 'telephone',
                placeholder: '+1 (555) 123-4567',
                description:
                    'Include your country code. This number will be used for account verification.',
            },
        ],
        []
    );

    const form: Form = useMemo(
        () => ( {
            layout: { type: 'regular' },
            fields: [ 'name', 'email', 'phone' ],
        } ),
        []
    );

    return (
        <Stack direction="column" gap="lg">
            <DataForm< HelpTextData >
                data={ data }
                fields={ fields }
                form={ form }
                onChange={ ( edits ) =>
                    setData( ( prev ) => ( { ...prev, ...edits } ) )
                }
            />
        </Stack>
    );
};
Validation Messages story ok
const ValidationMessages = () => {
    const [ data, setData ] = useState< ValidationMessagesData >( {
        name: '',
        email: 'invalid-email',
        phone: '123',
    } );

    const fields: Field< ValidationMessagesData >[] = useMemo(
        () => [
            {
                id: 'name',
                label: 'Name',
                type: 'text',
                placeholder: 'Jane Doe',
                isValid: {
                    required: true,
                },
            },
            {
                id: 'email',
                label: 'Email',
                type: 'email',
                placeholder: 'you@example.com',
                isValid: {
                    required: true,
                    custom: ( item ) => {
                        if ( ! item.email ) {
                            return null;
                        }
                        if ( ! item.email.includes( '@' ) ) {
                            return 'Please enter a valid email address.';
                        }
                        return null;
                    },
                },
            },
            {
                id: 'phone',
                label: 'Phone number',
                type: 'telephone',
                placeholder: '+1 (555) 123-4567',
                isValid: {
                    required: true,
                    custom: ( item ) => {
                        if ( ! item.phone ) {
                            return null;
                        }
                        if ( item.phone.length < 10 ) {
                            return 'Phone number must be at least 10 digits long.';
                        }
                        return null;
                    },
                },
            },
        ],
        []
    );

    const form: Form = useMemo(
        () => ( {
            layout: { type: 'regular' },
            fields: [ 'name', 'email', 'phone' ],
        } ),
        []
    );

    const { validity } = useFormValidity( data, fields, form );
    const containerRef = useRef< HTMLDivElement >( null );

    // Show validation messages on load without focusing
    useEffect( () => {
        if ( validity && containerRef.current ) {
            const inputs = containerRef.current.querySelectorAll( 'input' );
            inputs.forEach( ( input ) => {
                // Dispatch 'invalid' event to trigger the validation message display
                input.dispatchEvent(
                    new Event( 'invalid', { bubbles: false } )
                );
            } );
        }
    }, [ validity ] );

    return (
        <div ref={ containerRef }>
            <Stack direction="column" gap="xl">
                <DataForm< ValidationMessagesData >
                    data={ data }
                    fields={ fields }
                    form={ form }
                    validity={ validity }
                    onChange={ ( edits ) =>
                        setData( ( prev ) => ( { ...prev, ...edits } ) )
                    }
                />
            </Stack>
        </div>
    );
};
High Level Help Text story ok
const HighLevelHelpText = () => {
    const [ data, setData ] = useState< HighLevelHelpTextData >( {
        name: '',
        email: '',
        phone: '',
    } );

    const fields: Field< HighLevelHelpTextData >[] = useMemo(
        () => [
            {
                id: 'name',
                label: 'Name',
                type: 'text',
            },
            {
                id: 'email',
                label: 'Email',
                type: 'email',
            },
            {
                id: 'phone',
                label: 'Phone number',
                type: 'telephone',
            },
        ],
        []
    );

    const form: Form = useMemo(
        () => ( {
            layout: { type: 'regular' },
            fields: [
                {
                    id: 'accountForm',
                    label: 'Account Information',
                    description:
                        'We collect this information to create your account and provide personalized services. Your data will be kept secure and used only for account management and service improvements.',
                    children: [ 'name', 'email', 'phone' ],
                    layout: {
                        isCollapsible: false,
                        summary: 'account-form',
                        type: 'card',
                        withHeader: true,
                    },
                },
            ],
        } ),
        []
    );

    return (
        <Stack direction="column" gap="lg">
            <DataForm< HighLevelHelpTextData >
                data={ data }
                fields={ fields }
                form={ form }
                onChange={ ( edits ) =>
                    setData( ( prev ) => ( { ...prev, ...edits } ) )
                }
            />
        </Stack>
    );
};
Placeholders story ok
const Placeholders = () => {
    const [ data, setData ] = useState< PlaceholdersData >( {
        name: '',
        email: '',
        phone: '',
    } );

    const fields: Field< PlaceholdersData >[] = useMemo(
        () => [
            {
                id: 'name',
                label: 'Name',
                type: 'text',
                placeholder: 'Jane Doe',
            },
            {
                id: 'email',
                label: 'Email',
                type: 'email',
                placeholder: 'you@example.com',
            },
            {
                id: 'phone',
                label: 'Phone number',
                type: 'telephone',
                placeholder: '+1 (555) 123-4567',
            },
        ],
        []
    );

    const form: Form = useMemo(
        () => ( {
            layout: { type: 'regular' },
            fields: [ 'name', 'email', 'phone' ],
        } ),
        []
    );

    return (
        <Stack direction="column" gap="lg">
            <DataForm< PlaceholdersData >
                data={ data }
                fields={ fields }
                form={ form }
                onChange={ ( edits ) =>
                    setData( ( prev ) => ( { ...prev, ...edits } ) )
                }
            />
        </Stack>
    );
};

DataForm

dataviews-dataform · ../packages/dataviews/src/dataform/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 5 prop types
Component: ../packages/dataviews/src/dataform/index.tsx::default
Props:
data: Item

fields: Field< Item >[]

form: {
	layout?: Layout;
	fields?: Array< FormField | string >;
}

onChange: ( value: Record< string, any > ) => void

validity?: Record< string, FieldValidity > | undefined
Imports
import { DataForm } from "@wordpress/dataviews";
Layout Card story ok
const LayoutCard = () => <DataForm withHeader withSummary isCollapsible />;
Layout Details story ok
const LayoutDetails = () => <DataForm />;
Layout Panel story ok
const LayoutPanel = () => <DataForm openAs="default" />;
Layout Regular story ok
const LayoutRegular = () => <DataForm disabled={false} />;
Layout Row story ok
const LayoutRow = () => <DataForm alignment="default" />;
Layout Mixed story ok
const LayoutMixed = () => <DataForm />;
Validation story ok
const Validation = () => <DataForm
    layout="regular"
    required
    elements="sync"
    custom="sync"
    pattern={false}
    minMax={false} />;
Visibility story ok
const Visibility = () => <DataForm />;
Data Adapter story ok
const DataAdapter = () => <DataForm />;

DataForm

dataviews-fieldtypes · ../packages/dataviews/src/field-types/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 5 prop types
Component: ../packages/dataviews/src/dataform/index.tsx::default
Props:
data: Item

fields: Field< Item >[]

form: {
	layout?: Layout;
	fields?: Array< FormField | string >;
}

onChange: ( value: Record< string, any > ) => void

validity?: Record< string, FieldValidity > | undefined
Imports
import { DataForm, DataViews } from "@wordpress/dataviews";
import {
    Icon,
    __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper,
    __experimentalInputControlSuffixWrapper as InputControlSuffixWrapper,
} from "@wordpress/components";
import { Stack } from "@wordpress/ui";
All types story ok
const AllComponent = ( {
	type,
	Edit,
	asyncElements,
	manyElements,
	disabled,
}: {
	type: PanelTypes;
	Edit: ControlTypes;
	asyncElements: boolean;
	manyElements: boolean;
	disabled: boolean;
} ) => {
	return (
		<FieldTypeStory
			fields={ fields }
			type={ type }
			Edit={ Edit }
			asyncElements={ asyncElements }
			manyElements={ manyElements }
			disabled={ disabled }
		/>
	);
};
text story ok
const TextComponent = ( {
	type,
	Edit,
	asyncElements,
	manyElements,
	disabled,
}: {
	type: PanelTypes;
	Edit: ControlTypes;
	asyncElements: boolean;
	manyElements: boolean;
	disabled: boolean;
} ) => {
	const textFields = useMemo(
		() => fields.filter( ( field ) => field.type === 'text' ),
		[]
	);

	return (
		<FieldTypeStory
			fields={ textFields }
			type={ type }
			Edit={ Edit }
			asyncElements={ asyncElements }
			manyElements={ manyElements }
			disabled={ disabled }
		/>
	);
};
integer story ok
const IntegerComponent = ( {
	type,
	Edit,
	asyncElements,
	manyElements,
	formatSeparatorThousand,
	disabled,
}: {
	type: PanelTypes;
	Edit: ControlTypes;
	asyncElements: boolean;
	manyElements: boolean;
	formatSeparatorThousand?: string;
	disabled: boolean;
} ) => {
	const integerFields = useMemo(
		() =>
			fields
				.filter( ( field ) => field.type === 'integer' )
				.map( ( field ) => {
					if ( formatSeparatorThousand !== undefined ) {
						return {
							...field,
							format: {
								separatorThousand: formatSeparatorThousand,
							},
						};
					}
					return field;
				} ),
		[ formatSeparatorThousand ]
	);

	return (
		<FieldTypeStory
			fields={ integerFields }
			type={ type }
			Edit={ Edit }
			asyncElements={ asyncElements }
			manyElements={ manyElements }
			disabled={ disabled }
		/>
	);
};
number story ok
const NumberComponent = ( {
	type,
	Edit,
	asyncElements,
	manyElements,
	formatSeparatorThousand,
	formatSeparatorDecimal,
	formatDecimals,
	disabled,
}: {
	type: PanelTypes;
	Edit: ControlTypes;
	asyncElements: boolean;
	manyElements: boolean;
	formatSeparatorThousand?: string;
	formatSeparatorDecimal?: string;
	formatDecimals?: number;
	disabled: boolean;
} ) => {
	const numberFields = useMemo(
		() =>
			fields
				.filter( ( field ) => field.type === 'number' )
				.map( ( field ) => {
					if (
						formatSeparatorThousand !== undefined ||
						formatSeparatorDecimal !== undefined ||
						formatDecimals !== undefined
					) {
						const format: {
							separatorThousand?: string;
							separatorDecimal?: string;
							decimals?: number;
						} = {};
						if ( formatSeparatorThousand !== undefined ) {
							format.separatorThousand = formatSeparatorThousand;
						}
						if ( formatSeparatorDecimal !== undefined ) {
							format.separatorDecimal = formatSeparatorDecimal;
						}
						if ( formatDecimals !== undefined ) {
							format.decimals = formatDecimals;
						}
						return {
							...field,
							format,
						};
					}
					return field;
				} ),
		[ formatSeparatorThousand, formatSeparatorDecimal, formatDecimals ]
	);

	return (
		<FieldTypeStory
			fields={ numberFields }
			type={ type }
			Edit={ Edit }
			asyncElements={ asyncElements }
			manyElements={ manyElements }
			disabled={ disabled }
		/>
	);
};
boolean story ok
const BooleanComponent = ( {
	type,
	Edit,
	asyncElements,
	manyElements,
	disabled,
}: {
	type: PanelTypes;
	Edit: ControlTypes;
	asyncElements: boolean;
	manyElements: boolean;
	disabled: boolean;
} ) => {
	const booleanFields = useMemo(
		() => fields.filter( ( field ) => field.type === 'boolean' ),
		[]
	);

	return (
		<FieldTypeStory
			fields={ booleanFields }
			type={ type }
			Edit={ Edit }
			asyncElements={ asyncElements }
			manyElements={ manyElements }
			disabled={ disabled }
		/>
	);
};
datetime story ok
const DateTimeComponent = ( {
	type,
	Edit,
	asyncElements,
	manyElements,
	formatDatetime,
	formatWeekStartsOn,
	disabled,
}: {
	type: PanelTypes;
	Edit: ControlTypes;
	asyncElements: boolean;
	manyElements: boolean;
	formatDatetime?: string;
	formatWeekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
	disabled: boolean;
} ) => {
	const datetimeFields = useMemo(
		() =>
			fields
				.filter( ( field ) => field.id.startsWith( 'datetime' ) )
				.map( ( field ) => {
					if ( formatDatetime || formatWeekStartsOn !== undefined ) {
						const format: {
							datetime?: string;
							weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
						} = {};
						if ( formatDatetime ) {
							format.datetime = formatDatetime;
						}
						if ( formatWeekStartsOn !== undefined ) {
							format.weekStartsOn = formatWeekStartsOn;
						}
						return {
							...field,
							format,
						};
					}
					return field;
				} ),
		[ formatDatetime, formatWeekStartsOn ]
	);

	return (
		<FieldTypeStory
			fields={ datetimeFields }
			type={ type }
			Edit={ Edit }
			asyncElements={ asyncElements }
			manyElements={ manyElements }
			disabled={ disabled }
		/>
	);
};
date story ok
const DateComponent = ( {
	type,
	Edit,
	asyncElements,
	manyElements,
	formatDate,
	formatWeekStartsOn,
	disabled,
}: {
	type: PanelTypes;
	Edit: ControlTypes;
	asyncElements: boolean;
	manyElements: boolean;
	formatDate?: string;
	formatWeekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
	disabled: boolean;
} ) => {
	const dateFields = useMemo(
		() =>
			fields
				.filter( ( field ) => field.type === 'date' )
				.map( ( field ) => {
					if ( formatDate || formatWeekStartsOn !== undefined ) {
						const format: {
							date?: string;
							weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
						} = {};
						if ( formatDate ) {
							format.date = formatDate;
						}
						if ( formatWeekStartsOn !== undefined ) {
							format.weekStartsOn = formatWeekStartsOn;
						}
						return {
							...field,
							format,
						};
					}
					return field;
				} ),
		[ formatDate, formatWeekStartsOn ]
	);

	return (
		<FieldTypeStory
			fields={ dateFields }
			type={ type }
			Edit={ Edit }
			asyncElements={ asyncElements }
			manyElements={ manyElements }
			disabled={ disabled }
		/>
	);
};
email story ok
const EmailComponent = ( {
	type,
	Edit,
	asyncElements,
	manyElements,
	disabled,
}: {
	type: PanelTypes;
	Edit: ControlTypes;
	asyncElements: boolean;
	manyElements: boolean;
	disabled: boolean;
} ) => {
	const emailFields = useMemo(
		() => fields.filter( ( field ) => field.type === 'email' ),
		[]
	);

	return (
		<FieldTypeStory
			fields={ emailFields }
			type={ type }
			Edit={ Edit }
			asyncElements={ asyncElements }
			manyElements={ manyElements }
			disabled={ disabled }
		/>
	);
};
telephone story ok
const TelephoneComponent = ( {
	type,
	Edit,
	asyncElements,
	manyElements,
	disabled,
}: {
	type: PanelTypes;
	Edit: ControlTypes;
	asyncElements: boolean;
	manyElements: boolean;
	disabled: boolean;
} ) => {
	const telephoneFields = fields.filter( ( field ) =>
		field.id.startsWith( 'telephone' )
	);

	return (
		<FieldTypeStory
			fields={ telephoneFields }
			type={ type }
			Edit={ Edit }
			asyncElements={ asyncElements }
			manyElements={ manyElements }
			disabled={ disabled }
		/>
	);
};
url story ok
const UrlComponent = ( {
	type,
	Edit,
	asyncElements,
	manyElements,
	disabled,
}: {
	type: PanelTypes;
	Edit: ControlTypes;
	asyncElements: boolean;
	manyElements: boolean;
	disabled: boolean;
} ) => {
	const urlFields = useMemo(
		() => fields.filter( ( field ) => field.type === 'url' ),
		[]
	);

	return (
		<FieldTypeStory
			fields={ urlFields }
			type={ type }
			Edit={ Edit }
			asyncElements={ asyncElements }
			manyElements={ manyElements }
			disabled={ disabled }
		/>
	);
};
color story ok
const ColorComponent = ( {
	type,
	Edit,
	asyncElements,
	manyElements,
	disabled,
}: {
	type: PanelTypes;
	Edit: ControlTypes;
	asyncElements: boolean;
	manyElements: boolean;
	disabled: boolean;
} ) => {
	const colorFields = useMemo(
		() => fields.filter( ( field ) => field.type === 'color' ),
		[]
	);

	return (
		<FieldTypeStory
			fields={ colorFields }
			type={ type }
			Edit={ Edit }
			asyncElements={ asyncElements }
			manyElements={ manyElements }
			disabled={ disabled }
		/>
	);
};
media story ok
const MediaComponent = ( {
	type,
	Edit,
	asyncElements,
	manyElements,
	disabled,
}: {
	type: PanelTypes;
	Edit: ControlTypes;
	asyncElements: boolean;
	manyElements: boolean;
	disabled: boolean;
} ) => {
	const mediaFields = useMemo(
		() => fields.filter( ( field ) => field.type === 'media' ),
		[]
	);

	return (
		<FieldTypeStory
			fields={ mediaFields }
			type={ type }
			Edit={ Edit }
			asyncElements={ asyncElements }
			manyElements={ manyElements }
			disabled={ disabled }
		/>
	);
};
array story ok
const ArrayComponent = ( {
	type,
	Edit,
	asyncElements,
	manyElements,
	disabled,
}: {
	type: PanelTypes;
	Edit: ControlTypes;
	asyncElements: boolean;
	manyElements: boolean;
	disabled: boolean;
} ) => {
	const arrayTextFields = useMemo(
		() => fields.filter( ( field ) => field.type === 'array' ),
		[]
	);

	return (
		<FieldTypeStory
			fields={ arrayTextFields }
			type={ type }
			Edit={ Edit }
			asyncElements={ asyncElements }
			manyElements={ manyElements }
			disabled={ disabled }
		/>
	);
};
password story ok
const PasswordComponent = ( {
	type,
	Edit,
	asyncElements,
	manyElements,
	disabled,
}: {
	type: PanelTypes;
	Edit: ControlTypes;
	asyncElements: boolean;
	manyElements: boolean;
	disabled: boolean;
} ) => {
	const passwordFields = fields.filter( ( field ) =>
		field.id.startsWith( 'password' )
	);

	return (
		<FieldTypeStory
			fields={ passwordFields }
			type={ type }
			Edit={ Edit }
			asyncElements={ asyncElements }
			manyElements={ manyElements }
			disabled={ disabled }
		/>
	);
};
No type story ok
const NoTypeComponent = ( {
	type,
	Edit,
	asyncElements,
	manyElements,
	disabled,
}: {
	type: PanelTypes;
	Edit: ControlTypes;
	asyncElements: boolean;
	manyElements: boolean;
	disabled: boolean;
} ) => {
	const noTypeFields = useMemo(
		() => fields.filter( ( field ) => field.type === undefined ),
		[]
	);

	return (
		<FieldTypeStory
			fields={ noTypeFields }
			type={ type }
			Edit={ Edit }
			asyncElements={ asyncElements }
			manyElements={ manyElements }
			disabled={ disabled }
		/>
	);
};

DataForm

fields-base-fields · ../packages/fields/src/stories/index.story.tsx
Prop type error
File: /home/runner/work/gutenberg/gutenberg/node_modules/@wordpress/dataviews/build-module/index.mjs
Error:
Component files in node_modules are not supported.
The distributed files in node_modules usually don't contain the necessary comments or types needed to analyze component information.
Configure TypeScript path aliases to map your package name to the source file instead.

Example (tsconfig.json):
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@design-system/button": ["src/components/Button.tsx"],
      "@design-system/*": ["src/components/*"]
    }
  }
}

Then import using:
import { Button } from '@design-system/button'

Storybook resolves tsconfig paths automatically.
Code:
/* File in node_modules */
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { DataForm, DataViews } from "@wordpress/dataviews";
Data Forms Preview story ok
const DataFormsPreview = ( { type }: { type: 'regular' | 'panel' } ) => {
	const [ data, setData ] = useState( samplePostWithAuthor );

	const handleChange = ( updates: Partial< BasePostWithEmbeddedAuthor > ) => {
		setData( ( prev ) => ( { ...prev, ...updates } ) );
	};

	// Form configuration for the showcase.
	const showcaseForm: Form = {
		layout: {
			type,
		},
		fields: [
			'title',
			'slug',
			'status',
			'date',
			'author',
			'comment_status',
			'password',
			'menu_order',
		],
	};

	return (
		<div style={ { padding: '20px' } }>
			<h2>Base Fields</h2>
			<p>
				This story demonstrates all the base fields from the
				@wordpress/fields package within a DataForm.
			</p>

			<DataForm
				data={ data }
				fields={ showcaseFields }
				form={ showcaseForm }
				onChange={ handleChange }
			/>
		</div>
	);
};
Data Views Preview story ok
const DataViewsPreview = () => {
	const [ view, setView ] = useState< View >( {
		type: 'table',
		fields: showcaseFields.map( ( f ) => f.id ),
		titleField: 'title',
		descriptionField: undefined,
		mediaField: undefined,
	} );
	const [ data ] = useState( [ samplePostWithAuthor ] );

	const paginationInfo = {
		totalItems: 1,
		totalPages: 1,
	};

	const defaultLayouts = {
		table: {},
		list: {},
		grid: {},
	};

	return (
		<div style={ { padding: '20px' } }>
			<h2>Fields Package DataViews Preview</h2>
			<p>
				This story demonstrates all the base fields from the
				@wordpress/fields package, rendered in a DataViews component,
				allowing preview of view state and layout switching.
			</p>
			<DataViews
				data={ data }
				fields={ showcaseFields }
				view={ view }
				onChangeView={ ( nextView: View ) => setView( nextView ) }
				paginationInfo={ paginationInfo }
				defaultLayouts={ defaultLayouts }
			/>
		</div>
	);
};

DataForm

fields-media-fields · ../packages/media-fields/src/stories/index.story.tsx
Prop type error
File: /home/runner/work/gutenberg/gutenberg/node_modules/@wordpress/dataviews/build-module/index.mjs
Error:
Component files in node_modules are not supported.
The distributed files in node_modules usually don't contain the necessary comments or types needed to analyze component information.
Configure TypeScript path aliases to map your package name to the source file instead.

Example (tsconfig.json):
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@design-system/button": ["src/components/Button.tsx"],
      "@design-system/*": ["src/components/*"]
    }
  }
}

Then import using:
import { Button } from '@design-system/button'

Storybook resolves tsconfig paths automatically.
Code:
/* File in node_modules */
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { DataForm, DataViews } from "@wordpress/dataviews";
Data Forms Preview story ok
const DataFormsPreview = ( { type }: { type: 'regular' | 'panel' } ) => {
	const [ data, setData ] = useState< MediaItem >( sampleMediaItem );

	const handleChange = ( updates: Partial< MediaItem > ) => {
		setData( ( prev: MediaItem ) => ( { ...prev, ...updates } ) );
	};

	// Form configuration for the media fields showcase.
	const showcaseForm: Form = {
		layout: {
			type,
		},
		fields: [
			'media_thumbnail',
			'alt_text',
			'caption',
			'description',
			'filename',
			'mime_type',
			'media_dimensions',
			'filesize',
			'author',
			'date',
			'modified',
			'attached_to',
		],
	};

	return (
		<div style={ { padding: '20px' } }>
			<h2>Media Fields</h2>
			<p>
				This story demonstrates all the media fields from the
				@wordpress/media-fields package within a DataForm.
			</p>

			<DataForm
				data={ data }
				fields={ showcaseFields }
				form={ showcaseForm }
				onChange={ handleChange }
			/>
		</div>
	);
};
Data Views Preview story ok
const DataViewsPreview = () => {
	const [ view, setView ] = useState< View >( {
		type: 'table',
		fields: showcaseFields
			.map( ( f ) => f.id )
			.filter( ( id ) => id !== 'media_thumbnail' ),
		descriptionField: undefined,
		mediaField: 'media_thumbnail',
		showTitle: false,
	} );
	const [ data ] = useState< MediaItem[] >( [
		sampleMediaItem,
		sampleMediaItemZip,
		sampleMediaItemBrokenImage,
	] );

	const paginationInfo = {
		totalItems: 3,
		totalPages: 1,
	};

	const defaultLayouts = {
		table: {},
		list: {},
		grid: {},
	};

	return (
		<div style={ { padding: '20px' } }>
			<h2>Media Fields DataViews Preview</h2>
			<p>
				This story demonstrates all the media fields from the
				@wordpress/media-fields package, rendered in a DataViews
				component, allowing preview of view state and layout switching.
			</p>
			<DataViews
				data={ data }
				fields={ showcaseFields }
				view={ view }
				onChangeView={ ( nextView: View ) => setView( nextView ) }
				paginationInfo={ paginationInfo }
				defaultLayouts={ defaultLayouts }
			/>
		</div>
	);
};

DataViews

dataviews-dataviews · ../packages/dataviews/src/dataviews/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 22 prop types
Component: ../packages/dataviews/src/dataviews/index.tsx
Props:
actions?: Action< Item >[] = []

children?: ReactNode

config?: {
	perPageSizes: number[];
} = { perPageSizes: [ 10, 20, 50, 100 ] }

data: Item[]

defaultLayouts: SupportedLayouts

empty?: ReactNode

fields: Field< Item >[]

getItemId?: any = ( item: ItemWithId ) => item.id

getItemLevel?: ( item: Item ) => number

header?: ReactNode

isItemClickable?: ( item: Item ) => boolean = () => true

isLoading?: boolean = false

onChangeSelection?: ( items: string[] ) => void

onChangeView: ( view: View ) => void

onClickItem?: ( item: Item ) => void

onReset?: ( () => void ) | false

paginationInfo: {
	totalItems: number;
	totalPages: number;
}

renderItemLink?: (
	props: {
		item: Item;
	} & ComponentProps< 'a' >
) => ReactElement

search?: boolean = true

searchLabel?: string = undefined

selection?: string[]

view: | ViewList
| ViewGrid
| ViewTable
| ViewPickerGrid
| ViewPickerTable
| ViewActivity
Imports
import { DataViews } from "@wordpress/dataviews";
Layout Table story ok
const LayoutTable = () => <DataViews
    containerHeight="auto"
    groupBy={false}
    groupByLabel
    hasClickableItems
    perPageSizes={[ 10, 25, 50, 100 ]}
    showMedia />;
Layout Grid story ok
const LayoutGrid = () => <DataViews
    containerHeight="auto"
    groupBy={false}
    groupByLabel
    hasClickableItems
    perPageSizes={[ 10, 25, 50, 100 ]}
    showMedia />;
Layout List story ok
const LayoutList = () => <DataViews
    containerHeight="auto"
    fullWidth={false}
    groupBy={false}
    groupByLabel
    hasClickableItems
    perPageSizes={[ 10, 25, 50, 100 ]}
    showMedia />;
Layout Activity story ok
const LayoutActivity = () => <DataViews
    containerHeight="auto"
    fullWidth={false}
    groupBy={false}
    groupByLabel
    hasClickableItems
    perPageSizes={[ 10, 25, 50, 100 ]}
    showMedia />;
Layout Custom story ok
const LayoutCustom = () => <DataViews containerHeight="auto" />;
Empty story ok
const Empty = () => <DataViews containerHeight="auto" customEmpty={false} isLoading={false} />;
Minimal UI story ok
const MinimalUI = () => <DataViews containerHeight="auto" />;
Free Composition story ok
const FreeComposition = () => <DataViews containerHeight="auto" />;
With Card story ok
const WithCard = () => <DataViews containerHeight="auto" />;
Infinite Scroll story ok
const InfiniteScroll = () => <DataViews containerHeight="auto" />;

DataViewsPicker

dataviews-dataviewspicker · ../packages/dataviews/src/dataviews-picker/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 17 prop types
Component: ../packages/dataviews/src/dataviews-picker/index.tsx
Props:
actions?: ActionButton< Item >[] = []

children?: ReactNode

config?: {
	perPageSizes: number[];
} = { perPageSizes: [ 10, 20, 50, 100 ] }

data: Item[]

defaultLayouts: SupportedLayouts

empty?: ReactNode

fields: Field< Item >[]

getItemId?: any = ( item: ItemWithId ) => item.id

isLoading?: boolean = false

itemListLabel?: string

onChangeSelection: ( items: string[] ) => void

onChangeView: ( view: View ) => void

paginationInfo: {
	totalItems: number;
	totalPages: number;
}

search?: boolean = true

searchLabel?: string = undefined

selection: string[]

view: | ViewList
| ViewGrid
| ViewTable
| ViewPickerGrid
| ViewPickerTable
| ViewActivity
Imports
import { Button, Modal } from "@wordpress/components";
import { DataViewsPicker } from "@wordpress/dataviews";
import { Stack } from "@wordpress/ui";
Default story ok
const Default = ( {
	perPageSizes = [ 10, 25, 50, 100 ],
	isMultiselectable,
	isGrouped,
	infiniteScrollEnabled,
}: {
	perPageSizes: number[];
	isMultiselectable: boolean;
	isGrouped: boolean;
	infiniteScrollEnabled: boolean;
} ) => (
	<DataViewsPickerContent
		perPageSizes={ perPageSizes }
		isMultiselectable={ isMultiselectable }
		isGrouped={ isGrouped }
		infiniteScrollEnabled={ infiniteScrollEnabled }
	/>
);
With Modal story ok
const WithModal = ( {
	perPageSizes = [ 10, 25, 50, 100 ],
	isMultiselectable,
	isGrouped,
	infiniteScrollEnabled,
}: {
	perPageSizes: number[];
	isMultiselectable: boolean;
	isGrouped: boolean;
	infiniteScrollEnabled: boolean;
} ) => {
	const [ isModalOpen, setIsModalOpen ] = useState( false );
	const [ selectedItems, setSelectedItems ] = useState< SpaceObject[] >( [] );

	const modalActions: ActionButton< SpaceObject >[] = [
		{
			id: 'cancel',
			label: 'Cancel',
			supportsBulk: isMultiselectable,
			callback() {
				setIsModalOpen( false );
			},
		},
		{
			id: 'confirm',
			label: 'Confirm',
			isPrimary: true,
			supportsBulk: isMultiselectable,
			callback( items ) {
				setSelectedItems( items );
				setIsModalOpen( false );
			},
		},
	];

	return (
		<>
			<Stack direction="row" justify="left" gap="sm">
				<Button
					variant="primary"
					onClick={ () => setIsModalOpen( true ) }
				>
					Open Picker Modal
				</Button>
				<Button
					onClick={ () => setSelectedItems( [] ) }
					disabled={ ! selectedItems.length }
					accessibleWhenDisabled
				>
					Clear Selection
				</Button>
			</Stack>
			{ selectedItems.length > 0 && (
				<p>
					Selected:{ ' ' }
					{ selectedItems
						.map( ( item ) => item.name.title )
						.join( ', ' ) }
				</p>
			) }
			{ isModalOpen && (
				<>
					<style>{ `
						.components-modal__content {
							padding: 0;
						}
						.components-modal__frame.is-full-screen .components-modal__content {
							margin-bottom: 0;
						}
					` }</style>
					<Modal
						title="Select Items"
						onRequestClose={ () => setIsModalOpen( false ) }
						isFullScreen={ false }
						size="fill"
					>
						<DataViewsPickerContent
							perPageSizes={ perPageSizes }
							isMultiselectable={ isMultiselectable }
							isGrouped={ isGrouped }
							infiniteScrollEnabled={ infiniteScrollEnabled }
							actions={ modalActions }
							selection={ selectedItems.map( ( item ) =>
								String( item.id )
							) }
						/>
					</Modal>
				</>
			) }
		</>
	);
};

DateCalendar

components-selection-input-time-date-datecalendar · ../packages/components/src/calendar/stories/date-calendar.story.tsx
`DateCalendar` is a React component that provides a customizable calendar interface for **single date** selection. The component is built with accessibility in mind and follows ARIA best practices for calendar widgets. It provides keyboard navigation, screen reader support, and customizable labels for internationalization.
Prop types 20 prop types
Component: ../packages/components/src/calendar/date-calendar/index.tsx::DateCalendar
Props:
/**
 * Focus the first selected day (if set) or today's date (if not disabled).
 * 
 * Use this prop when you need to focus the calendar after a user action
 * (e.g. opening the dialog with the calendar).
 */
autoFocus?: boolean

/**
 * The initial month to show in the calendar view (uncontrolled).
 * @default The current month
 */
defaultMonth?: Date

/**
 * The default selected date (for uncontrolled usage).
 */
defaultSelected?: Date

/**
 * Specify which days are disabled. Using `true` will disable all dates.
 */
disabled?: Matcher | Matcher[] | undefined

/**
 * Disable the navigation buttons.
 */
disableNavigation?: boolean

/**
 * The latest month to end the month navigation.
 */
endMonth?: Date

/**
 * When `true`, the calendar always shows a fixed number of weeks (e.g. 6)
 * so the grid height does not change between months.
 * @default false
 */
fixedWeeks?: boolean

/**
 * Use custom labels, useful for translating the component.
 * 
 * For a correct localized experience, consumers should make sure the locale
 * used for the translated labels and `locale` prop are consistent.
 */
labels?: {
	/**
	 * The label for the navigation toolbar.
	 * @default ""
	 */
	labelNav?: () => string;
	/**
	 * The label for the month grid.
	 * @default "LLLL y" (e.g. "November 2022")
	 */
	labelGrid?: ( date: Date ) => string;
	/**
	 * The label for the gridcell, when the calendar is not interactive.
	 * @default The formatted date.
	 */
	labelGridcell?: ( date: Date, modifiers?: Modifiers ) => string;
	/**
	 * The label for the "next month" button.
	 * @default "Go to the Next Month"
	 */
	labelNext?: ( month: Date | undefined ) => string;
	/**
	 * The label for the "previous month" button.
	 * @default "Go to the Previous Month"
	 */
	labelPrevious?: ( month: Date | undefined ) => string;
	/**
	 * The label for the day button.
	 * @default The formatted date.
	 */
	labelDayButton?: ( date: Date, modifiers?: Modifiers ) => string;
	/**
	 * The label for the weekday.
	 * @default ( date: Date ) => "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" | "Sunday"
	 */
	labelWeekday?: ( date: Date ) => string;
}

/**
 * The locale object used to localize dates. Pass a locale from
 * `@date-fns/locale` to localize the calendar.
 * 
 * For a correct localized experience, consumers should make sure the locale
 * used for the translated labels and `locale` prop are consistent.
 * @see https://github.com/date-fns/date-fns/tree/main/src/locale for a list of the supported locales
 * @default The `enUS` locale from `@date-fns/locale`
 */
locale?: Locale = enUS

/**
 * The month displayed in the calendar view (controlled). Use together with
 * `onMonthChange` to change the month programmatically.
 */
month?: Date

/**
 * The number of months displayed at once.
 * @default 1
 */
numberOfMonths?: number = 1

/**
 * Event fired when the user navigates between months.
 */
onMonthChange?: ( month: Date ) => void

/**
 * Event handler when a day is selected.
 */
onSelect?: (
	selected: T,
	triggerDate: Date,
	modifiers: Modifiers,
	e: React.MouseEvent | React.KeyboardEvent
) => void

/**
 * Whether the selection is required.
 * When `true`, there always needs to be a date selected.
 * @default false
 */
required?: boolean

/**
 * The role attribute to add to the container element.
 * @default 'application'
 */
role?: 'application' | 'dialog' | undefined

/**
 * The selected date.
 */
selected?: Date | undefined | null

/**
 * When `true`, days from adjacent months are shown in the grid and receive
 * the `outside` modifier and the class.
 * @default false
 */
showOutsideDays?: boolean

/**
 * The earliest month to start the month navigation.
 */
startMonth?: Date

/**
 * The time zone (IANA or UTC offset) to use in the calendar.
 * 
 * See
 * [Wikipedia](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
 * for the possible values.
 * 
 * When working with time zones, use the `TZDate` object exported by this
 * package instead of the native `Date` object.
 * @example
 *   import { DateCalendar, TZDate } from "@wordpress/components";
 * 
 *   export function WithTimeZone() {
 *     const timeZone = "America/New_York";
 *     const [ selected, setSelected ] = useState< Date | undefined >(
 *       new TZDate( 2024, 12, 10, timeZone ) // Use `TZDate` instead of `Date`
 *     );
 *     return (
 *       <DateCalendar
 *         timeZone={ timeZone }
 *         selected={ selected }
 *         onSelect={ setSelected }
 *     />
 *   );
 * }
 */
timeZone?: string

/**
 * The index of the first day of the week (0 - Sunday). Overrides the locale's
 * one.
 * @default Based on the `locale` prop
 */
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | undefined
Imports
import { DateCalendar } from "@wordpress/components";
Default story ok
const Default = () => <DateCalendar onMonthChange={fn()} onSelect={fn()} />;
Disabled Dates story ok
const DisabledDates = () => <DateCalendar
    onMonthChange={fn()}
    onSelect={fn()}
    disabled={[
        // Disable tomorrow (single date)
        new Date( new Date().setDate( new Date().getDate() + 1 ) ),
        // Disable all dates after Feb 1st of next year
        { after: new Date( new Date().getFullYear() + 1, 1, 1 ) },
        // Disable all dates before Dec 1st of last year
        { before: new Date( new Date().getFullYear() - 1, 11, 1 ) },
        // Disable all dates between 12th and 14th of August of this year
        {
            after: new Date( new Date().getFullYear(), 7, 11 ),
            before: new Date( new Date().getFullYear(), 7, 15 ),
        },
        // Disable all dates between 21st and 26th of October of this year
        {
            from: new Date( new Date().getFullYear(), 9, 21 ),
            to: new Date( new Date().getFullYear(), 9, 26 ),
        },
        // Disable all Wednesdays
        { dayOfWeek: 3 },
        // Disable all prime day numbers
        function isPrimeDate( date: Date ) {
            return [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 ].includes(
                date.getDate()
            );
        },
    ]} />;
With Selected Date And Month story ok
const WithSelectedDateAndMonth = () => <DateCalendar
    onMonthChange={fn()}
    onSelect={fn()}
    defaultSelected={firstDayOfNextMonth}
    defaultMonth={firstDayOfNextMonth} />;
With Outside Days story ok
Shows days from adjacent months in the grid. Outside days use a lighter style and are still interactive. Use `fixedWeeks` to keep the grid height constant.
const WithOutsideDays = () => <DateCalendar onMonthChange={fn()} onSelect={fn()} showOutsideDays fixedWeeks />;
With Time Zone story ok
When working with time zones, use the `TZDate` object exported by this package instead of the native `Date` object.
const WithTimeZone = () => {
    const [ selected, setSelected ] = useState< TZDate | null >( null );

    useEffect( () => {
        setSelected(
            // Select one week from today every time the time zone changes.
            new TZDate(
                new Date().setDate( new Date().getDate() + 7 ),
                args.timeZone
            )
        );
    }, [ args.timeZone ] );

    return (
        <>
            <DateCalendar
                onMonthChange={fn()}
                timeZone="Pacific/Auckland"
                selected={ selected }
                onSelect={ ( selectedDate, ...rest ) => {
                    setSelected(
                        selectedDate
                            ? new TZDate( selectedDate, args.timeZone )
                            : null
                    );
                    args.onSelect?.( selectedDate, ...rest );
                } }
                disabled={ [
                    {
                        // Disable any date before today
                        before: new TZDate( new Date(), args.timeZone ),
                    },
                ] } />
            <p>Calendar set to { args.timeZone ?? 'current' }timezone,
                                    disabling selection for all dates before today, and starting
                                    with a default date of 1 week from today.
                                </p>
        </>
    );
};

DateFormatPicker

blockeditor-dateformatpicker · ../packages/block-editor/src/components/date-format-picker/stories/index.story.jsx
The `DateFormatPicker` component renders controls that let the user choose a _date format_. That is, how they want their dates to be formatted.
see: https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/date-format-picker/README.md param: {Object} props param: {string|null} props.format The selected date format. If `null`, _Default_ is selected.param: {string} props.defaultFormat The date format that will be used if the user selects 'Default'.param: {Function} props.onChange Called when a selection is made. If `null`, _Default_ is selected.
Imports
import { DateFormatPicker } from "@wordpress/block-editor";
Default story ok
const Default = () => {
    const [ format, setFormat ] = useState();

    return (
        <DateFormatPicker
            defaultFormat="M j, Y"
            onChange={ ( ...changeArgs ) => {
                onChange( ...changeArgs );
                setFormat( ...changeArgs );
            } }
            format={ format } />
    );
};

DatePicker

components-datepicker · ../packages/components/src/date-time/stories/date.story.tsx
DatePicker is a React component that renders a calendar for date selection. ```jsx import { DatePicker } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyDatePicker = () => { const [ date, setDate ] = useState( new Date() ); return ( <DatePicker currentDate={ date } onChange={ ( newDate ) => setDate( newDate ) } /> ); }; ```
Prop types 6 prop types
Component: ../packages/components/src/date-time/date/index.tsx::DatePicker
Props:
/**
 * The current date and time at initialization. Optionally pass in a `null`
 * value to specify no date is currently selected.
 */
currentDate?: Date | string | number | null

/**
 * List of events to show in the date picker. Each event will appear as a
 * dot on the day of the event.
 */
events?: DatePickerEvent[] = []

/**
 * A callback function which receives a Date object representing a day as an
 * argument, and should return a Boolean to signify if the day is valid or
 * not.
 */
isInvalidDate?: ( date: Date ) => boolean

/**
 * The function called when a new date has been selected. It is passed the
 * date as an argument.
 */
onChange?: ( date: string ) => void

/**
 * A callback invoked when selecting the previous/next month in the date
 * picker. The callback receives the new month date in the ISO format as an
 * argument.
 */
onMonthPreviewed?: ( date: string ) => void

/**
 * The day that the week should start on. 0 for Sunday, 1 for Monday, etc.
 * 
 * @default 0
 */
startOfWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6 = 0
Imports
import { DatePicker } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ date, setDate ] = useState( currentDate );
    useEffect( () => {
		setDate( currentDate );
	}, [ currentDate ] );

    return (
        <DatePicker
            currentDate={ date }
            onChange={ ( newDate ) => {
				setDate( newDate );
				onChange?.( newDate );
			} } />
    );
};
With Events story ok
const WithEvents = () => {
    const [ date, setDate ] = useState( currentDate );
    useEffect( () => {
		setDate( currentDate );
	}, [ currentDate ] );

    return (
        <DatePicker
            events={[
                { date: daysFromNow( 2 ) },
                { date: daysFromNow( 4 ) },
                { date: daysFromNow( 6 ) },
                { date: daysFromNow( 8 ) },
            ]}
            currentDate={ date }
            onChange={ ( newDate ) => {
				setDate( newDate );
				onChange?.( newDate );
			} } />
    );
};
With Invalid Dates story ok
const WithInvalidDates = () => {
    const [ date, setDate ] = useState( currentDate );
    useEffect( () => {
		setDate( currentDate );
	}, [ currentDate ] );

    return (
        <DatePicker
            isInvalidDate={isWeekend}
            currentDate={ date }
            onChange={ ( newDate ) => {
				setDate( newDate );
				onChange?.( newDate );
			} } />
    );
};

DateRangeCalendar

components-selection-input-time-date-daterangecalendar · ../packages/components/src/calendar/stories/date-range-calendar.story.tsx
`DateRangeCalendar` is a React component that provides a customizable calendar interface for **date range** selection. The component is built with accessibility in mind and follows ARIA best practices for calendar widgets. It provides keyboard navigation, screen reader support, and customizable labels for internationalization.
Prop types 23 prop types
Component: ../packages/components/src/calendar/date-range-calendar/index.tsx::DateRangeCalendar
Props:
/**
 * Focus the first selected day (if set) or today's date (if not disabled).
 * 
 * Use this prop when you need to focus the calendar after a user action
 * (e.g. opening the dialog with the calendar).
 */
autoFocus?: boolean

/**
 * The initial month to show in the calendar view (uncontrolled).
 * @default The current month
 */
defaultMonth?: Date

/**
 * The default selected range (for uncontrolled usage).
 */
defaultSelected?: {
	from: Date | undefined;
	to?: Date | undefined;
}

/**
 * Specify which days are disabled. Using `true` will disable all dates.
 */
disabled?: Matcher | Matcher[] | undefined

/**
 * Disable the navigation buttons.
 */
disableNavigation?: boolean

/**
 * The latest month to end the month navigation.
 */
endMonth?: Date

/**
 * When `true`, the range will reset when including a disabled day.
 */
excludeDisabled?: boolean

/**
 * When `true`, the calendar always shows a fixed number of weeks (e.g. 6)
 * so the grid height does not change between months.
 * @default false
 */
fixedWeeks?: boolean

/**
 * Use custom labels, useful for translating the component.
 * 
 * For a correct localized experience, consumers should make sure the locale
 * used for the translated labels and `locale` prop are consistent.
 */
labels?: {
	/**
	 * The label for the navigation toolbar.
	 * @default ""
	 */
	labelNav?: () => string;
	/**
	 * The label for the month grid.
	 * @default "LLLL y" (e.g. "November 2022")
	 */
	labelGrid?: ( date: Date ) => string;
	/**
	 * The label for the gridcell, when the calendar is not interactive.
	 * @default The formatted date.
	 */
	labelGridcell?: ( date: Date, modifiers?: Modifiers ) => string;
	/**
	 * The label for the "next month" button.
	 * @default "Go to the Next Month"
	 */
	labelNext?: ( month: Date | undefined ) => string;
	/**
	 * The label for the "previous month" button.
	 * @default "Go to the Previous Month"
	 */
	labelPrevious?: ( month: Date | undefined ) => string;
	/**
	 * The label for the day button.
	 * @default The formatted date.
	 */
	labelDayButton?: ( date: Date, modifiers?: Modifiers ) => string;
	/**
	 * The label for the weekday.
	 * @default ( date: Date ) => "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" | "Sunday"
	 */
	labelWeekday?: ( date: Date ) => string;
}

/**
 * The locale object used to localize dates. Pass a locale from
 * `@date-fns/locale` to localize the calendar.
 * 
 * For a correct localized experience, consumers should make sure the locale
 * used for the translated labels and `locale` prop are consistent.
 * @see https://github.com/date-fns/date-fns/tree/main/src/locale for a list of the supported locales
 * @default The `enUS` locale from `@date-fns/locale`
 */
locale?: Locale = enUS

/**
 * The maximum number of nights to include in the range.
 */
max?: number

/**
 * The minimum number of nights to include in the range.
 */
min?: number

/**
 * The month displayed in the calendar view (controlled). Use together with
 * `onMonthChange` to change the month programmatically.
 */
month?: Date

/**
 * The number of months displayed at once.
 * @default 1
 */
numberOfMonths?: number = 1

/**
 * Event fired when the user navigates between months.
 */
onMonthChange?: ( month: Date ) => void

/**
 * Event handler when the selection changes.
 */
onSelect?: (
	selected: T,
	triggerDate: Date,
	modifiers: Modifiers,
	e: React.MouseEvent | React.KeyboardEvent
) => void

/**
 * Whether the selection is required.
 * When `true`, there always needs to be a date selected.
 * @default false
 */
required?: boolean

/**
 * The role attribute to add to the container element.
 * @default 'application'
 */
role?: 'application' | 'dialog' | undefined

/**
 * The selected range.
 */
selected?: DateRange | undefined | null

/**
 * When `true`, days from adjacent months are shown in the grid and receive
 * the `outside` modifier and the class.
 * @default false
 */
showOutsideDays?: boolean

/**
 * The earliest month to start the month navigation.
 */
startMonth?: Date

/**
 * The time zone (IANA or UTC offset) to use in the calendar.
 * 
 * See
 * [Wikipedia](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
 * for the possible values.
 * 
 * When working with time zones, use the `TZDate` object exported by this
 * package instead of the native `Date` object.
 * @example
 *   import { DateCalendar, TZDate } from "@wordpress/components";
 * 
 *   export function WithTimeZone() {
 *     const timeZone = "America/New_York";
 *     const [ selected, setSelected ] = useState< Date | undefined >(
 *       new TZDate( 2024, 12, 10, timeZone ) // Use `TZDate` instead of `Date`
 *     );
 *     return (
 *       <DateCalendar
 *         timeZone={ timeZone }
 *         selected={ selected }
 *         onSelect={ setSelected }
 *     />
 *   );
 * }
 */
timeZone?: string

/**
 * The index of the first day of the week (0 - Sunday). Overrides the locale's
 * one.
 * @default Based on the `locale` prop
 */
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | undefined
Imports
import { DateRangeCalendar } from "@wordpress/components";
Default story ok
const Default = () => <DateRangeCalendar onMonthChange={fn()} onSelect={fn()} />;
Disabled Dates story ok
const DisabledDates = () => <DateRangeCalendar
    onMonthChange={fn()}
    onSelect={fn()}
    disabled={[
        // Disable tomorrow (single date)
        new Date( new Date().setDate( new Date().getDate() + 1 ) ),
        // Disable all dates after Feb 1st of next year
        { after: new Date( new Date().getFullYear() + 1, 1, 1 ) },
        // Disable all dates before Dec 1st of last year
        { before: new Date( new Date().getFullYear() - 1, 11, 1 ) },
        // Disable all dates between 12th and 14th of August of this year
        {
            after: new Date( new Date().getFullYear(), 7, 11 ),
            before: new Date( new Date().getFullYear(), 7, 15 ),
        },
        // Disable all dates between 21st and 26th of October of this year
        {
            from: new Date( new Date().getFullYear(), 9, 21 ),
            to: new Date( new Date().getFullYear(), 9, 26 ),
        },
        // Disable all Wednesdays
        { dayOfWeek: 3 },
        // Disable all prime day numbers
        function isPrimeDate( date: Date ) {
            return [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 ].includes(
                date.getDate()
            );
        },
    ]} />;
With Selected Range And Month story ok
const WithSelectedRangeAndMonth = () => <DateRangeCalendar
    onMonthChange={fn()}
    onSelect={fn()}
    defaultSelected={{
        from: firstDayOfNextMonth,
        to: fourthDayOfNextMonth,
    }}
    defaultMonth={firstDayOfNextMonth} />;
With Outside Days story ok
Shows days from adjacent months in the grid. Outside days use a lighter style and are still interactive. Use `fixedWeeks` to keep the grid height constant.
const WithOutsideDays = () => <DateRangeCalendar onMonthChange={fn()} onSelect={fn()} showOutsideDays fixedWeeks />;
With Time Zone story ok
When working with time zones, use the `TZDate` object exported by this package instead of the native `Date` object.
const WithTimeZone = () => {
    const [ range, setRange ] = useState< typeof args.selected | null >(
        null
    );

    useEffect( () => {
        setRange(
            // Select from one week from today to two weeks from today
            // every time the timezone changes.
            {
                from: new TZDate(
                    new Date().setDate( new Date().getDate() + 7 ),
                    args.timeZone
                ),
                to: new TZDate(
                    new Date().setDate( new Date().getDate() + 14 ),
                    args.timeZone
                ),
            }
        );
    }, [ args.timeZone ] );

    return (
        <>
            <DateRangeCalendar
                onMonthChange={fn()}
                timeZone="Pacific/Auckland"
                selected={ range }
                onSelect={ ( selectedDate, ...rest ) => {
                    setRange(
                        // Set controlled state to null if there's no selection
                        ! selectedDate ||
                            ( selectedDate.from === undefined &&
                                selectedDate.to === undefined )
                            ? null
                            : selectedDate
                    );
                    args.onSelect?.( selectedDate, ...rest );
                } }
                disabled={ [
                    {
                        // Disable any date before today
                        before: new TZDate( new Date(), args.timeZone ),
                    },
                ] } />
            <p>Calendar set to { args.timeZone ?? 'current' }timezone,
                                    disabling selection for all dates before today, and starting
                                    with a default date range of 1 week from today to 2 weeks
                                    from today.
                                </p>
        </>
    );
};

DateTimePicker

components-datetimepicker · ../packages/components/src/date-time/stories/date-time.story.tsx
DateTimePicker is a React component that renders a calendar and clock for date and time selection. The calendar and clock components can be accessed individually using the `DatePicker` and `TimePicker` components respectively. ```jsx import { DateTimePicker } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyDateTimePicker = () => { const [ date, setDate ] = useState( new Date() ); return ( <DateTimePicker currentDate={ date } onChange={ ( newDate ) => setDate( newDate ) } is12Hour /> ); }; ```
Prop types 2 prop types
Component: ../packages/components/src/date-time/date-time/index.tsx::DateTimePicker
Props:
/**
 * The function called when a new date or time has been selected. It is
 * passed the date and time as an argument.
 */
onChange?: ( date: string | null ) => void

onMonthPreviewed?: any = () => {}
Imports
import { DateTimePicker } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ date, setDate ] = useState( currentDate );
    useEffect( () => {
		setDate( currentDate );
	}, [ currentDate ] );

    return (
        <DateTimePicker
            currentDate={ date }
            onChange={ ( newDate ) => {
				setDate( newDate );
				onChange?.( newDate );
			} } />
    );
};
With Events story ok
const WithEvents = () => {
    const [ date, setDate ] = useState( currentDate );
    useEffect( () => {
		setDate( currentDate );
	}, [ currentDate ] );

    return (
        <DateTimePicker
            events={[
                { date: daysFromNow( 2 ) },
                { date: daysFromNow( 4 ) },
                { date: daysFromNow( 6 ) },
                { date: daysFromNow( 8 ) },
            ]}
            currentDate={ date }
            onChange={ ( newDate ) => {
				setDate( newDate );
				onChange?.( newDate );
			} } />
    );
};
With Invalid Dates story ok
const WithInvalidDates = () => {
    const [ date, setDate ] = useState( currentDate );
    useEffect( () => {
		setDate( currentDate );
	}, [ currentDate ] );

    return (
        <DateTimePicker
            isInvalidDate={isWeekend}
            currentDate={ date }
            onChange={ ( newDate ) => {
				setDate( newDate );
				onChange?.( newDate );
			} } />
    );
};

Dialog.Root

design-system-components-dialog · ../packages/ui/src/dialog/stories/index.story.tsx
Groups the dialog trigger and popup. `Dialog` is a collection of React components that combine to render an ARIA-compliant dialog pattern.
Prop types 1 prop type
Component: ../packages/ui/src/dialog/root.tsx::Root
Props:
/**
 * The content to be rendered inside the component.
 */
children?: ReactNode
Imports
import { Action, CloseIcon, Footer, Header, Popup, Root, Title, Trigger } from "@wordpress/ui";
Default story ok
An informational dialog with a close icon, where there is no ambiguity on what happens when clicking the close icon.
const _Default = () => <Dialog.Root>(<>
        <Dialog.Trigger>Open Dialog</Dialog.Trigger>
        <Dialog.Popup>
            <Dialog.Header>
                <Dialog.Title>Welcome</Dialog.Title>
                <Dialog.CloseIcon />
            </Dialog.Header>
            <p>
                This dialog demonstrates best practices for
                informational dialogs. It includes a close icon because
                dismissing it is safe and expected.
            </p>
            <Dialog.Footer>
                <Dialog.Action>Got it</Dialog.Action>
            </Dialog.Footer>
        </Dialog.Popup>
    </>)</Dialog.Root>;
All Sizes story ok
const AllSizes = () => <Dialog.Root><SizePlaygroundContent /></Dialog.Root>;
With Custom z-index story ok
Popovers in Gutenberg are managed with explicit z-index values, which can create situations where a dialog renders below another popover, when you want it to be rendered above. The `--wp-ui-dialog-z-index` CSS variable controls the z-index of both the backdrop and the popup. It can be overridden globally by setting the variable on `:root` or `body`. (This story doesn't actually demonstrate the feature because it requires a global CSS rule.)
const WithCustomZIndex = () => <Dialog.Root />;

DimensionControl

blockeditor-dimensioncontrol · ../packages/block-editor/src/components/dimension-control/stories/index.story.jsx
DimensionControl renders a linked unit control and range control for adjusting dimensions of a block.
see: https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/dimension-control/README.md param: {Object} props param: {?string} props.label A label for the control.param: {( value: string ) => void} props.onChange Called when the dimension value changes.param: {string} props.value The current dimension value.param: {?Object} props.dimensionSizes Optional dimension size presets. Falls back to settings from the store.return: {Component} The component to be rendered.
Prop types 1 prop type
Component: ../packages/block-editor/src/components/dimension-control/index.js::default
Props:
label?: any = __( 'Dimension' )
Imports
import { DimensionControl } from "@wordpress/block-editor";
Default story ok
const Default = ( props ) => {
	const [ value, setValue ] = useState();
	return (
		<DimensionControl onChange={ setValue } value={ value } { ...props } />
	);
};
With Custom Label story ok
const WithCustomLabel = ( props ) => {
	const [ value, setValue ] = useState();
	return (
		<DimensionControl onChange={ setValue } value={ value } { ...props } />
	);
};
With Width Label story ok
const WithWidthLabel = ( props ) => {
	const [ value, setValue ] = useState();
	return (
		<DimensionControl onChange={ setValue } value={ value } { ...props } />
	);
};
With Min Height Label story ok
const WithMinHeightLabel = ( props ) => {
	const [ value, setValue ] = useState();
	return (
		<DimensionControl onChange={ setValue } value={ value } { ...props } />
	);
};
With Presets story ok
const WithPresets = ( props ) => {
	const [ value, setValue ] = useState();
	return (
		<DimensionControl onChange={ setValue } value={ value } { ...props } />
	);
};
With Initial Value story ok
const WithInitialValue = ( props ) => {
	const [ value, setValue ] = useState();
	return (
		<DimensionControl onChange={ setValue } value={ value } { ...props } />
	);
};
With Preset Value story ok
const WithPresetValue = ( props ) => {
	const [ value, setValue ] = useState( 'var:preset|dimension|medium' );
	return (
		<DimensionControl onChange={ setValue } value={ value } { ...props } />
	);
};

DimensionsTool

blockeditor-dimensionstool-dimensionstool · ../packages/block-editor/src/components/dimensions-tool/stories/index.story.jsx
Component that renders controls to edit the dimensions of an image or container.
param: {DimensionsControlsProps} props The component props.return: {Element} The dimensions controls.
Prop types 5 prop types
Component: ../packages/block-editor/src/components/dimensions-tool/index.js::default
Props:
defaultAspectRatio?: any = 'auto'

defaultScale?: any = 'fill'

onChange?: any = () => {}

tools?: any = [ 'aspectRatio', 'widthHeight', 'scale' ]

value?: any = {}
Imports
import { DimensionsTool } from "@wordpress/block-editor";
import { Panel, __experimentalToolsPanel as ToolsPanel } from "@wordpress/components";
Default story ok
const Default = ( { panelId, onChange, ...props } ) => {
	const [ value, setValue ] = useState( EMPTY_OBJECT );
	const resetAll = () => {
		setValue( EMPTY_OBJECT );
		onChange( EMPTY_OBJECT );
	};
	return (
		<Panel>
			<ToolsPanel
				label="Dimensions"
				panelId={ panelId }
				resetAll={ resetAll }
			>
				<DimensionsTool
					panelId={ panelId }
					onChange={ ( nextValue ) => {
						setValue( nextValue );
						onChange( nextValue );
					} }
					value={ value }
					{ ...props }
				/>
			</ToolsPanel>
		</Panel>
	);
};

Disabled

components-disabled · ../packages/components/src/disabled/stories/index.story.tsx
`Disabled` is a component which disables descendant tabbable elements and prevents pointer interaction. _Note: this component may not behave as expected in browsers that don't support the `inert` HTML attribute. We recommend adding the official WICG polyfill when using this component in your project._
see: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/inert ```jsx import { Button, Disabled, TextControl } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyDisabled = () => { const [ isDisabled, setIsDisabled ] = useState( true ); let input = ( <TextControl __next40pxDefaultSize label="Input" onChange={ () => {} } /> ); if ( isDisabled ) { input = <Disabled>{ input }</Disabled>; } const toggleDisabled = () => { setIsDisabled( ( state ) => ! state ); }; return ( <div> { input } <Button variant="primary" onClick={ toggleDisabled }> Toggle Disabled </Button> </div> ); }; ```
Prop types 1 prop type
Component: ../packages/components/src/disabled/index.tsx::default
Props:
isDisabled?: any = true
Imports
import { Disabled, SelectControl, TextareaControl, TextControl, VStack } from "@wordpress/components";
Default story ok
const Default = () => {
    return (
        <Disabled isDisabled>
            <Form />
        </Disabled>
    );
};
Content Editable story ok
const ContentEditable = () => {
    return (
        <Disabled isDisabled>
            <div contentEditable tabIndex={ 0 } suppressContentEditableWarning>contentEditable
                            </div>
        </Disabled>
    );
};

Divider

components-divider · ../packages/components/src/divider/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Divider, Flex, Text } from "@wordpress/components";
Horizontal story ok
const Horizontal = () => <div>
    <Text>Some text before the divider</Text>
    <Divider margin="2" />
    <Text>Some text after the divider</Text>
</div>;
Vertical story ok
const Vertical = () => <div>
    <Text>Some text before the divider</Text>
    <Divider orientation="vertical" />
    <Text>Some text after the divider</Text>
</div>;
In Flex Container story ok
const InFlexContainer = () => {
    return (
        <Flex align="stretch">
            <Text>Some text before the divider Some text before the divider Some
                                text before the divider Some text before the divider Some text
                                before the divider Some text before the divider Some text before
                                the divider
                            </Text>
            <Divider />
            <Text>Some text after the divider Some text after the divider Some
                                text after the divider
                            </Text>
        </Flex>
    );
};

Draggable

components-draggable · ../packages/components/src/draggable/stories/index.story.tsx
`Draggable` is a Component that provides a way to set up a cross-browser (including IE) customizable drag image and the transfer data for the drag event. It decouples the drag handle and the element to drag: use it by wrapping the component that will become the drag handle and providing the DOM ID of the element to drag. Note that the drag handle needs to declare the `draggable="true"` property and bind the `Draggable`s `onDraggableStart` and `onDraggableEnd` event handlers to its own `onDragStart` and `onDragEnd` respectively. `Draggable` takes care of the logic to setup the drag image and the transfer data, but is not concerned with creating an actual DOM element that is draggable. ```jsx import { Draggable, Panel, PanelBody } from '@wordpress/components'; import { Icon, more } from '@wordpress/icons'; const MyDraggable = () => ( <div id="draggable-panel"> <Panel header="Draggable panel"> <PanelBody> <Draggable elementId="draggable-panel" transferData={ {} }> { ( { onDraggableStart, onDraggableEnd } ) => ( <div className="example-drag-handle" draggable onDragStart={ onDraggableStart } onDragEnd={ onDraggableEnd } > <Icon icon={ more } /> </div> ) } </Draggable> </PanelBody> </Panel> </div> ); ```
Prop types 10 prop types
Component: ../packages/components/src/draggable/index.tsx::Draggable
Props:
/**
 * Component to show when dragging.
 */
__experimentalDragComponent?: ReactNode

/**
 * The transfer data type to set.
 * 
 * @default 'text'
 */
__experimentalTransferDataType?: string = 'text'

/**
 * Whether to append the cloned element to the `ownerDocument` body.
 * By default, elements sourced by id are appended to the element's wrapper.
 * 
 * @default false
 */
appendToOwnerDocument?: boolean = false

/**
 * Children.
 */
children: ( props: {
	/**
	 * `onDragStart` handler.
	 */
	onDraggableStart: ( event: DragEvent ) => void;
	/**
	 * `onDragEnd` handler.
	 */
	onDraggableEnd: ( event: DragEvent ) => void;
} ) => React.JSX.Element | null

/**
 * Classname for the cloned element.
 */
cloneClassname?: string

/**
 * The HTML id of the element to clone on drag
 */
elementId: string

/**
 * A function called when dragging ends. This callback receives the `event`
 * object from the `dragend` event as its first parameter.
 */
onDragEnd?: ( event: DragEvent ) => void

/**
 * A function called when the element being dragged is dragged over a valid
 * drop target. This callback receives the `event` object from the
 * `dragover` event as its first parameter.
 */
onDragOver?: ( event: DragEvent ) => void

/**
 * A function called when dragging starts. This callback receives the
 * `event` object from the `dragstart` event as its first parameter.
 */
onDragStart?: ( event: DragEvent ) => void

/**
 * Arbitrary data object attached to the drag and drop event.
 */
transferData: unknown
Imports
import { Draggable } from "@wordpress/components";
import { Icon } from "@wordpress/icons";
Default story ok
const Default = () => {
    const [ isDragging, setDragging ] = useState( false );
    const instanceId = useInstanceId( DefaultTemplate );

    return (
        <div>
            <p
                style={ {
					padding: '1em',
					position: 'relative',
					zIndex: 1000,
					backgroundColor: 'whitesmoke',
				} }>Is Dragging? { isDragging ? 'Yes' : 'No!' }
            </p>
            <div
                style={ {
					zIndex: 100,
					position: 'relative',
				} }>
                <div
                    id={ `draggable-example-box-${ instanceId }` }
                    style={ {
						display: 'inline-flex',
						position: 'relative',
					} }>
                    <Draggable
                        onDragStart={fn()}
                        onDragEnd={fn()}
                        onDragOver={fn()}
                        elementId={ `draggable-example-box-${ instanceId }` }>
                        { ( { onDraggableStart, onDraggableEnd } ) => {
							const handleOnDragStart = ( event: DragEvent ) => {
								setDragging( true );
								onDraggableStart( event );
							};
							const handleOnDragEnd = ( event: DragEvent ) => {
								setDragging( false );
								onDraggableEnd( event );
							};

							return (
								<div
									onDragStart={ handleOnDragStart }
									onDragEnd={ handleOnDragEnd }
									draggable
									style={ {
										alignItems: 'center',
										display: 'flex',
										justifyContent: 'center',
										width: 100,
										height: 100,
										background: '#ddd',
									} }
								>
									<Icon icon={ more } />
								</div>
							);
						} }
                    </Draggable>
                </div>
            </div>
        </div>
    );
};
Append Element To Owner Document story ok
`appendToOwnerDocument` is used to append the element being dragged to the body of the owner document. This is useful when the element being dragged should not receive styles from its parent. For example, when the element's parent sets a `z-index` value that would cause the dragged element to be rendered behind other elements.
const AppendElementToOwnerDocument = () => {
    const [ isDragging, setDragging ] = useState( false );
    const instanceId = useInstanceId( DefaultTemplate );

    return (
        <div>
            <p
                style={ {
					padding: '1em',
					position: 'relative',
					zIndex: 1000,
					backgroundColor: 'whitesmoke',
				} }>Is Dragging? { isDragging ? 'Yes' : 'No!' }
            </p>
            <div
                style={ {
					zIndex: 100,
					position: 'relative',
				} }>
                <div
                    id={ `draggable-example-box-${ instanceId }` }
                    style={ {
						display: 'inline-flex',
						position: 'relative',
					} }>
                    <Draggable
                        onDragStart={fn()}
                        onDragEnd={fn()}
                        onDragOver={fn()}
                        appendToOwnerDocument
                        elementId={ `draggable-example-box-${ instanceId }` }>
                        { ( { onDraggableStart, onDraggableEnd } ) => {
							const handleOnDragStart = ( event: DragEvent ) => {
								setDragging( true );
								onDraggableStart( event );
							};
							const handleOnDragEnd = ( event: DragEvent ) => {
								setDragging( false );
								onDraggableEnd( event );
							};

							return (
								<div
									onDragStart={ handleOnDragStart }
									onDragEnd={ handleOnDragEnd }
									draggable
									style={ {
										alignItems: 'center',
										display: 'flex',
										justifyContent: 'center',
										width: 100,
										height: 100,
										background: '#ddd',
									} }
								>
									<Icon icon={ more } />
								</div>
							);
						} }
                    </Draggable>
                </div>
            </div>
        </div>
    );
};

Dropdown

components-dropdown · ../packages/components/src/dropdown/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 14 prop types
Component: ../packages/components/src/dropdown/index.tsx
Props:
/**
 * The className of the global container.
 */
className?: string

/**
 * If you want to target the dropdown menu for styling purposes,
 * you need to provide a contentClassName because it's not being rendered
 * as a child of the container node.
 */
contentClassName?: string

/**
 * The open state of the dropdown when initially rendered.
 * Use when you do not need to control its open state. It will be overridden
 * by the `open` prop if it is specified on the component's first render.
 */
defaultOpen?: boolean

/**
 * Opt-in prop to show popovers fullscreen on mobile.
 * 
 * @default false
 */
expandOnMobile?: boolean

/**
 * Determines focus behavior when the dialog mounts.
 * 
 * - `"firstElement"` focuses the first tabbable element within.
 * - `"firstInputElement"` focuses the first value control within.
 * - `true` focuses the element itself.
 * - `false` does nothing and _should not be used unless an accessible
 *    substitute behavior is implemented_.
 * 
 * @default 'firstElement'
 */
focusOnMount?: useFocusOnMount.Mode

/**
 * Set this to customize the text that is shown in the dropdown's header
 * when it is fullscreen on mobile.
 */
headerTitle?: string

/**
 * A callback invoked when the popover should be closed.
 */
onClose?: () => void

/**
 * A callback invoked when the state of the dropdown changes
 * from open to closed and vice versa.
 */
onToggle?: ( willOpen: boolean ) => void

/**
 * The controlled open state of the dropdown.
 * Must be used in conjunction with `onToggle`.
 */
open?: boolean

/**
 * Properties of popoverProps object will be passed as props
 * to the Popover component.
 * Use this object to access properties/features
 * of the Popover component that are not already exposed
 * in the Dropdown component,
 * e.g.: the ability to have the popover without an arrow.
 */
popoverProps?: Omit<
	ComponentPropsWithoutRef< typeof Popover >,
	'children'
>

/**
 * Legacy way to specify the popover's position with respect to its anchor.
 * For details about the possible values, see the `Popover` component's docs.
 * _Note: this prop is deprecated. Use the `popoverProps.placement` prop
 * instead._
 * 
 * @deprecated
 */
position?: PopoverProps[ 'position' ]

/**
 * A callback invoked to render the content of the dropdown menu.
 * Its first argument is the same as the renderToggle prop.
 */
renderContent: ( props: CallbackProps ) => ReactNode

/**
 * A callback invoked to render the Dropdown Toggle Button.
 * 
 * The first argument of the callback is an object
 * containing the following properties:
 * 
 * - isOpen: whether the dropdown menu is opened or not
 * - onToggle: A function switching the dropdown menu's state
 * from open to closed and vice versa
 * - onClose: A function that closes the menu if invoked
 */
renderToggle: ( props: CallbackProps ) => ReactNode

/**
 * The style of the global container.
 */
style?: CSSProperties
Imports
import { Button, Dropdown, DropdownContentWrapper, MenuGroup, MenuItem } from "@wordpress/components";
Default story ok
const Default = () => <Dropdown
    onClose={fn()}
    onToggle={fn()}
    renderToggle={( { isOpen, onToggle } ) => (
        <Button
            __next40pxDefaultSize
            onClick={ onToggle }
            aria-expanded={ isOpen }
            variant="primary"
        >
            Open dropdown
        </Button>
    )}
    renderContent={() => <div>This is the dropdown content.</div>} />;
With More Padding story ok
To apply more padding to the dropdown content, use the provided `<DropdownContentWrapper>` convenience wrapper. A `paddingSize` of `"medium"` is suitable for relatively larger dropdowns (default is `"small"`).
const WithMorePadding = () => <Dropdown
    onClose={fn()}
    onToggle={fn()}
    renderContent={() => (
        <DropdownContentWrapper paddingSize="medium">
            { /* eslint-disable react/no-unescaped-entities */ }
            Content wrapped with <code>paddingSize="medium"</code>.
            { /* eslint-enable react/no-unescaped-entities */ }
        </DropdownContentWrapper>
    )} />;
With No Padding story ok
The `<DropdownContentWrapper>` convenience wrapper can also be used to remove padding entirely, with a `paddingSize` of `"none"`. This can also serve as a clean foundation to add arbitrary paddings, for example when child components already have padding on their own.
const WithNoPadding = () => <Dropdown
    onClose={fn()}
    onToggle={fn()}
    renderContent={() => (
        <DropdownContentWrapper paddingSize="none">
            { /* eslint-disable react/no-unescaped-entities */ }
            Content wrapped with <code>paddingSize="none"</code>.
            { /* eslint-enable react/no-unescaped-entities */ }
        </DropdownContentWrapper>
    )} />;
With Menu Items story ok
const WithMenuItems = () => <Dropdown
    onClose={fn()}
    onToggle={fn()}
    renderContent={() => (
        <>
            <MenuItem>Standalone Item</MenuItem>
            <MenuGroup label="Group 1">
                <MenuItem>Item 1</MenuItem>
                <MenuItem>Item 2</MenuItem>
            </MenuGroup>
            <MenuGroup label="Group 2">
                <MenuItem>Item 1</MenuItem>
                <MenuItem>Item 2</MenuItem>
            </MenuGroup>
        </>
    )} />;

DropdownMenu

components-dropdownmenu · ../packages/components/src/dropdown-menu/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 14 prop types
Component: ../packages/components/src/dropdown-menu/index.tsx
Props:
/**
 * A [function render prop](https://reactjs.org/docs/render-props.html#using-props-other-than-render)
 * which should return an element or elements valid for use in a DropdownMenu:
 * `MenuItem`, `MenuItemsChoice`, or `MenuGroup`. Its first argument is a
 * props object including the same values as given to a `Dropdown`'s
 * `renderContent` (`isOpen`, `onToggle`, `onClose`).
 * 
 * A valid DropdownMenu must specify a `controls` or `children` prop, or both.
 */
children?: ( callbackProps: DropdownCallbackProps ) => ReactNode

/**
 * A class name to apply to the dropdown menu's toggle element wrapper.
 */
className?: string

/**
 * An array or nested array of objects describing the options to be shown in
 * the expanded menu. Each object should include an `icon` Dashicon slug
 * string, a human-readable `title` string, `isDisabled` boolean flag, and
 * an `onClick` function callback to invoke when the option is selected.
 * 
 * A valid DropdownMenu must specify a `controls` or `children` prop, or both.
 */
controls?: DropdownOption[] | DropdownOption[][]

/**
 * The open state of the dropdown menu when initially rendered.
 * Use when you do not need to control its open state. It will be overridden
 * by the `open` prop if it is specified on the component's first render.
 */
defaultOpen?: boolean

/**
 * In some contexts, the arrow down key used to open the dropdown menu might
 * need to be disabled—for example when that key is used to perform another
 * action.
 * 
 * @default false
 */
disableOpenOnArrowDown?: boolean

/**
 * The icon to be shown in the collapsed menu button.
 * 
 * @default "menu"
 */
icon?: IconProps[ 'icon' ] | null

/**
 * A human-readable label to present as accessibility text on the focused
 * collapsed menu button.
 */
label: string

/**
 * Properties of `menuProps` object will be passed as props to the nested
 * `NavigableMenu` component in the `renderContent` implementation of the
 * `Dropdown` component used internally.
 * Use this object to modify props available for the `NavigableMenu`
 * component that are not already exposed in the `DropdownMenu` component,
 * e.g.: the orientation of the menu set with `orientation` prop.
 */
menuProps?: Omit< Partial< NavigableMenuProps >, 'children' >

/**
 * Whether or not `no-icons` should be added to the menu's `className`.
 */
noIcons?: boolean

/**
 * A callback invoked when the state of the dropdown menu changes
 * from open to closed and vice versa.
 */
onToggle?: ( willOpen: boolean ) => void

/**
 * The controlled open state of the dropdown menu.
 * Must be used in conjunction with `onToggle`.
 */
open?: boolean

/**
 * Properties of `popoverProps` object will be passed as props to the nested
 * `Popover` component.
 * Use this object to modify props available for the `Popover` component that
 * are not already exposed in the `DropdownMenu` component, e.g.: the
 * direction in which the popover should open relative to its parent node
 * set with `position` prop.
 */
popoverProps?: DropdownProps[ 'popoverProps' ]

/**
 * Text to display on the nested `Button` component in the `renderToggle`
 * implementation of the `Dropdown` component used internally.
 */
text?: string

/**
 * Properties of `toggleProps` object will be passed as props to the nested
 * `Button` component in the `renderToggle` implementation of the `Dropdown`
 * component used internally.
 * Use this object to modify props available for the `Button` component that
 * are not already exposed in the `DropdownMenu` component, e.g.: the tooltip
 * text displayed on hover set with `tooltip` prop.
 */
toggleProps?: Partial<
	Omit<
		WordPressComponentProps< ButtonAsButtonProps, 'button', false >,
		'label' | 'text'
	>
> & {
	as?: React.ElementType | keyof React.JSX.IntrinsicElements;
	'data-toolbar-item'?: boolean;
}
Imports
import { DropdownMenu, MenuGroup, MenuItem } from "@wordpress/components";
Default story ok
const Default = () => <DropdownMenu
    onToggle={fn()}
    label="Select a direction."
    icon={menu}
    controls={[
        {
            title: 'First Menu Item Label',
            icon: arrowUp,
            // eslint-disable-next-line no-console
            onClick: () => console.log( 'up!' ),
        },
        {
            title: 'Second Menu Item Label',
            icon: arrowDown,
            // eslint-disable-next-line no-console
            onClick: () => console.log( 'down!' ),
        },
    ]} />;
With Children story ok
const WithChildren = () => <DropdownMenu onToggle={fn()} label="Select a direction." icon={more}>{( { onClose } ) => (
        <>
            <MenuItem icon={ arrowUp } onClick={ onClose }>
                Standalone Item
            </MenuItem>
            <MenuGroup>
                <MenuItem icon={ arrowUp } onClick={ onClose }>
                    Move Up
                </MenuItem>
                <MenuItem icon={ arrowDown } onClick={ onClose }>
                    Move Down
                </MenuItem>
            </MenuGroup>
            <MenuGroup>
                <MenuItem icon={ trash } onClick={ onClose }>
                    Remove
                </MenuItem>
            </MenuGroup>
        </>
    )}</DropdownMenu>;

DropZone

components-dropzone · ../packages/components/src/drop-zone/stories/index.story.tsx
`DropZone` is a component creating a drop zone area taking the full size of its parent element. It supports dropping files, HTML content or any other HTML drop event. ```jsx import { DropZone } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyDropZone = () => { const [ hasDropped, setHasDropped ] = useState( false ); return ( <div> { hasDropped ? 'Dropped!' : 'Drop something here' } <DropZone onFilesDrop={ () => setHasDropped( true ) } onHTMLDrop={ () => setHasDropped( true ) } onDrop={ () => setHasDropped( true ) } /> </div> ); } ```
Prop types 2 prop types
Component: ../packages/components/src/drop-zone/index.tsx::DropZoneComponent
Props:
icon?: any = jsx(SVG, { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx(Path, { d: "M18.5 15v3.5H13V6.7l4.5 4.1 1-1.1-6.2-5.8-5.8 5.8 1 1.1 4-4v11.7h-6V15H4v5h16v-5z" }) })

isEligible?: any = () => true
Imports
import { DropZone } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	return (
		<div
			style={ {
				background: 'lightgray',
				padding: 32,
				position: 'relative',
			} }
		>
			Drop something here
			<DropZone { ...props } />
		</div>
	);
};

DuotonePicker

components-duotonepicker · ../packages/components/src/duotone-picker/stories/duotone-picker.story.tsx
```jsx import { DuotonePicker, DuotoneSwatch } from '@wordpress/components'; import { useState } from '@wordpress/element'; const DUOTONE_PALETTE = [ { colors: [ '#8c00b7', '#fcff41' ], name: 'Purple and yellow', slug: 'purple-yellow' }, { colors: [ '#000097', '#ff4747' ], name: 'Blue and red', slug: 'blue-red' }, ]; const COLOR_PALETTE = [ { color: '#ff4747', name: 'Red', slug: 'red' }, { color: '#fcff41', name: 'Yellow', slug: 'yellow' }, { color: '#000097', name: 'Blue', slug: 'blue' }, { color: '#8c00b7', name: 'Purple', slug: 'purple' }, ]; const Example = () => { const [ duotone, setDuotone ] = useState( [ '#000000', '#ffffff' ] ); return ( <> <DuotonePicker duotonePalette={ DUOTONE_PALETTE } colorPalette={ COLOR_PALETTE } value={ duotone } onChange={ setDuotone } /> <DuotoneSwatch values={ duotone } /> </> ); }; ```
Prop types 10 prop types
Component: ../packages/components/src/duotone-picker/duotone-picker.tsx::default
Props:
/**
 * Whether the control should present as a set of buttons,
 * each with its own tab stop.
 * 
 * @default false
 */
asButtons?: boolean

/**
 * Whether there should be a button to clear the duotone value.
 * 
 * @default true
 */
clearable?: boolean = true

/**
 * Array of color presets of the form `{ color: '#000000', name: 'Black', slug: 'black' }`.
 */
colorPalette: Color[]

/**
 * Whether custom colors should be disabled.
 * 
 * @default false
 */
disableCustomColors?: boolean

/**
 * Whether custom duotone values should be disabled.
 * 
 * @default false
 */
disableCustomDuotone?: boolean

/**
 * Array of duotone presets of the form `{ colors: [ '#000000', '#ffffff' ], name: 'Grayscale', slug: 'grayscale' }`.
 */
duotonePalette: DuotoneColor[]

/**
 * Prevents keyboard interaction from wrapping around.
 * Only used when `asButtons` is not true.
 * 
 * @default true
 */
loop?: boolean

/**
 * Callback which is called when the duotone colors change.
 */
onChange: ( value: DuotonePickerProps[ 'value' ] | undefined ) => void

/**
 * Whether there should be an `unset` option.
 * 
 * @default true
 */
unsetable?: boolean = true

/**
 * An array of colors for the duotone effect.
 */
value?: string[] | 'unset'
Imports
import { DuotonePicker } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState< DuotonePickerProps[ 'value' ] >();

    return (
        <DuotonePicker
            colorPalette={COLOR_PALETTE}
            duotonePalette={DUOTONE_PALETTE}
            onChange={ ( ...changeArgs ) => {
				setValue( ...changeArgs );
				onChange( ...changeArgs );
			} }
            value={ value } />
    );
};

DuotoneSwatch

components-duotoneswatch · ../packages/components/src/duotone-picker/stories/duotone-swatch.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 1 prop type
Component: ../packages/components/src/duotone-picker/duotone-swatch.tsx::default
Props:
/**
 * An array of colors to show or `null` to show the placeholder swatch icon.
 */
values?: string[] | null
Imports
import { DuotoneSwatch } from "@wordpress/components";
Default story ok
const Default = () => {
    return <DuotoneSwatch values={[ '#000', '#fff' ]} />;
};
Single Color story ok
const SingleColor = () => {
    return <DuotoneSwatch values={[ 'pink' ]} />;
};
Null story ok
const Null = () => {
    return <DuotoneSwatch values={null} />;
};

Elevation

components-elevation · ../packages/components/src/elevation/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Elevation } from "@wordpress/components";
Default story ok
const Default = () => {
    return (
        <div
            style={ {
				width: 150,
				height: 150,
				position: 'relative',
			} }>
            <Elevation value={5} />
        </div>
    );
};
With Interactive story ok
Enable the `isInteractive` prop to automatically generate values for the hover/active/focus states.
const WithInteractive = () => {
    return (
        <button
            style={ {
				border: 0,
				background: 'transparent',
				width: 150,
				height: 150,
				position: 'relative',
			} }>Click me
                        <Elevation isInteractive />
        </button>
    );
};
With Custom Interactive story ok
You can also provide custom values for the hover/active/focus states instead of using the `isInteractive` prop.
const WithCustomInteractive = () => {
    return (
        <button
            style={ {
				border: 0,
				background: 'transparent',
				width: 150,
				height: 150,
				position: 'relative',
			} }>Click me
                        <Elevation hover={7} active={1} focus={10} />
        </button>
    );
};

EmptyState.Root

design-system-components-emptystate · ../packages/ui/src/empty-state/stories/index.story.tsx
A badge component for displaying labels with semantic intent.
Prop types 4 prop types
Component: ../packages/ui/src/badge/badge.tsx::Badge
Props:
/**
 * The text to display in the badge.
 */
children: string

/**
 * CSS class name to apply to the component.
 */
className?: string

/**
 * The semantic intent of the badge, communicating its meaning through color.
 * 
 * @default "none"
 */
intent?: | 'high'
| 'medium'
| 'low'
| 'stable'
| 'informational'
| 'draft'
| 'none' = 'none'

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: | ComponentRenderFn< HTMLAttributesWithRef >
| React.ReactElement< Record< string, unknown > >
Imports
import { Button, EmptyState } from "@wordpress/ui";
Default story ok
const Default = () => <EmptyState.Root>(<>
        <EmptyState.Icon icon={ search } />
        <EmptyState.Title>No results found</EmptyState.Title>
        <EmptyState.Description>
            Try adjusting your search or filter to find what you&apos;re
            looking for.
        </EmptyState.Description>
        <EmptyState.Actions>
            <Button variant="outline">Clear filters</Button>
            <Button>Add item</Button>
        </EmptyState.Actions>
    </>)</EmptyState.Root>;
With Custom Visual story ok
const WithCustomVisual = () => <EmptyState.Root>(<>
        <EmptyState.Visual>
            <svg
                width="50"
                height="50"
                viewBox="0 0 50 50"
                fill="none"
                xmlns="http://www.w3.org/2000/svg"
            >
                <circle cx="25" cy="25" r="25" fill="currentColor" />
            </svg>
        </EmptyState.Visual>
        <EmptyState.Title>All caught up!</EmptyState.Title>
        <EmptyState.Description>
            You&apos;ve completed all your tasks. Great work!
        </EmptyState.Description>
        <EmptyState.Actions>
            <Button>Create new task</Button>
        </EmptyState.Actions>
    </>)</EmptyState.Root>;

ExternalLink

components-externallink · ../packages/components/src/external-link/stories/index.story.tsx
Link to an external resource. ```jsx import { ExternalLink } from '@wordpress/components'; const MyExternalLink = () => ( <ExternalLink href="https://wordpress.org">WordPress.org</ExternalLink> ); ```
Imports
import { ExternalLink } from "@wordpress/components";
Default story ok
const Default = () => {
    return <ExternalLink href="https://wordpress.org">WordPress</ExternalLink>;
};

Field.Root

design-system-components-form-primitives-field · ../packages/ui/src/form/primitives/field/stories/index.story.tsx
A badge component for displaying labels with semantic intent.
Prop types 4 prop types
Component: ../packages/ui/src/badge/badge.tsx::Badge
Props:
/**
 * The text to display in the badge.
 */
children: string

/**
 * CSS class name to apply to the component.
 */
className?: string

/**
 * The semantic intent of the badge, communicating its meaning through color.
 * 
 * @default "none"
 */
intent?: | 'high'
| 'medium'
| 'low'
| 'stable'
| 'informational'
| 'draft'
| 'none' = 'none'

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: | ComponentRenderFn< HTMLAttributesWithRef >
| React.ReactElement< Record< string, unknown > >
Imports
import { Field } from "@wordpress/ui";
Default story ok
If your control component forwards refs, as well as the `aria-labelledby` and `aria-describedby` props to the actual underlying HTML element to be labeled, you can simply place your control in the `render` prop of `Field.Control`.
const Default = () => <Field.Root>(<>
        <Field.Label>Label</Field.Label>
        <Field.Control
            render={ <input type="text" placeholder="Placeholder" /> }
        />
        <Field.Description>
            The accessible description.
        </Field.Description>
    </>)</Field.Root>;
Using htmlFor story ok
If your control component does not forward refs, but does forward the `id` prop to the actual underlying HTML element to be labeled, use the `htmlFor` prop of the `Field.Label` component to associate the label with the control. This is preferred over `aria-labelledby` because it allows users to click the label to focus the control.
const UsingHtmlFor = () => {
    const controlId = useId();
    const descriptionId = useId();

    return (
        <Field.Root>
            <Field.Label htmlFor={ controlId }>Label</Field.Label>
            <MyNonRefForwardingControl
                placeholder="Placeholder"
                id={ controlId }
                aria-describedby={ descriptionId } />
            <Field.Description id={ descriptionId }>The accessible description.
                                </Field.Description>
        </Field.Root>
    );
};
Using aria-labelledby story ok
If your control component does not forward refs nor the `id` prop, but does forward the `aria-labelledby` prop to the actual underlying HTML element to be labeled, use the `id` prop of the `Field.Label` component to associate the label with the control.
const UsingAriaLabelledby = () => {
    const labelId = useId();
    const descriptionId = useId();

    return (
        <Field.Root>
            <Field.Label id={ labelId }>Label</Field.Label>
            <MyNonRefForwardingControl
                placeholder="Placeholder"
                aria-labelledby={ labelId }
                aria-describedby={ descriptionId } />
            <Field.Description id={ descriptionId }>The accessible description.
                                </Field.Description>{ ' ' }
        </Field.Root>
    );
};
Hidden Label story ok
When `hideFromVision` is set on `Field.Label`, the label is visually hidden but remains accessible to screen readers.
const HiddenLabel = () => <Field.Root>(<>
        <Field.Label hideFromVision>Label</Field.Label>
        <Field.Control
            render={ <input type="text" placeholder="Placeholder" /> }
        />
    </>)</Field.Root>;
With Details story ok
To add rich content (such as links) to the description, use `Field.Details`. Although this content is not associated with the field using direct semantics, it is made discoverable to screen reader users via a visually hidden description, alerting them to the presence of additional information below. If the content only includes plain text, use `Field.Description` instead, so the readout is not unnecessarily verbose for screen reader users.
const WithDetails = () => <Field.Root>(<>
        <Field.Label>Label</Field.Label>
        <Field.Control
            render={ <input type="text" placeholder="Placeholder" /> }
        />
        <Field.Details>{ DETAILS_EXAMPLE }</Field.Details>
    </>)</Field.Root>;

Fieldset.Root

design-system-components-form-primitives-fieldset · ../packages/ui/src/form/primitives/fieldset/stories/index.story.tsx
A badge component for displaying labels with semantic intent.
Prop types 4 prop types
Component: ../packages/ui/src/badge/badge.tsx::Badge
Props:
/**
 * The text to display in the badge.
 */
children: string

/**
 * CSS class name to apply to the component.
 */
className?: string

/**
 * The semantic intent of the badge, communicating its meaning through color.
 * 
 * @default "none"
 */
intent?: | 'high'
| 'medium'
| 'low'
| 'stable'
| 'informational'
| 'draft'
| 'none' = 'none'

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: | ComponentRenderFn< HTMLAttributesWithRef >
| React.ReactElement< Record< string, unknown > >
Imports
import { Fieldset } from "@wordpress/ui";
Default story ok
const Default = () => <Fieldset.Root>(<>
        <Fieldset.Legend>Legend</Fieldset.Legend>
        { [ 'Apples', 'Bananas' ].map( ( fruit ) => (
            // eslint-disable-next-line jsx-a11y/label-has-associated-control
            (<label key={ fruit }>
                <input type="checkbox" /> { fruit }
            </label>)
        ) ) }
        <Fieldset.Description>
            This is a description for the entire fieldset.
        </Fieldset.Description>
    </>)</Fieldset.Root>;
Hidden Legend story ok
When `hideFromVision` is set on `Fieldset.Legend`, the legend is visually hidden but remains accessible to screen readers.
const HiddenLegend = () => <Fieldset.Root>(<>
        <Fieldset.Legend hideFromVision>Legend</Fieldset.Legend>
        { [ 'Apples', 'Bananas' ].map( ( fruit ) => (
            // eslint-disable-next-line jsx-a11y/label-has-associated-control
            (<label key={ fruit }>
                <input type="checkbox" /> { fruit }
            </label>)
        ) ) }
    </>)</Fieldset.Root>;
With Details story ok
To add rich content (such as links) to the description, use `Fieldset.Details`. Although this content is not associated with the fieldset using direct semantics, it is made discoverable to screen reader users via a visually hidden description, alerting them to the presence of additional information below. If the content only includes plain text, use `Fieldset.Description` instead, so the readout is not unnecessarily verbose for screen reader users.
const WithDetails = () => <Fieldset.Root>(<>
        <Fieldset.Legend>Legend</Fieldset.Legend>
        { [ 'Apples', 'Bananas' ].map( ( fruit ) => (
            // eslint-disable-next-line jsx-a11y/label-has-associated-control
            (<label key={ fruit }>
                <input type="checkbox" /> { fruit }
            </label>)
        ) ) }
        <Fieldset.Details>{ DETAILS_EXAMPLE }</Fieldset.Details>
    </>)</Fieldset.Root>;

Flex

components-flex · ../packages/components/src/flex/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Flex, FlexBlock, FlexItem, View } from "@wordpress/components";
Default story ok
const Default = () => {
    return (
        <Flex>
            <FlexItem>
                <GrayBox>Item 1</GrayBox>
            </FlexItem>
            <FlexItem>
                <GrayBox>Item 2</GrayBox>
            </FlexItem>
            <FlexItem>
                <GrayBox>Item 3</GrayBox>
            </FlexItem>
        </Flex>
    );
};
Responsive Direction story ok
const ResponsiveDirection = () => {
    return (
        <Flex direction={[ 'column', 'row' ]}>
            <FlexItem>
                <GrayBox>Item 1</GrayBox>
            </FlexItem>
            <FlexBlock>
                <GrayBox>Item 2</GrayBox>
            </FlexBlock>
            <FlexItem>
                <GrayBox>Item 3</GrayBox>
            </FlexItem>
            <FlexItem>
                <GrayBox>Item 4</GrayBox>
            </FlexItem>
        </Flex>
    );
};

FocalPointPicker

components-focalpointpicker · ../packages/components/src/focal-point-picker/stories/index.story.tsx
Focal Point Picker is a component which creates a UI for identifying the most important visual point of an image. This component addresses a specific problem: with large background images it is common to see undesirable crops, especially when viewing on smaller viewports such as mobile phones. This component allows the selection of the point with the most important visual information and returns it as a pair of numbers between 0 and 1. This value can be easily converted into the CSS `background-position` attribute, and will ensure that the focal point is never cropped out, regardless of viewport. - Example focal point picker value: `{ x: 0.5, y: 0.1 }` - Corresponding CSS: `background-position: 50% 10%;` ```jsx import { FocalPointPicker } from '@wordpress/components'; import { useState } from '@wordpress/element'; const Example = () => { const [ focalPoint, setFocalPoint ] = useState( { x: 0.5, y: 0.5, } ); const url = '/path/to/image'; // Example function to render the CSS styles based on Focal Point Picker value const style = { backgroundImage: `url(${ url })`, backgroundPosition: `${ focalPoint.x * 100 }% ${ focalPoint.y * 100 }%`, }; return ( <> <FocalPointPicker url={ url } value={ focalPoint } onDragStart={ setFocalPoint } onDrag={ setFocalPoint } onChange={ setFocalPoint } /> <div style={ style } /> </> ); }; ```
Prop types 2 prop types
Component: ../packages/components/src/focal-point-picker/index.tsx::FocalPointPicker
Props:
autoPlay?: any = true

value?: any = {
	x: 0.5,
	y: 0.5,
}
Imports
import { FocalPointPicker } from "@wordpress/components";
Default story ok
const Default = ( {
	onChange,
	...props
} ) => {
	const [ focalPoint, setFocalPoint ] = useState( {
		x: 0.5,
		y: 0.5,
	} );

	return (
		<FocalPointPicker
			{ ...props }
			value={ focalPoint }
			onChange={ ( ...changeArgs ) => {
				onChange( ...changeArgs );
				setFocalPoint( ...changeArgs );
			} }
		/>
	);
};
Image story ok
const Image = ( {
	onChange,
	...props
} ) => {
	const [ focalPoint, setFocalPoint ] = useState( {
		x: 0.5,
		y: 0.5,
	} );

	return (
		<FocalPointPicker
			{ ...props }
			value={ focalPoint }
			onChange={ ( ...changeArgs ) => {
				onChange( ...changeArgs );
				setFocalPoint( ...changeArgs );
			} }
		/>
	);
};
Video story ok
const Video = ( {
	onChange,
	...props
} ) => {
	const [ focalPoint, setFocalPoint ] = useState( {
		x: 0.5,
		y: 0.5,
	} );

	return (
		<FocalPointPicker
			{ ...props }
			value={ focalPoint }
			onChange={ ( ...changeArgs ) => {
				onChange( ...changeArgs );
				setFocalPoint( ...changeArgs );
			} }
		/>
	);
};
Snapping story ok
const Snapping = ( {
	onChange,
	...props
} ) => {
	const [ focalPoint, setFocalPoint ] = useState( {
		x: 0.5,
		y: 0.5,
	} );

	return (
		<FocalPointPicker
			{ ...props }
			value={ focalPoint }
			onChange={ ( ...changeArgs ) => {
				onChange( ...changeArgs );
				setFocalPoint( ...changeArgs );
			} }
		/>
	);
};

FontFamilyControl

blockeditor-fontfamilycontrol · ../packages/block-editor/src/components/font-family/stories/index.story.jsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 2 prop types
Component: ../packages/block-editor/src/components/font-family/index.js::default
Props:
__next40pxDefaultSize?: any = false

value?: any = ''
Imports
import { FontFamilyControl } from "@wordpress/block-editor";
Default story ok
const Default = function Template( props ) {
    const [ value, setValue ] = useState();
    return (
        <FontFamilyControl
            onChange={ setValue }
            value={ value }
            { ...props }
        />
    );
};

FontSizePicker

components-fontsizepicker · ../packages/components/src/font-size-picker/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 12 prop types
Component: ../packages/components/src/font-size-picker/index.tsx::FontSizePicker
Props:
/**
 * Start opting into the larger default height that will become the default size in a future version.
 * 
 * @default false
 */
__next40pxDefaultSize?: boolean

/**
 * Start opting into the new margin-free styles that will become the default
 * in a future version, currently scheduled to be WordPress 6.4. (The prop
 * can be safely removed once this happens.)
 * 
 * @default false
 * @deprecated Default behavior since WP 6.5. Prop can be safely removed.
 * @ignore
 */
__nextHasNoMarginBottom?: boolean

/**
 * If `true`, it will not be possible to choose a custom fontSize. The user
 * will be forced to pick one of the pre-defined sizes passed in fontSizes.
 * 
 * @default false
 */
disableCustomFontSizes?: boolean

/**
 * If no value exists, this prop defines the starting position for the font
 * size picker slider. Only relevant if `withSlider` is `true`.
 */
fallbackFontSize?: number

/**
 * An array of font size objects. The object should contain properties size,
 * name, and slug.
 */
fontSizes?: FontSize[]

/**
 * A function that receives the new font size value.
 * If onChange is called without any parameter, it should reset the value,
 * attending to what reset means in that context, e.g., set the font size to
 * undefined or set the font size a starting value.
 */
onChange?: (
	value: number | string | undefined,
	selectedItem?: FontSize
) => void

/**
 * Size of the control.
 * 
 * @default 'default'
 */
size?: 'default' | '__unstable-large'

/**
 * Available units for custom font size selection.
 * 
 * @default [ 'px', 'em', 'rem', 'vw', 'vh' ]
 */
units?: string[]

/**
 * The current font size value.
 * 
 * Note: For the `units` property to work, the current font size value must be specified
 * as strings with units (e.g., '12px' instead of 12). When the font size is provided
 * as a number, the component operates in "unitless mode" where the `units` property has no effect.
 */
value?: number | string

/**
 * Determines how the `value` prop should be interpreted.
 * - `'literal'`: The `value` prop contains the actual font size value (number or string)
 * - `'slug'`: The `value` prop contains the slug of the selected font size
 * 
 * @default 'literal'
 */
valueMode?: 'literal' | 'slug'

/**
 * If `true`, a reset button will be displayed alongside the input field
 * when a custom font size is active. Has no effect when
 * `disableCustomFontSizes` is `true`.
 * 
 * @default true
 */
withReset?: boolean

/**
 * If `true`, a slider will be displayed alongside the input field when a
 * custom font size is active. Has no effect when `disableCustomFontSizes`
 * is `true`.
 * 
 * @default false
 */
withSlider?: boolean
Imports
import { FontSizePicker } from "@wordpress/components";
Default story ok
const Default = ( {
	value,
	onChange,
	...props
}: React.ComponentProps< typeof FontSizePicker > ) => {
	const [ fontSize, setFontSize ] = useState( value );
	return (
		<FontSizePicker
			__next40pxDefaultSize
			{ ...props }
			value={ fontSize }
			onChange={ ( nextValue ) => {
				setFontSize( nextValue );
				onChange?.( nextValue );
			} }
		/>
	);
};
With Slider story ok
const WithSlider = ( {
	value,
	onChange,
	...props
}: React.ComponentProps< typeof FontSizePicker > ) => {
	const [ fontSize, setFontSize ] = useState( value );
	return (
		<FontSizePicker
			__next40pxDefaultSize
			{ ...props }
			value={ fontSize }
			onChange={ ( nextValue ) => {
				setFontSize( nextValue );
				onChange?.( nextValue );
			} }
		/>
	);
};
With Custom Sizes Disabled story ok
With custom font sizes disabled via the `disableCustomFontSizes` prop, the user will only be able to pick one of the predefined sizes passed in `fontSizes`.
const WithCustomSizesDisabled = ( {
	value,
	onChange,
	...props
}: React.ComponentProps< typeof FontSizePicker > ) => {
	const [ fontSize, setFontSize ] = useState( value );
	return (
		<FontSizePicker
			__next40pxDefaultSize
			{ ...props }
			value={ fontSize }
			onChange={ ( nextValue ) => {
				setFontSize( nextValue );
				onChange?.( nextValue );
			} }
		/>
	);
};
With More Font Sizes story ok
When there are more than 5 font size options, the UI is no longer a toggle group.
const WithMoreFontSizes = ( {
	value,
	onChange,
	...props
}: React.ComponentProps< typeof FontSizePicker > ) => {
	const [ fontSize, setFontSize ] = useState( value );
	return (
		<FontSizePicker
			__next40pxDefaultSize
			{ ...props }
			value={ fontSize }
			onChange={ ( nextValue ) => {
				setFontSize( nextValue );
				onChange?.( nextValue );
			} }
		/>
	);
};
With Units story ok
When units like `px` are specified explicitly, it will be shown as a label hint.
const WithUnits = ( {
	fontSizes,
	...props
}: React.ComponentProps< typeof FontSizePicker > ) => {
	return (
		<>
			<h2>Fewer font sizes</h2>
			<FontSizePickerWithState
				{ ...props }
				fontSizes={ fontSizes?.slice( 0, 4 ) }
			/>

			<h2>More font sizes</h2>
			<FontSizePickerWithState { ...props } fontSizes={ fontSizes } />
		</>
	);
};
With Complex CSS Values story ok
The label hint will not be shown if it is a complex CSS value. Some examples of complex CSS values in this context are CSS functions like `calc()`, `clamp()`, and `var()`.
const WithComplexCSSValues = ( {
	fontSizes,
	...props
}: React.ComponentProps< typeof FontSizePicker > ) => {
	return (
		<>
			<h2>Fewer font sizes</h2>
			<FontSizePickerWithState
				{ ...props }
				fontSizes={ fontSizes?.slice( 0, 4 ) }
			/>

			<h2>More font sizes</h2>
			<FontSizePickerWithState { ...props } fontSizes={ fontSizes } />
		</>
	);
};

FormFileUpload

components-formfileupload · ../packages/components/src/form-file-upload/stories/index.story.tsx
FormFileUpload allows users to select files from their local device. ```jsx import { FormFileUpload } from '@wordpress/components'; const MyFormFileUpload = () => ( <FormFileUpload __next40pxDefaultSize accept="image/*" onChange={ ( event ) => console.log( event.currentTarget.files ) } > Upload </FormFileUpload> ); ```
Prop types 1 prop type
Component: ../packages/components/src/form-file-upload/index.tsx::FormFileUpload
Props:
multiple?: any = false
Imports
import { FormFileUpload } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	return <FormFileUpload __next40pxDefaultSize { ...props } />;
};
Restrict File Types story ok
const RestrictFileTypes = ( props ) => {
	return <FormFileUpload __next40pxDefaultSize { ...props } />;
};
Allow Multiple Files story ok
const AllowMultipleFiles = ( props ) => {
	return <FormFileUpload __next40pxDefaultSize { ...props } />;
};
With Icon story ok
const WithIcon = ( props ) => {
	return <FormFileUpload __next40pxDefaultSize { ...props } />;
};
With Custom Render story ok
Render a custom trigger button by passing a render function to the `render` prop. ```jsx ( { openFileDialog } ) => <button onClick={ openFileDialog }>Custom Upload Button</button> ```
const WithCustomRender = ( props ) => {
	return <FormFileUpload __next40pxDefaultSize { ...props } />;
};

FormToggle

components-formtoggle · ../packages/components/src/form-toggle/stories/index.story.tsx
FormToggle switches a single setting on or off. ```jsx import { FormToggle } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyFormToggle = () => { const [ isChecked, setChecked ] = useState( true ); return ( <FormToggle checked={ isChecked } onChange={ () => setChecked( ( state ) => ! state ) } /> ); }; ```
Imports
import { FormToggle } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ isChecked, setChecked ] = useState( true );

    return (
        <FormToggle
            checked={ isChecked }
            onChange={ ( e ) => {
				setChecked( ( state ) => ! state );
				onChange( e );
			} } />
    );
};

FormTokenField

components-formtokenfield · ../packages/components/src/form-token-field/stories/index.story.tsx
A `FormTokenField` is a field similar to the tags and categories fields in the interim editor chrome, or the "to" field in Mail on OS X. Tokens can be entered by typing them or selecting them from a list of suggested tokens. Up to one hundred suggestions that match what the user has typed so far will be shown from which the user can pick from (auto-complete). Tokens are separated by the "," character. Suggestions can be selected with the up or down arrows and added with the tab or enter key. The `value` property is handled in a manner similar to controlled form components. See [Forms](https://react.dev/reference/react-dom/components#form-components) in the React Documentation for more information.
Prop types 24 prop types
Component: ../packages/components/src/form-token-field/index.tsx::FormTokenField
Props:
/**
 * If true, the select the first matching suggestion when the user presses
 * the Enter key (or space when tokenizeOnSpace is true).
 * 
 * @default false
 */
__experimentalAutoSelectFirstMatch?: boolean

/**
 * If true, the suggestions list will be always expanded when the input field has the focus.
 */
__experimentalExpandOnFocus?: boolean

/**
 * Custom renderer for suggestions.
 */
__experimentalRenderItem?: ( args: { item: string } ) => ReactNode

/**
 * If false, the text on how to use the select (ie: _Separate with commas or the Enter key._) will be hidden.
 * 
 * @default true
 */
__experimentalShowHowTo?: boolean

/**
 * If passed, all introduced values will be validated before being added as tokens.
 * 
 * @default () => true
 */
__experimentalValidateInput?: ( token: string ) => boolean

/**
 * Deprecated. Use `__next40pxDefaultSize` instead.
 * 
 * @default false
 * @deprecated
 * @ignore
 */
__next36pxDefaultSize?: boolean

/**
 * Start opting into the larger default height that will become the
 * default size in a future version.
 * 
 * @default false
 */
__next40pxDefaultSize?: boolean

/**
 * Start opting into the new margin-free styles that will become the default in a future version.
 * 
 * @deprecated Default behavior since WP 7.0. Prop can be safely removed.
 * @ignore
 * 
 * @default false
 */
__nextHasNoMarginBottom?: boolean

/**
 * When true, tokens are not able to be added or removed.
 */
disabled?: boolean

/**
 * Function to call to transform tokens for display.
 * (In the editor, this is needed to decode HTML entities embedded in tags
 * - otherwise entities like `&` in tag names are double-encoded like `&amp;`,
 * once by the REST API and once by React).
 */
displayTransform?: ( token: string ) => string

/**
 * When true, renders tokens as without a background.
 */
isBorderless?: boolean

label?: string

/**
 * If passed, `TokenField` will disable ability to add new tokens once number of tokens is greater than or equal to `maxLength`.
 */
maxLength?: number

/**
 * The maximum number of suggestions to display at a time.
 * 
 * @default 100
 */
maxSuggestions?: number

/**
 * Allows customizing the messages presented by screen readers in different occasions:
 * 
 * -   `added`: The user added a new token.
 * -   `removed`: The user removed an existing token.
 * -   `remove` : The user focused the button to remove the token.
 * -   `__experimentalInvalid`: The user tried to add a token that didn't pass the validation.
 */
messages?: {
	/**
	 * The user added a new token.
	 */
	added: string;
	/**
	 * The user removed an existing token.
	 */
	removed: string;
	/**
	 * The user focused the button to remove the token.
	 */
	remove: string;
	/**
	 * The user tried to add a token that didn't pass the validation.
	 */
	__experimentalInvalid: string;
}

/**
 * Function to call when the tokens have changed. An array of new tokens is passed to the callback.
 */
onChange?: ( tokens: ( string | TokenItem )[] ) => void

/**
 * Function to call when the TokenField has been focused on. The event is passed to the callback. Useful for analytics.
 */
onFocus?: ( event: FocusEvent ) => void

/**
 * Function to call when the users types in the input field. It can be used to trigger autocomplete requests.
 */
onInputChange?: ( input: string ) => void

/**
 * If passed, the `TokenField` input will show a placeholder string if no value tokens are present.
 */
placeholder?: string

/**
 * Function to call to transform tokens for saving. The default is to trim the token value.
 * This function is also applied when matching suggestions against the current value
 * so that matching works correctly with leading or trailing spaces. (In the editor,
 * this is needed to remove leading and trailing spaces from tag names, like wp-admin does.
 * Otherwise the REST API won't save them.)
 * 
 * @default ( token: string ) => token.trim()
 */
saveTransform?: ( token: string ) => string

/**
 * An array of strings to present to the user as suggested tokens.
 */
suggestions?: string[]

/**
 * If true, add any incompleteTokenValue as a new token when the field loses focus.
 * 
 * @default false
 */
tokenizeOnBlur?: boolean

/**
 * If true, will add a token when `TokenField` is focused and `space` is pressed.
 */
tokenizeOnSpace?: boolean

/**
 * An array of strings or objects to display as tokens in the field.
 * If objects are present in the array, they **must** have a property of `value`.
 */
value?: ( string | TokenItem )[]
Imports
import { FormTokenField } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ selectedContinents, setSelectedContinents ] = useState<
		ComponentProps< typeof FormTokenField >[ 'value' ]
	>( [] );

    return (
        <FormTokenField
            __next40pxDefaultSize
            label="Type a continent"
            suggestions={continents}
            value={ selectedContinents }
            onChange={ ( tokens ) => setSelectedContinents( tokens ) } />
    );
};
Async story ok
const Async = () => {
    const [ selectedContinents, setSelectedContinents ] = useState<
		ComponentProps< typeof FormTokenField >[ 'value' ]
	>( [] );
    const [ availableContinents, setAvailableContinents ] = useState<
		string[]
	>( [] );

    const searchContinents = ( input: string ) => {
		const timeout = setTimeout( () => {
			const available = ( suggestions || [] ).filter( ( continent ) =>
				continent.toLowerCase().includes( input.toLowerCase() )
			);
			setAvailableContinents( available );
		}, 1000 );

		return () => clearTimeout( timeout );
	};

    return (
        <FormTokenField
            __next40pxDefaultSize
            label="Type a continent"
            value={ selectedContinents }
            suggestions={ availableContinents }
            onChange={ ( tokens ) => setSelectedContinents( tokens ) }
            onInputChange={ searchContinents } />
    );
};
Dropdown Selector story ok
const DropdownSelector = () => {
    const [ selectedContinents, setSelectedContinents ] = useState<
		ComponentProps< typeof FormTokenField >[ 'value' ]
	>( [] );

    return (
        <FormTokenField
            __next40pxDefaultSize
            __experimentalExpandOnFocus
            __experimentalAutoSelectFirstMatch
            value={ selectedContinents }
            onChange={ ( tokens ) => setSelectedContinents( tokens ) } />
    );
};
With Custom Rendered Items story ok
The rendered content of each token can be customized by passing a render function to the `displayTransform` prop. Similarly, each suggestion can be customized by passing a render function to the `__experimentalRenderItem` prop. (This is still an experimental feature and is subject to change.)
const WithCustomRenderedItems = () => {
    const [ selectedContinents, setSelectedContinents ] = useState<
		ComponentProps< typeof FormTokenField >[ 'value' ]
	>( [] );

    return (
        <FormTokenField
            __next40pxDefaultSize
            displayTransform={( token ) => `📍 ${ token }`}
            __experimentalRenderItem={( { item } ) => (
                <div>{ `${ item } — a nice place to visit` }</div>
            )}
            __experimentalExpandOnFocus
            value={ selectedContinents }
            onChange={ ( tokens ) => setSelectedContinents( tokens ) } />
    );
};
Validate New Tokens story ok
Only values for which the `__experimentalValidateInput` function returns `true` will be tokenized. (This is still an experimental feature and is subject to change.) In this example, the user can only add tokens that are already in the list.
const ValidateNewTokens = () => {
    const [ selectedContinents, setSelectedContinents ] = useState<
		ComponentProps< typeof FormTokenField >[ 'value' ]
	>( [] );

    return (
        <FormTokenField
            __next40pxDefaultSize
            __experimentalValidateInput={( input: string ) =>
                continents.includes( input )}
            __experimentalExpandOnFocus
            value={ selectedContinents }
            onChange={ ( tokens ) => setSelectedContinents( tokens ) } />
    );
};

GradientPicker

components-gradientpicker · ../packages/components/src/gradient-picker/stories/index.story.tsx
GradientPicker is a React component that renders a color gradient picker to define a multi step gradient. There's either a _linear_ or a _radial_ type available. ```jsx import { useState } from 'react'; import { GradientPicker } from '@wordpress/components'; const MyGradientPicker = () => { const [ gradient, setGradient ] = useState( null ); return ( <GradientPicker value={ gradient } onChange={ ( currentGradient ) => setGradient( currentGradient ) } gradients={ [ { name: 'JShine', gradient: 'linear-gradient(135deg,#12c2e9 0%,#c471ed 50%,#f64f59 100%)', slug: 'jshine', }, { name: 'Moonlit Asteroid', gradient: 'linear-gradient(135deg,#0F2027 0%, #203A43 0%, #2c5364 100%)', slug: 'moonlit-asteroid', }, { name: 'Rastafarie', gradient: 'linear-gradient(135deg,#1E9600 0%, #FFF200 0%, #FF0000 100%)', slug: 'rastafari', }, ] } /> ); }; ```
Prop types 12 prop types
Component: ../packages/components/src/gradient-picker/index.tsx::GradientPicker
Props:
/**
 * Whether this is rendered in the sidebar.
 * 
 * @default false
 */
__experimentalIsRenderedInSidebar?: boolean

/**
 * Start opting in to the new margin-free styles that will become the default
 * in a future version, currently scheduled to be WordPress 6.4. (The prop
 * can be safely removed once this happens.)
 * 
 * @default false
 * @deprecated Default behavior since WP 6.5. Prop can be safely removed.
 * @ignore
 */
__nextHasNoMargin?: boolean

/**
 * Whether the control should present as a set of buttons,
 * each with its own tab stop.
 * 
 * @default false
 */
asButtons?: boolean

/**
 * The class name added to the wrapper.
 */
className?: string

/**
 * Whether the palette should have a clearing button or not.
 * 
 * @default true
 */
clearable?: boolean = true

/**
 * If true, the gradient picker will not be displayed and only defined
 * gradients from `gradients` will be shown.
 * 
 * @default false
 */
disableCustomGradients?: boolean = false

/**
 * Whether to enable alpha transparency options in the picker.
 * 
 * @default true
 */
enableAlpha?: boolean = true

/**
 * An array of objects as predefined gradients displayed above the gradient
 * selector. Alternatively, if there are multiple sets (or 'origins') of
 * gradients, you can pass an array of objects each with a `name` and a
 * `gradients` array which will in turn contain the predefined gradient objects.
 * 
 * @default []
 */
gradients?: GradientObject[] | OriginObject[] = []

/**
 * The heading level. Only applies in cases where gradients are provided
 * from multiple origins (i.e. when the array passed as the `gradients` prop
 * contains two or more items).
 * 
 * @default 2
 */
headingLevel?: | 1
| 2
| 3
| 4
| 5
| 6
| '1'
| '2'
| '3'
| '4'
| '5'
| '6' = 2

/**
 * Prevents keyboard interaction from wrapping around.
 * Only used when `asButtons` is not true.
 * 
 * @default true
 */
loop?: boolean

/**
 * The function called when a new gradient has been defined. It is passed to
 * the `currentGradient` as an argument.
 */
onChange: ( currentGradient: string | undefined ) => void

/**
 * The current value of the gradient. Pass a css gradient string (See default value for example).
 * Optionally pass in a `null` value to specify no gradient is currently selected.
 * 
 * @default 'linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)'
 */
value?: GradientObject[ 'gradient' ] | null
Imports
import { GradientPicker } from "@wordpress/components";
Default story ok
const Default = ( {
	onChange,
	...props
}: React.ComponentProps< typeof GradientPicker > ) => {
	const [ gradient, setGradient ] =
		useState< ( typeof props )[ 'value' ] >( null );
	return (
		<GradientPicker
			{ ...props }
			value={ gradient }
			onChange={ ( ...changeArgs ) => {
				setGradient( ...changeArgs );
				onChange?.( ...changeArgs );
			} }
		/>
	);
};
With No Existing Gradients story ok
const WithNoExistingGradients = ( {
	onChange,
	...props
}: React.ComponentProps< typeof GradientPicker > ) => {
	const [ gradient, setGradient ] =
		useState< ( typeof props )[ 'value' ] >( null );
	return (
		<GradientPicker
			{ ...props }
			value={ gradient }
			onChange={ ( ...changeArgs ) => {
				setGradient( ...changeArgs );
				onChange?.( ...changeArgs );
			} }
		/>
	);
};
Multiple Origins story ok
const MultipleOrigins = ( {
	onChange,
	...props
}: React.ComponentProps< typeof GradientPicker > ) => {
	const [ gradient, setGradient ] =
		useState< ( typeof props )[ 'value' ] >( null );
	return (
		<GradientPicker
			{ ...props }
			value={ gradient }
			onChange={ ( ...changeArgs ) => {
				setGradient( ...changeArgs );
				onChange?.( ...changeArgs );
			} }
		/>
	);
};
CSS Variables story ok
const CSSVariables = () => <div
    style={ {
        '--red': '#f00',
        '--yellow': '#ff0',
        '--blue': '#00f',
    } }>
    <Template
        onChange={fn()}
        gradients={[
			{
				name: 'Red to Yellow',
				gradient:
					'linear-gradient(135deg,var(--red) 0%,var(--yellow) 100%)',
				slug: 'red-to-yellow',
			},
			{
				name: 'Yellow to Blue',
				gradient:
					'linear-gradient(135deg,var(--yellow) 0%,var(--blue) 100%)',
				slug: 'yellow-to-blue',
			},
			{
				name: 'Blue to Red',
				gradient:
					'linear-gradient(135deg,var(--blue) 0%,var(--red) 100%)',
				slug: 'blue-to-red',
			},
		]} />
</div>;

Grid

components-grid · ../packages/components/src/grid/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Grid, View } from "@wordpress/components";
Default story ok
const Default = ( props ) => (
	<Grid { ...props }>
		<Item>One</Item>
		<Item>Two</Item>
		<Item>Three</Item>
		<Item>Four</Item>
		<Item>Five</Item>
		<Item>Six</Item>
		<Item>Seven</Item>
		<Item>Eight</Item>
	</Grid>
);

Guide

components-guide · ../packages/components/src/guide/stories/index.story.tsx
`Guide` is a React component that renders a _user guide_ in a modal. The guide consists of several pages which the user can step through one by one. The guide is finished when the modal is closed or when the user clicks _Finish_ on the last page of the guide. ```jsx function MyTutorial() { const [ isOpen, setIsOpen ] = useState( true ); if ( ! isOpen ) { return null; } return ( <Guide onFinish={ () => setIsOpen( false ) } pages={ [ { content: <p>Welcome to the ACME Store!</p>, }, { image: <img src="https://acmestore.com/add-to-cart.png" />, content: ( <p> Click <i>Add to Cart</i> to buy a product. </p> ), }, ] } /> ); } ```
Prop types 8 prop types
Component: ../packages/components/src/guide/index.tsx::default
Props:
/**
 * Deprecated. Use `pages` prop instead.
 * 
 * @deprecated since 5.5
 */
children?: ReactNode

/**
 * A custom class to add to the modal.
 */
className?: string

/**
 * Used as the modal's accessibility label.
 */
contentLabel: ModalProps[ 'contentLabel' ]

/**
 * Use this to customize the label of the _Finish_ button shown at the end of the guide.
 * 
 * @default 'Finish'
 */
finishButtonText?: string = __( 'Finish' )

/**
 * Use this to customize the label of the _Next_ button shown on each page of the guide.
 * 
 * @default 'Next'
 */
nextButtonText?: string = __( 'Next' )

/**
 * A function which is called when the guide is finished.
 */
onFinish: ModalProps[ 'onRequestClose' ]

/**
 * A list of objects describing each page in the guide. Each object **must** contain a `'content'` property and may optionally contain a `'image'` property.
 * 
 * @default []
 */
pages?: Page[] = []

/**
 * Use this to customize the label of the _Previous_ button shown on each page of the guide except the first.
 * 
 * @default 'Previous'
 */
previousButtonText?: string = __( 'Previous' )
Imports
import { Button, Guide } from "@wordpress/components";
Default story ok
const Default = ( { onFinish, ...props } ) => {
	const [ isOpen, setOpen ] = useState( false );

	const openGuide = () => setOpen( true );
	const closeGuide = () => setOpen( false );

	return (
		<>
			<Button
				__next40pxDefaultSize
				variant="secondary"
				onClick={ openGuide }
			>
				Open Guide
			</Button>
			{ isOpen && (
				<Guide
					{ ...props }
					onFinish={ ( ...finishArgs ) => {
						closeGuide();
						onFinish?.( ...finishArgs );
					} }
				/>
			) }
		</>
	);
};

Heading

components-heading · ../packages/components/src/heading/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Heading } from "@wordpress/components";
Default story ok
const Default = ( props ) => (
	<Heading { ...props } />
);

HeadingLevelDropdown

blockeditor-headingleveldropdown · ../packages/block-editor/src/components/block-heading-level-dropdown/stories/index.story.jsx
Dropdown for selecting a heading level (1 through 6) or paragraph (0).
param: {WPHeadingLevelDropdownProps} props Component props.return: {ComponentType} The toolbar.
Prop types 1 prop type
Component: ../packages/block-editor/src/components/block-heading-level-dropdown/index.js::default
Props:
options?: any = [ 1, 2, 3, 4, 5, 6 ]
Imports
import { HeadingLevelDropdown } from "@wordpress/block-editor";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState( args.value );

    return (
        <HeadingLevelDropdown
            value={ value }
            onChange={ ( ...changeArgs ) => {
                setValue( ...changeArgs );
                onChange( ...changeArgs );
            } } />
    );
};

HeightControl

blockeditor-heightcontrol · ../packages/block-editor/src/components/height-control/stories/index.story.jsx
HeightControl renders a linked unit control and range control for adjusting the height of a block.
deprecated: Use DimensionControl instead.see: https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/height-control/README.md param: {Object} props param: {?string} props.label A label for the control.param: {( value: string ) => void} props.onChange Called when the height changes.param: {string} props.value The current height value.return: {Component} The component to be rendered.
Prop types 1 prop type
Component: ../packages/block-editor/src/components/height-control/index.js::default
Props:
label?: any = __( 'Height' )
Imports
import { HeightControl } from "@wordpress/block-editor";
Default story ok
const Default = ( props ) => {
	const [ value, setValue ] = useState();
	return <HeightControl onChange={ setValue } value={ value } { ...props } />;
};

HStack

components-hstack · ../packages/components/src/h-stack/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { HStack, View } from "@wordpress/components";
Default story ok
const Default = () => <HStack spacing="3" style={ { background: '#eee', minHeight: '3rem' } }>
    { [ 'One', 'Two', 'Three', 'Four', 'Five' ].map( ( text ) => (
        <View key={ text } style={ { background: '#b9f9ff' } }>
            { text }
        </View>
    ) ) }
</HStack>;

Icon

components-icon · ../packages/components/src/icon/stories/index.story.tsx
Renders a raw icon without any initial styling or wrappers. ```jsx import { wordpress } from '@wordpress/icons'; <Icon icon={ wordpress } /> ```
Prop types 2 prop types
Component: ../packages/components/src/icon/index.tsx::default
Props:
/**
 * The icon to render. In most cases, you should use an icon from
 * [the `@wordpress/icons` package](https://wordpress.github.io/gutenberg/?path=/story/icons-icon--library).
 * 
 * Other supported values are: component instances, functions,
 * [Dashicons](https://developer.wordpress.org/resource/dashicons/)
 * (specified as strings), and `null`.
 * 
 * The `size` value, as well as any other additional props, will be passed through.
 * 
 * @default null
 */
icon?: IconType | null = null

/**
 * The size (width and height) of the icon.
 * 
 * Defaults to `20` when `icon` is a string (i.e. a Dashicon id), otherwise `24`.
 * 
 * @default `'string' === typeof icon ? 20 : 24`.
 */
size?: number = 'string' === typeof icon ? 20 : 24
Imports
import { Icon, VStack } from "@wordpress/components";
import { Path, SVG } from "@wordpress/primitives";
Default story ok
const Default = () => <Icon icon={wordpress} />;
Fill Color story ok
const FillColor = () => {
    return (
        <div
            style={ {
				fill: 'blue',
			} }>
            <Icon />
        </div>
    );
};
With A Function story ok
When `icon` is a function, it will be passed the `size` prop and any other additional props.
const WithAFunction = () => <Icon
    icon={( { size }: { size?: number } ) => (
		<img
			width={ size }
			height={ size }
			src="https://s.w.org/style/images/about/WordPress-logotype-wmark.png"
			alt="WordPress"
		/>
	)} />;
With A Component story ok
When `icon` is a component, it will be passed the `size` prop and any other additional props.
const WithAComponent = () => <Icon icon={<MyIconComponent />} />;
With An SVG story ok
const WithAnSVG = () => <Icon
    icon={(<SVG>
        <Path d="M5 4v3h5.5v12h3V7H19V4z" />
    </SVG>)} />;
With A Dashicon story ok
Although it's preferred to use icons from the `@wordpress/icons` package, [Dashicons](https://developer.wordpress.org/resource/dashicons/) are still supported, as long as you are in a context where the Dashicons stylesheet is loaded. To simulate that here, use the Global CSS Injector in the Storybook toolbar at the top and select the "WordPress" preset.
const WithADashicon = () => {
    return (
        <VStack>
            <Icon icon="wordpress" />
            <small>This won’t show an icon if the Dashicons stylesheet isn’t
                                loaded.
                            </small>
        </VStack>
    );
};

Icon

icons-icon · ../packages/icons/src/icon/stories/index.story.tsx
Return an SVG icon.
param: props The component props.return: Icon component
Prop types 2 prop types
Component: ../packages/icons/src/icon/index.ts::default
Props:
/**
 * The SVG component to render
 */
icon: ReactElement

/**
 * The size of the icon in pixels
 * 
 * @default 24
 */
size?: number = 24
Imports
import { Icon } from "@wordpress/icons";
Default story ok
const Default = (): ReactElement => {
	return (
		<>
			<div>
				<h2>Dashicons (corrected viewport)</h2>

				<Icon icon={ check } />
				<Icon icon={ check } size={ 36 } />
				<Icon icon={ check } size={ 48 } />
			</div>
			<div>
				<h2>Material and Other</h2>

				<Icon icon={ icons.paragraph } />
				<Icon icon={ icons.paragraph } size={ 36 } />
				<Icon icon={ icons.paragraph } size={ 48 } />
			</div>
		</>
	);
};

Icon

design-system-components-icon · ../packages/ui/src/icon/stories/index.story.tsx
Renders an SVG icon with a 24px default size. If no `fill` colors are explicitly set on the icon itself, it will be rendered with a `currentColor` fill. ```jsx import { wordpress } from '@wordpress/icons'; <Icon icon={ wordpress } /> ```
Prop types 2 prop types
Component: ../packages/ui/src/icon/icon.tsx::Icon
Props:
/**
 * The icon to render, which must be an svg element or an `SVG` from `@wordpress/primitives`.
 * 
 * In most cases, you should use an icon from
 * [the `@wordpress/icons` package](https://wordpress.github.io/gutenberg/?path=/story/icons-icon--library).
 */
icon: React.ReactElement< React.ComponentProps< 'svg' > >

/**
 * The size (width and height) of the icon.
 * @default 24
 */
size?: number = 24
Imports
import { Icon } from "@wordpress/ui";
Default story ok
const Default = () => <Icon icon={wordpress} />;
With Intrinsic Fill Color story ok
Explicit `fill` colors in the icon will be preserved.
const WithIntrinsicFillColor = () => <Icon
    icon={(<svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="blue"
    >
        <rect x="0" y="0" width="24" height="24" />
    </svg>)} />;

IconButton

design-system-components-iconbutton · ../packages/ui/src/icon-button/stories/index.story.tsx
An icon-only button with automatic tooltip and optimized styling. Inherits all Button props while providing icon-specific enhancements.
Prop types 4 prop types
Component: ../packages/ui/src/icon-button/icon-button.tsx::IconButton
Props:
children?: unknown

/**
 * The icon to display in the button.
 */
icon: IconProps[ 'icon' ]

/**
 * A label describing the button's action, shown as a tooltip and to
 * assistive technology.
 */
label: string

/**
 * The keyboard shortcut associated with this button. When provided, the
 * shortcut is displayed in the tooltip and announced to assistive technology.
 * 
 * **Note**: This prop is for display and accessibility purposes only — the
 * consumer is responsible for implementing the actual keyboard event handler.
 */
shortcut?: {
	/**
	 * The human-readable representation of the shortcut, displayed in the
	 * tooltip. Use platform-appropriate symbols (e.g., "⌘S" on macOS,
	 * "Ctrl+S" on Windows).
	 */
	displayShortcut: string;
	/**
	 * The shortcut in a format compatible with the
	 * [aria-keyshortcuts](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-keyshortcuts)
	 * attribute. Use "+" to separate keys and standard key names
	 * (e.g., "Meta+S", "Control+Shift+P").
	 */
	ariaKeyShortcut: string;
}
Imports
import { IconButton } from "@wordpress/ui";
Default story ok
const Default = () => <IconButton icon={cog} label="Settings" />;
Outline story ok
const Outline = () => <IconButton variant="outline" />;
Minimal story ok
const Minimal = () => <IconButton variant="minimal" />;
Neutral story ok
const Neutral = () => <IconButton tone="neutral" label="Settings" />;
Neutral Outline story ok
const NeutralOutline = () => <IconButton tone="neutral" variant="outline" label="Settings" />;
Disabled story ok
const Disabled = () => <IconButton disabled label="Settings" />;
With Different Icons story ok
const WithDifferentIcons = () => <div
    style={ {
        display: 'flex',
        gap: '1rem',
        alignItems: 'center',
        flexWrap: 'wrap',
    } }>
    <IconButton icon={ wordpress } label="WordPress" />
    <IconButton icon={ plus } label="Add" />
    <IconButton icon={ pencil } label="Edit" />
    <IconButton icon={ trash } label="Delete" />
    <IconButton icon={ download } label="Download" />
    <IconButton icon={ upload } label="Upload" />
</div>;
Pressed story ok
The pressed state is only available for buttons with `tone="neutral"` and `variant="minimal"` and can be toggled via the `aria-pressed` HTML attribute.
const Pressed = () => <IconButton tone="neutral" variant="minimal" label="Toggle Settings" aria-pressed />;
With Shortcut story ok
const WithShortcut = () => <IconButton icon={copy} label="Copy" shortcut={EXAMPLE_SHORTCUT_OBJECT} />;

ImageCropper

imagecropper-imagecropper · ../packages/image-cropper/src/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 4 prop types
Component: ../packages/image-cropper/src/components/image-cropper/index.tsx::default
Props:
maxZoom?: number = 5

minZoom?: number = 1

onLoad?: ( mediaSize: MediaSize ) => void

src: string
Imports
import {
    __experimentalHeading as Heading,
    __experimentalHStack as HStack,
    SelectControl,
    __experimentalVStack as VStack,
} from "@wordpress/components";
import { ImageCropper, ImageCropperProvider } from "@wordpress/image-cropper";
Default story ok
const Default = () => {
    return (
        <ImageCropperProvider>
            <div className="image-cropper__container-wrapper-story">
                <div className="image-cropper__container-story">
                    <ImageCropper
                        src="https://s.w.org/images/core/5.3/MtBlanc1.jpg"
                        minZoom={1}
                        maxZoom={5} />
                </div>
            </div>
        </ImageCropperProvider>
    );
};
With Controls story ok
const WithControls = () => {
    return (
        <ImageCropperProvider>
            <WithControlsContent
                src="https://s.w.org/images/core/5.3/MtBlanc1.jpg"
                minZoom={1}
                maxZoom={5} />
        </ImageCropperProvider>
    );
};

Input

design-system-components-form-primitives-input · ../packages/ui/src/form/primitives/input/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 5 prop types
Component: ../packages/ui/src/form/primitives/input/input.tsx::Input
Props:
/**
 * The default value to use in uncontrolled mode.
 */
defaultValue?: Input.Props[ 'defaultValue' ]

/**
 * Whether the field is disabled.
 */
disabled?: boolean

/**
 * The size of the field.
 */
size?: Exclude< InputLayoutProps[ 'size' ], 'small' > = 'default'

/**
 * The type of the input element.
 */
type?: Input.Props[ 'type' ]

/**
 * The value to use in controlled mode.
 */
value?: Input.Props[ 'value' ]
WithSuffixControl story error
Expected story to be a function or variable declaration
  38 | 	children: undefined,
  39 | };
> 40 | export { WithSuffixControl };
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  41 |
  42 | export const Disabled: Story = {
  43 | 	args: {
Imports
import { Input, InputLayout } from "@wordpress/ui";
Default story ok
const Default = () => <Input placeholder="Placeholder" />;
With Prefix story ok
The `InputLayout.Slot` component can be used to add standard padding in the `prefix` or `suffix` slot.
const WithPrefix = () => <Input placeholder="username" prefix={<InputLayout.Slot>@</InputLayout.Slot>} />;
Disabled story ok
const Disabled = () => <Input disabled />;

InputControl

components-inputcontrol · ../packages/components/src/input-control/stories/index.story.tsx
InputControl components let users enter and edit text. This is an experimental component intended to (in time) merge with or replace `TextControl`. ```jsx import { __experimentalInputControl as InputControl } from '@wordpress/components'; import { useState } from 'react'; const Example = () => { const [ value, setValue ] = useState( '' ); return ( <InputControl __next40pxDefaultSize value={ value } onChange={ ( nextValue ) => setValue( nextValue ?? '' ) } /> ); }; ```
Prop types 1 prop type
Component: ../packages/components/src/input-control/index.tsx::InputControl
Props:
__unstableStateReducer?: InputFieldProps[ 'stateReducer' ]
Imports
import { Button, InputControl, InputControlPrefixWrapper, InputControlSuffixWrapper } from "@wordpress/components";
import { Icon } from "@wordpress/icons";
Default story ok
const Default = () => <InputControl
    __next40pxDefaultSize
    onChange={fn()}
    onValidate={fn()}
    onKeyDown={fn()}
    label="Value"
    placeholder="Placeholder" />;
With Help Text story ok
const WithHelpText = () => <InputControl
    __next40pxDefaultSize
    onChange={fn()}
    onValidate={fn()}
    onKeyDown={fn()}
    help="Help text to describe the control." />;
With Prefix story ok
A `prefix` can be inserted before the input. By default, the prefix is aligned with the edge of the input border, with no padding. If you want to apply standard padding in accordance with the size variant, use the provided `<InputControlPrefixWrapper>` convenience wrapper.
const WithPrefix = () => <InputControl
    __next40pxDefaultSize
    onChange={fn()}
    onValidate={fn()}
    onKeyDown={fn()}
    prefix={<InputControlPrefixWrapper>@</InputControlPrefixWrapper>} />;
With Suffix story ok
A `suffix` can be inserted after the input. By default, the suffix is aligned with the edge of the input border, with no padding. If you want to apply standard padding in accordance with the size variant, use the provided `<InputControlSuffixWrapper>` convenience wrapper.
const WithSuffix = () => <InputControl
    __next40pxDefaultSize
    onChange={fn()}
    onValidate={fn()}
    onKeyDown={fn()}
    suffix={<InputControlSuffixWrapper>%</InputControlSuffixWrapper>} />;
With Icon Or Control story ok
`<InputControlPrefixWrapper>` and `<InputControlSuffixWrapper>` have a `variant` prop that can be used to adjust the wrapper based on the prefix or suffix content. - `'default'`: Standard padding for text content. - `'icon'`: For icons. - `'control'`: For controls, like buttons or selects.
const WithIconOrControl = () => <InputControl
    __next40pxDefaultSize
    onChange={fn()}
    onValidate={fn()}
    onKeyDown={fn()}
    prefix={(<InputControlPrefixWrapper variant="icon">
        <Icon icon={ link } />
    </InputControlPrefixWrapper>)}
    suffix={(<InputControlSuffixWrapper variant="control">
        <Button icon={ closeSmall } size="small" label="Clear" />
    </InputControlSuffixWrapper>)} />;
With Side Label story ok
const WithSideLabel = () => <InputControl
    __next40pxDefaultSize
    onChange={fn()}
    onValidate={fn()}
    onKeyDown={fn()}
    labelPosition="side" />;
With Edge Label story ok
const WithEdgeLabel = () => <InputControl
    __next40pxDefaultSize
    onChange={fn()}
    onValidate={fn()}
    onKeyDown={fn()}
    __unstableInputWidth="20em"
    labelPosition="edge" />;
Show Password story ok
const ShowPassword = () => {
    const [ visible, setVisible ] = useState( false );

    return (
        <InputControl
            __next40pxDefaultSize
            type={ visible ? 'text' : 'password' }
            suffix={
				<InputControlSuffixWrapper variant="control">
					<Button
						size="small"
						icon={ visible ? unseen : seen }
						onClick={ () => setVisible( ( value ) => ! value ) }
						label={ visible ? 'Hide password' : 'Show password' }
					/>
				</InputControlSuffixWrapper>
			}
            onChange={fn()}
            onValidate={fn()}
            onKeyDown={fn()}
            label="Password"
            placeholder={undefined} />
    );
};

InputControl

design-system-components-form-inputcontrol · ../packages/ui/src/form/input-control/stories/index.story.tsx
A complete input field with integrated label and description.
Prop types 4 prop types
Component: ../packages/ui/src/form/input-control/input-control.tsx::InputControl
Props:
/**
 * The accessible description, associated using `aria-describedby`.
 * 
 * For screen reader accessibility, this should only contain plain text,
 * and no semantics such as links.
 */
description?: React.ComponentProps<
	typeof Field.Description
>[ 'children' ]

/**
 * Additional information about the field, which unlike a normal description,
 * can include links and other semantic elements.
 * 
 * Do not use this prop when the content is only plain text;
 * use `description` instead.
 */
details?: React.ComponentProps< typeof Field.Details >[ 'children' ]

/**
 * Whether to visually hide the label while keeping it accessible
 * to screen readers.
 * 
 * @default false
 */
hideLabelFromVision?: React.ComponentProps<
	typeof Field.Label
>[ 'hideFromVision' ]

/**
 * The accessible label. All controls must be labeled.
 */
label: React.ComponentProps< typeof Field.Label >[ 'children' ]
WithPrefix story error
Expected story to be a function or variable declaration
  60 | 	...Default.args,
  61 | };
> 62 | export { WithPrefix, WithSuffixControl };
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  63 |
  64 | export const Password: Story = {
  65 | 	render: function Template( args ) {
WithSuffixControl story error
Expected story to be a function or variable declaration
  60 | 	...Default.args,
  61 | };
> 62 | export { WithPrefix, WithSuffixControl };
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  63 |
  64 | export const Password: Story = {
  65 | 	render: function Template( args ) {
Imports
import { IconButton, InputControl, InputLayout, Stack } from "@wordpress/ui";
Default story ok
const Default = () => <InputControl
    label="Label"
    description="This is the description."
    placeholder="Placeholder" />;
Visually Hidden Label story ok
const VisuallyHiddenLabel = () => <InputControl hideLabelFromVision />;
With Details story ok
const WithDetails = () => <InputControl description={undefined} details={DETAILS_EXAMPLE} />;
Password story ok
const Password = () => {
    const [ show, setShow ] = useState( false );

    return (
        <InputControl
            defaultValue="password"
            type={ show ? 'text' : 'password' }
            suffix={
                <InputLayout.Slot padding="minimal">
                    <IconButton
                        label={ show ? 'Hide password' : 'Show password' }
                        onClick={ () => setShow( ! show ) }
                        icon={ show ? unseen : seen }
                        size="small"
                        variant="minimal"
                    />
                </InputLayout.Slot>
            } />
    );
};
Date story ok
const Date = () => <InputControl type="date" />;
Number story ok
const Number = () => <InputControl placeholder="0" type="number" />;
Number With Steppers story ok
const NumberWithSteppers = () => {
    const [ value, setValue ] = useState( 0 );

    return (
        <>
            <style>
                { `
                  .my-number-with-steppers input[type='number'] {
                        -moz-appearance: textfield;
                  }
                    .my-number-with-steppers ::-webkit-inner-spin-button {
                        appearance: none;
                    }
                ` }
            </style>
            <InputControl
                type="number"
                value={ value }
                onValueChange={ ( v ) => setValue( parseInt( v, 10 ) ) }
                className="my-number-with-steppers"
                suffix={
                    <InputLayout.Slot padding="minimal">
                        <Stack direction="row" gap="xs">
                            <IconButton
                                label="Increment"
                                icon={ plus }
                                onClick={ () => setValue( value + 1 ) }
                                size="small"
                                variant="minimal"
                            />
                            <IconButton
                                label="Decrement"
                                icon={ reset }
                                onClick={ () => setValue( value - 1 ) }
                                size="small"
                                variant="minimal"
                            />
                        </Stack>
                    </InputLayout.Slot>
                } />
        </>
    );
};
Disabled story ok
const Disabled = () => <InputControl disabled />;

InputLayout

design-system-components-form-primitives-inputlayout · ../packages/ui/src/form/primitives/input-layout/stories/index.story.tsx
A low-level component that handles the visual layout of an input-like field, including disabled states and standard prefix/suffix slots.
Prop types 5 prop types
Component: ../packages/ui/src/form/primitives/input-layout/input-layout.tsx::InputLayout
Props:
/**
 * Whether the field should hide the border.
 */
isBorderless?: boolean

/**
 * Element to render before the input.
 */
prefix?: React.ReactNode

/**
 * The size of the field.
 * 
 * @default 'default'
 */
size?: 'default' | 'compact' | 'small' = 'default'

/**
 * Element to render after the input.
 */
suffix?: React.ReactNode

/**
 * Whether the field should be visually styled as disabled.
 */
visuallyDisabled?: boolean
Imports
import { IconButton, InputLayout } from "@wordpress/ui";
Default story ok
const Default = () => <InputLayout />;
With Prefix story ok
By default, the `prefix` and `suffix` slots are rendered with no padding.
const WithPrefix = () => <InputLayout
    prefix={(<div
        style={ {
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            height: '100%',
            aspectRatio: '1 / 1',
            background: '#eee',
        } }
    >$
                    </div>)} />;
With Padded Prefix story ok
The `InputLayout.Slot` component can be used to add standard padding in the `prefix` or `suffix` slot. The `padding="minimal"` setting will work best when the slot content is a button or icon.
const WithPaddedPrefix = () => <InputLayout prefix={<InputLayout.Slot>https://</InputLayout.Slot>} />;
With Suffix Control story ok
The `padding="minimal"` setting on `InputLayout.Slot` will work best when the slot content is a button or icon.
const WithSuffixControl = () => <InputLayout
    suffix={(<InputLayout.Slot padding="minimal">
        <IconButton
            size="small"
            variant="minimal"
            icon={ copy }
            label="Copy"
        />
    </InputLayout.Slot>)}><div style={ { flex: 1 } } /></InputLayout>;
Compact story ok
const Compact = () => <InputLayout size="compact" />;
Small story ok
The `small` size is intended only for rare cases like the trigger button of a low-profile `select` element.
const Small = () => <InputLayout size="small" />;

Inserter

blockeditor-inserter · ../packages/block-editor/src/components/inserter/stories/index.story.jsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { BlockLibrary, ExperimentalBlockEditorProvider, Inserter } from "@wordpress/block-editor";
Library Without Patterns story ok
const LibraryWithoutPatterns = () => {
	return (
		<ExperimentalBlockEditorProvider>
			<div style={ wrapperStyle }>
				<BlockLibrary showInserterHelpPanel />
			</div>
		</ExperimentalBlockEditorProvider>
	);
};
Library With Patterns story ok
const LibraryWithPatterns = () => {
	return (
		<ExperimentalBlockEditorProvider
			settings={ {
				__experimentalBlockPatternCategories: patternCategories,
				__experimentalBlockPatterns: patterns,
			} }
		>
			<div style={ wrapperStyle }>
				<BlockLibrary showInserterHelpPanel />
			</div>
		</ExperimentalBlockEditorProvider>
	);
};
Library With Patterns And Reusable Blocks story ok
const LibraryWithPatternsAndReusableBlocks = () => {
	return (
		<ExperimentalBlockEditorProvider
			settings={ {
				__experimentalBlockPatternCategories: patternCategories,
				__experimentalBlockPatterns: patterns,
				__experimentalReusableBlocks: reusableBlocks,
			} }
		>
			<div style={ wrapperStyle }>
				<BlockLibrary showInserterHelpPanel />
			</div>
		</ExperimentalBlockEditorProvider>
	);
};
Full Inserter story ok
const FullInserter = () => {
	return (
		<ExperimentalBlockEditorProvider
			settings={ {
				__experimentalBlockPatternCategories: patternCategories,
				__experimentalBlockPatterns: patterns,
				__experimentalReusableBlocks: reusableBlocks,
			} }
		>
			<div style={ wrapperStyle }>
				<Inserter />
			</div>
		</ExperimentalBlockEditorProvider>
	);
};
Quick Inserter story ok
const QuickInserter = () => {
	return (
		<ExperimentalBlockEditorProvider
			settings={ {
				__experimentalBlockPatternCategories: patternCategories,
				__experimentalBlockPatterns: patterns,
				__experimentalReusableBlocks: reusableBlocks,
			} }
		>
			<div style={ wrapperStyle }>
				<Inserter __experimentalIsQuick />
			</div>
		</ExperimentalBlockEditorProvider>
	);
};

ItemGroup

components-itemgroup · ../packages/components/src/item-group/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Item, ItemGroup } from "@wordpress/components";
Default story ok
const Default = ( props ) => (
	<ItemGroup { ...props } />
);
Non Clickable Items story ok
const NonClickableItems = ( props ) => (
	<ItemGroup { ...props } />
);
Custom Item Size story ok
const CustomItemSize = ( props ) => (
	<ItemGroup { ...props } />
);
Without Border story ok
const WithoutBorder = ( props ) => (
	<ItemGroup { ...props } />
);

KeyboardShortcuts

components-keyboardshortcuts · ../packages/components/src/keyboard-shortcuts/stories/index.story.tsx
`KeyboardShortcuts` is a component which handles keyboard sequences during the lifetime of the rendering element. When passed children, it will capture key events which occur on or within the children. If no children are passed, events are captured on the document. It uses the [Mousetrap](https://craig.is/killing/mice) library to implement keyboard sequence bindings. ```jsx import { KeyboardShortcuts } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyKeyboardShortcuts = () => { const [ isAllSelected, setIsAllSelected ] = useState( false ); const selectAll = () => { setIsAllSelected( true ); }; return ( <div> <KeyboardShortcuts shortcuts={ { 'mod+a': selectAll, } } /> [cmd/ctrl + A] Combination pressed? { isAllSelected ? 'Yes' : 'No' } </div> ); }; ```
Prop types 4 prop types
Component: ../packages/components/src/keyboard-shortcuts/index.tsx::default
Props:
/**
 * By default, a callback will not be invoked if the key combination occurs in an editable field.
 * Pass `bindGlobal` as `true` if the key events should be observed globally, including within editable fields.
 * 
 * Tip: If you need some but not all keyboard events to be observed globally,
 * simply render two distinct `KeyboardShortcuts` elements, one with and one without the `bindGlobal` prop.
 */
bindGlobal?: KeyboardShortcutProps[ 'bindGlobal' ]

/**
 * Elements to render, upon whom key events are to be monitored.
 */
children?: React.ReactNode

/**
 * By default, a callback is invoked in response to the `keydown` event.
 * To override this, pass `eventName` with the name of a specific keyboard event.
 */
eventName?: KeyboardShortcutProps[ 'eventName' ]

/**
 * An object of shortcut bindings, where each key is a keyboard combination,
 * the value of which is the callback to be invoked when the key combination is pressed.
 * 
 * The value of each shortcut should be a consistent function reference, not an anonymous function.
 * Otherwise, the callback will not be correctly unbound when the component unmounts.
 * 
 * The `KeyboardShortcuts` component will not update to reflect a changed `shortcuts` prop.
 * If you need to change shortcuts, mount a separate `KeyboardShortcuts` element,
 * which can be achieved by assigning a unique `key` prop.
 * 
 * @see {@link https://craig.is/killing/mice Mousetrap documentation}
 */
shortcuts: Record< string, KeyboardShortcutProps[ 'callback' ] >
Imports
import { KeyboardShortcuts } from "@wordpress/components";
Default story ok
const Default = ( props ) => (
	<KeyboardShortcuts { ...props } />
);

LayoutCardSaveExample

design-system-patterns-save-submit · ./stories/design-system/patterns/save-and-submit.story.tsx
Prop type error
No component file found for the "LayoutCardSaveExample" component.
  51 | };
  52 |
> 53 | const meta: Meta< typeof LayoutCardSaveExample > = {
     | ^
  54 | 	title: 'Design System/Patterns/Save & Submit',
  55 | 	component: LayoutCardSaveExample,
  56 | 	parameters: {

./stories/design-system/patterns/save-and-submit.mdx:
import type { Meta, StoryObj } from '@storybook/react-vite';
import { Button, Card, CardBody } from '@wordpress/components';
import { DataForm } from '@wordpress/dataviews';
import { useState } from '@wordpress/element';

const LayoutCardSaveExample = () => {
	const [ data, setData ] = useState( { title: '' } );

	return (
		<div style={ { maxWidth: '480px' } }>
			<Card
				size={ {
					blockStart: 'medium',
					blockEnd: 'medium',
					inlineStart: 'medium',
					inlineEnd: 'medium',
				} }
			>
				<CardBody>
					<DataForm
						data={ data }
						fields={ [
							{
								id: 'title',
								label: 'Title',
								type: 'text',
							},
						] }
						form={ {
							layout: { type: 'regular' },
							fields: [ 'title' ],
						} }
						onChange={ ( edits ) =>
							setData( ( previous ) => ( {
								...previous,
								...edits,
							} ) )
						}
					/>
					<Button
						variant="primary"
						isBusy
						style={ { marginTop: '16px' } }
					>
						Save
					</Button>
				</CardBody>
			</Card>
		</div>
	);
};

const meta: Meta< typeof LayoutCardSaveExample > = {
	title: 'Design System/Patterns/Save & Submit',
	component: LayoutCardSaveExample,
	parameters: {
		controls: { disable: true },
	},
	tags: [ '!dev' /* Hide individual story pages from sidebar */ ],
};

export default meta;

type Story = StoryObj< typeof LayoutCardSaveExample >;

export const SaveFormLayoutCard: Story = {
	name: 'Save form layout card',
	render: () => <LayoutCardSaveExample />,
};
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Button, Card, CardBody } from "@wordpress/components";
import { DataForm } from "@wordpress/dataviews";
Save form layout card story ok
const SaveFormLayoutCard = () => <LayoutCardSaveExample />;

LetterSpacingControl

blockeditor-letterspacingcontrol · ../packages/block-editor/src/components/letter-spacing-control/stories/index.story.jsx
Control for letter-spacing.
param: {Object} props Component props.param: {boolean} props.__next40pxDefaultSize Start opting into the larger default height that will become the default size in a future version.param: {string} props.value Currently selected letter-spacing.param: {Function} props.onChange Handles change in letter-spacing selection.param: {string|number|undefined} props.__unstableInputWidth Input width to pass through to inner UnitControl. Should be a valid CSS value.return: {Element} Letter-spacing control.
Prop types 2 prop types
Component: ../packages/block-editor/src/components/letter-spacing-control/index.js::default
Props:
__next40pxDefaultSize?: any = false

__unstableInputWidth?: any = '60px'
Imports
import { LetterSpacingControl } from "@wordpress/block-editor";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState( '' );

    return (
        <LetterSpacingControl
            __next40pxDefaultSize
            value={ value }
            onChange={ ( newValue ) => {
                onChange( newValue );
                setValue( newValue );
            } } />
    );
};

LineHeightControl

blockeditor-lineheightcontrol · ../packages/block-editor/src/components/line-height-control/stories/index.story.jsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 2 prop types
Component: ../packages/block-editor/src/components/line-height-control/index.js::default
Props:
__next40pxDefaultSize?: any = false

__unstableInputWidth?: any = '60px'
Imports
import { LineHeightControl } from "@wordpress/block-editor";
Default story ok
const Default = ( props ) => {
	const [ value, setValue ] = useState();
	return (
		<LineHeightControl onChange={ setValue } value={ value } { ...props } />
	);
};
Unconstrained Width story ok
const UnconstrainedWidth = ( props ) => {
	const [ value, setValue ] = useState();
	return (
		<LineHeightControl onChange={ setValue } value={ value } { ...props } />
	);
};

Link

design-system-components-link · ../packages/ui/src/link/stories/index.story.tsx
A styled anchor element with support for semantic color tones and an unstyled escape hatch.
Prop types 4 prop types
Component: ../packages/ui/src/link/link.tsx::Link
Props:
/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

/**
 * Whether to open the link in a new browser tab.
 * When true, sets `target="_blank"`, appends a visual arrow indicator,
 * and prevents navigation for internal anchors (`#`-prefixed hrefs).
 * 
 * @default false
 */
openInNewTab?: boolean = false

/**
 * The tone of the link. Tone describes a semantic color intent.
 * Only applies when `variant` is `default`.
 * 
 * @default "brand"
 */
tone?: 'brand' | 'neutral' = 'brand'

/**
 * The visual treatment of the link.
 * 
 * - `default`: Applies tone-based color and underline styles.
 * - `unstyled`: Strips all visual styles so consumers can bring their own.
 * 
 * @default "default"
 */
variant?: 'default' | 'unstyled' = 'default'
Imports
import { Link, Stack, Text } from "@wordpress/ui";
Default story ok
const Default = () => <Link href="#">Learn more</Link>;
All Tones And Variants story ok
Note: `tone` has no effect on `unstyled` variant
const AllTonesAndVariants = ( args ) => (
    <Stack direction="column" gap="lg">
        { ( [ 'brand', 'neutral' ] as const ).map( ( tone ) =>
            ( [ 'default', 'unstyled' ] as const ).map( ( variant ) => (
                <Stack
                    direction="column"
                    gap="xs"
                    key={ `${ tone }-${ variant }` }
                >
                    <Text variant="heading-sm">
                        { tone } tone, { variant } variant
                    </Text>
                    <Link { ...args } tone={ tone } variant={ variant } />
                </Stack>
            ) )
        ) }
    </Stack>
);
Inline story ok
const Inline = () => <Text variant="body-md" render={ <p /> }>This is a paragraph with an <Link>inline link</Link>that inherits its
                typography from the parent Text component.
            </Text>;
Standalone story ok
When composing `Text` and `Link` via the `render` prop, the order matters: - `<Text render={ <Link /> } />` renders an `<a>` element (Link's default tag wins). - `<Link render={ <Text /> } />` renders a `<span>` element (Text's default tag wins).
const Standalone = ( args ) => (
    <Stack direction="column" gap="md">
        <Text variant="body-md" render={ <Link { ...args } /> }>
            A standalone link with body-md typography
        </Text>
        <Text variant="body-sm" render={ <Link { ...args } /> }>
            A standalone link with body-sm typography
        </Text>
    </Stack>
);

Menu

components-menu · ../packages/components/src/menu/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 5 prop types
Component: ../packages/components/src/menu/index.tsx
Props:
/**
 * The elements, which should include one instance of the `Menu.TriggerButton`
 * component and one instance of the `Menu.Popover` component.
 */
children?: Ariakit.MenuProviderProps[ 'children' ]

/**
 * Whether the menu popover and its contents should be visible by default.
 * 
 * Note: this prop will be overridden by the `open` prop if it is
 * provided (meaning the component will be used in "controlled" mode).
 * 
 * @default false
 */
defaultOpen?: Ariakit.MenuProviderProps[ 'defaultOpen' ]

/**
 * A callback that gets called when the `open` state changes.
 */
onOpenChange?: Ariakit.MenuProviderProps[ 'setOpen' ]

/**
 * Whether the menu popover and its contents should be visible.
 * Should be used in conjunction with `onOpenChange` in order to control
 * the open state of the menu popover.
 * 
 * Note: this prop will set the component in "controlled" mode, and it will
 * override the `defaultOpen` prop.
 */
open?: Ariakit.MenuProviderProps[ 'open' ]

/**
 * The placement of the menu popover.
 * 
 * @default 'bottom-start' for root-level menus, 'right-start' for submenus
 */
placement?: Ariakit.MenuProviderProps[ 'placement' ]
Imports
import {
    Button,
    ContextSystemProvider,
    Icon,
    Menu,
    Modal,
    Provider as SlotFillProvider,
} from "@wordpress/components";
Default story ok
const Default = () => <Menu onOpenChange={fn()}>(<>
        <Menu.TriggerButton
            render={
                <Button __next40pxDefaultSize variant="secondary" />
            }
        >
            Open menu
        </Menu.TriggerButton>
        <Menu.Popover>
            <Menu.Item>
                <Menu.ItemLabel>Label</Menu.ItemLabel>
            </Menu.Item>
            <Menu.Item>
                <Menu.ItemLabel>Label</Menu.ItemLabel>
                <Menu.ItemHelpText>Help text</Menu.ItemHelpText>
            </Menu.Item>
            <Menu.Item>
                <Menu.ItemLabel>Label</Menu.ItemLabel>
                <Menu.ItemHelpText>
                    The menu item help text is automatically truncated
                    when there are more than two lines of text
                </Menu.ItemHelpText>
            </Menu.Item>
            <Menu.Item hideOnClick={ false }>
                <Menu.ItemLabel>Label</Menu.ItemLabel>
                <Menu.ItemHelpText>
                    This item doesn&apos;t close the menu on click
                </Menu.ItemHelpText>
            </Menu.Item>
            <Menu.Item disabled>Disabled item</Menu.Item>
            <Menu.Separator />
            <Menu.Group>
                <Menu.GroupLabel>Group label</Menu.GroupLabel>
                <Menu.Item
                    prefix={ <Icon icon={ customLink } size={ 24 } /> }
                >
                    <Menu.ItemLabel>With prefix</Menu.ItemLabel>
                </Menu.Item>
                <Menu.Item suffix="⌘S">With suffix</Menu.Item>
                <Menu.Item
                    disabled
                    prefix={
                        <Icon icon={ formatCapitalize } size={ 24 } />
                    }
                    suffix="⌥⌘T"
                >
                    <Menu.ItemLabel>
                        Disabled with prefix and suffix
                    </Menu.ItemLabel>
                    <Menu.ItemHelpText>And help text</Menu.ItemHelpText>
                </Menu.Item>
            </Menu.Group>
        </Menu.Popover>
    </>)</Menu>;
With Submenu story ok
const WithSubmenu = () => <Menu onOpenChange={fn()}>(<>
        <Menu.TriggerButton
            render={
                <Button __next40pxDefaultSize variant="secondary" />
            }
        >
            Open menu
        </Menu.TriggerButton>
        <Menu.Popover>
            <Menu.Item>Level 1 item</Menu.Item>
            <Menu>
                <Menu.SubmenuTriggerItem suffix="Suffix">
                    <Menu.ItemLabel>
                        Submenu trigger item with a long label
                    </Menu.ItemLabel>
                </Menu.SubmenuTriggerItem>
                <Menu.Popover>
                    <Menu.Item>
                        <Menu.ItemLabel>Level 2 item</Menu.ItemLabel>
                    </Menu.Item>
                    <Menu.Item>
                        <Menu.ItemLabel>Level 2 item</Menu.ItemLabel>
                    </Menu.Item>
                    <Menu>
                        <Menu.SubmenuTriggerItem>
                            <Menu.ItemLabel>
                                Submenu trigger
                            </Menu.ItemLabel>
                        </Menu.SubmenuTriggerItem>
                        <Menu.Popover>
                            <Menu.Item>
                                <Menu.ItemLabel>
                                    Level 3 item
                                </Menu.ItemLabel>
                            </Menu.Item>
                            <Menu.Item>
                                <Menu.ItemLabel>
                                    Level 3 item
                                </Menu.ItemLabel>
                            </Menu.Item>
                        </Menu.Popover>
                    </Menu>
                </Menu.Popover>
            </Menu>
        </Menu.Popover>
    </>)</Menu>;
With Checkboxes story ok
const WithCheckboxes = function WithCheckboxes( props: Props ) {
    const [ isAChecked, setAChecked ] = useState( false );
    const [ isBChecked, setBChecked ] = useState( true );
    const [ multipleCheckboxesValue, setMultipleCheckboxesValue ] =
        useState< string[] >( [ 'b' ] );

    const onMultipleCheckboxesCheckedChange: React.ComponentProps<
        typeof Menu.CheckboxItem
    >[ 'onChange' ] = ( e ) => {
        setMultipleCheckboxesValue( ( prevValues ) => {
            if ( prevValues.includes( e.target.value ) ) {
                return prevValues.filter(
                    ( val ) => val !== e.target.value
                );
            }
            return [ ...prevValues, e.target.value ];
        } );
    };

    return (
        <Menu { ...props }>
            <Menu.TriggerButton
                render={
                    <Button __next40pxDefaultSize variant="secondary" />
                }
            >
                Open menu
            </Menu.TriggerButton>
            <Menu.Popover>
                <Menu.Group>
                    <Menu.GroupLabel>
                        Single selection, uncontrolled
                    </Menu.GroupLabel>
                    <Menu.CheckboxItem
                        name="checkbox-individual-uncontrolled-a"
                        value="a"
                        suffix="⌥⌘T"
                    >
                        <Menu.ItemLabel>Checkbox item A</Menu.ItemLabel>
                        <Menu.ItemHelpText>
                            Initially unchecked
                        </Menu.ItemHelpText>
                    </Menu.CheckboxItem>
                    <Menu.CheckboxItem
                        name="checkbox-individual-uncontrolled-b"
                        value="b"
                        defaultChecked
                    >
                        <Menu.ItemLabel>Checkbox item B</Menu.ItemLabel>
                        <Menu.ItemHelpText>
                            Initially checked
                        </Menu.ItemHelpText>
                    </Menu.CheckboxItem>
                </Menu.Group>
                <Menu.Separator />
                <Menu.Group>
                    <Menu.GroupLabel>
                        Single selection, controlled
                    </Menu.GroupLabel>
                    <Menu.CheckboxItem
                        name="checkbox-individual-controlled-a"
                        value="a"
                        checked={ isAChecked }
                        onChange={ ( e ) => {
                            setAChecked( e.target.checked );
                        } }
                    >
                        <Menu.ItemLabel>Checkbox item A</Menu.ItemLabel>
                        <Menu.ItemHelpText>
                            Initially unchecked
                        </Menu.ItemHelpText>
                    </Menu.CheckboxItem>
                    <Menu.CheckboxItem
                        name="checkbox-individual-controlled-b"
                        value="b"
                        checked={ isBChecked }
                        onChange={ ( e ) =>
                            setBChecked( e.target.checked )
                        }
                    >
                        <Menu.ItemLabel>Checkbox item B</Menu.ItemLabel>
                        <Menu.ItemHelpText>
                            Initially checked
                        </Menu.ItemHelpText>
                    </Menu.CheckboxItem>
                </Menu.Group>
                <Menu.Separator />
                <Menu.Group>
                    <Menu.GroupLabel>
                        Multiple selection, uncontrolled
                    </Menu.GroupLabel>
                    <Menu.CheckboxItem
                        name="checkbox-multiple-uncontrolled"
                        value="a"
                    >
                        <Menu.ItemLabel>Checkbox item A</Menu.ItemLabel>
                        <Menu.ItemHelpText>
                            Initially unchecked
                        </Menu.ItemHelpText>
                    </Menu.CheckboxItem>
                    <Menu.CheckboxItem
                        name="checkbox-multiple-uncontrolled"
                        value="b"
                        defaultChecked
                    >
                        <Menu.ItemLabel>Checkbox item B</Menu.ItemLabel>
                        <Menu.ItemHelpText>
                            Initially checked
                        </Menu.ItemHelpText>
                    </Menu.CheckboxItem>
                </Menu.Group>
                <Menu.Separator />
                <Menu.Group>
                    <Menu.GroupLabel>
                        Multiple selection, controlled
                    </Menu.GroupLabel>
                    <Menu.CheckboxItem
                        name="checkbox-multiple-controlled"
                        value="a"
                        checked={ multipleCheckboxesValue.includes( 'a' ) }
                        onChange={ onMultipleCheckboxesCheckedChange }
                    >
                        <Menu.ItemLabel>Checkbox item A</Menu.ItemLabel>
                        <Menu.ItemHelpText>
                            Initially unchecked
                        </Menu.ItemHelpText>
                    </Menu.CheckboxItem>
                    <Menu.CheckboxItem
                        name="checkbox-multiple-controlled"
                        value="b"
                        checked={ multipleCheckboxesValue.includes( 'b' ) }
                        onChange={ onMultipleCheckboxesCheckedChange }
                    >
                        <Menu.ItemLabel>Checkbox item B</Menu.ItemLabel>
                        <Menu.ItemHelpText>
                            Initially checked
                        </Menu.ItemHelpText>
                    </Menu.CheckboxItem>
                </Menu.Group>
            </Menu.Popover>
        </Menu>
    );
};
With Radios story ok
const WithRadios = function WithRadios( props: Props ) {
    const [ radioValue, setRadioValue ] = useState( 'two' );
    const onRadioChange: React.ComponentProps<
        typeof Menu.RadioItem
    >[ 'onChange' ] = ( e ) => setRadioValue( e.target.value );

    return (
        <Menu { ...props }>
            <Menu.TriggerButton
                render={
                    <Button __next40pxDefaultSize variant="secondary" />
                }
            >
                Open menu
            </Menu.TriggerButton>
            <Menu.Popover>
                <Menu.Group>
                    <Menu.GroupLabel>Uncontrolled</Menu.GroupLabel>
                    <Menu.RadioItem name="radio-uncontrolled" value="one">
                        <Menu.ItemLabel>Radio item 1</Menu.ItemLabel>
                        <Menu.ItemHelpText>
                            Initially unchecked
                        </Menu.ItemHelpText>
                    </Menu.RadioItem>
                    <Menu.RadioItem
                        name="radio-uncontrolled"
                        value="two"
                        defaultChecked
                    >
                        <Menu.ItemLabel>Radio item 2</Menu.ItemLabel>
                        <Menu.ItemHelpText>
                            Initially checked
                        </Menu.ItemHelpText>
                    </Menu.RadioItem>
                </Menu.Group>
                <Menu.Separator />
                <Menu.Group>
                    <Menu.GroupLabel>Controlled</Menu.GroupLabel>
                    <Menu.RadioItem
                        name="radio-controlled"
                        value="one"
                        checked={ radioValue === 'one' }
                        onChange={ onRadioChange }
                    >
                        <Menu.ItemLabel>Radio item 1</Menu.ItemLabel>
                        <Menu.ItemHelpText>
                            Initially unchecked
                        </Menu.ItemHelpText>
                    </Menu.RadioItem>
                    <Menu.RadioItem
                        name="radio-controlled"
                        value="two"
                        checked={ radioValue === 'two' }
                        onChange={ onRadioChange }
                    >
                        <Menu.ItemLabel>Radio item 2</Menu.ItemLabel>
                        <Menu.ItemHelpText>
                            Initially checked
                        </Menu.ItemHelpText>
                    </Menu.RadioItem>
                </Menu.Group>
            </Menu.Popover>
        </Menu>
    );
};
With Modals story ok
const WithModals = function WithModals( props: Props ) {
    const [ isOuterModalOpen, setOuterModalOpen ] = useState( false );
    const [ isInnerModalOpen, setInnerModalOpen ] = useState( false );

    const cx = useCx();
    const modalOverlayClassName = cx( modalOnTopOfMenuPopover );

    return (
        <>
            <Menu { ...props }>
                <Menu.TriggerButton
                    render={
                        <Button __next40pxDefaultSize variant="secondary" />
                    }
                >
                    Open menu
                </Menu.TriggerButton>
                <Menu.Popover>
                    <Menu.Item
                        onClick={ () => setOuterModalOpen( true ) }
                        hideOnClick={ false }
                    >
                        <Menu.ItemLabel>Open outer modal</Menu.ItemLabel>
                    </Menu.Item>
                    <Menu.Item
                        onClick={ () => setInnerModalOpen( true ) }
                        hideOnClick={ false }
                    >
                        <Menu.ItemLabel>Open inner modal</Menu.ItemLabel>
                    </Menu.Item>
                    { isInnerModalOpen && (
                        <Modal
                            onRequestClose={ () =>
                                setInnerModalOpen( false )
                            }
                            overlayClassName={ modalOverlayClassName }
                        >
                            Modal&apos;s contents
                            <button
                                onClick={ () => setInnerModalOpen( false ) }
                            >
                                Close
                            </button>
                        </Modal>
                    ) }
                </Menu.Popover>
            </Menu>
            { isOuterModalOpen && (
                <Modal
                    onRequestClose={ () => setOuterModalOpen( false ) }
                    overlayClassName={ modalOverlayClassName }
                >
                    Modal&apos;s contents
                    <button onClick={ () => setOuterModalOpen( false ) }>
                        Close
                    </button>
                </Modal>
            ) }
        </>
    );
};
With Slot Fill story ok
const WithSlotFill = ( props: Props ) => {
    return (
        <SlotFillProvider>
            <Menu { ...props }>
                <Menu.TriggerButton
                    render={
                        <Button __next40pxDefaultSize variant="secondary" />
                    }
                >
                    Open menu
                </Menu.TriggerButton>
                <Menu.Popover>
                    <Menu.Item>
                        <Menu.ItemLabel>Item</Menu.ItemLabel>
                    </Menu.Item>
                    <Slot />
                </Menu.Popover>
            </Menu>

            <Fill>
                <Menu.Item>
                    <Menu.ItemLabel>Item from fill</Menu.ItemLabel>
                </Menu.Item>
                <Menu>
                    <Menu.SubmenuTriggerItem>
                        <Menu.ItemLabel>Submenu from fill</Menu.ItemLabel>
                    </Menu.SubmenuTriggerItem>
                    <Menu.Popover>
                        <Menu.Item>
                            <Menu.ItemLabel>
                                Submenu item from fill
                            </Menu.ItemLabel>
                        </Menu.Item>
                    </Menu.Popover>
                </Menu>
            </Fill>
        </SlotFillProvider>
    );
};
Toolbar Variant story ok
const ToolbarVariant = ( props: Props ) => (
    // TODO: add toolbar
    (<ContextSystemProvider value={ toolbarVariantContextValue }>
        <Menu { ...props }>
            <Menu.TriggerButton
                render={
                    <Button __next40pxDefaultSize variant="secondary" />
                }
            >
                Open menu
            </Menu.TriggerButton>
            <Menu.Popover>
                <Menu.Item>
                    <Menu.ItemLabel>Level 1 item</Menu.ItemLabel>
                </Menu.Item>
                <Menu.Item>
                    <Menu.ItemLabel>Level 1 item</Menu.ItemLabel>
                </Menu.Item>
                <Menu.Separator />
                <Menu>
                    <Menu.SubmenuTriggerItem>
                        <Menu.ItemLabel>Submenu trigger</Menu.ItemLabel>
                    </Menu.SubmenuTriggerItem>
                    <Menu.Popover>
                        <Menu.Item>
                            <Menu.ItemLabel>Level 2 item</Menu.ItemLabel>
                        </Menu.Item>
                    </Menu.Popover>
                </Menu>
            </Menu.Popover>
        </Menu>
    </ContextSystemProvider>)
);
Inside Modal story ok
const InsideModal = function InsideModal( props: Props ) {
    const [ isModalOpen, setModalOpen ] = useState( false );
    return (
        <>
            <Button
                onClick={ () => setModalOpen( true ) }
                __next40pxDefaultSize
                variant="secondary"
            >
                Open modal
            </Button>
            { isModalOpen && (
                <Modal
                    onRequestClose={ () => setModalOpen( false ) }
                    title="Menu inside modal"
                >
                    <Menu { ...props }>
                        <Menu.TriggerButton
                            render={
                                <Button
                                    __next40pxDefaultSize
                                    variant="secondary"
                                />
                            }
                        >
                            Open menu
                        </Menu.TriggerButton>
                        <Menu.Popover>
                            <Menu.Item>
                                <Menu.ItemLabel>
                                    Level 1 item
                                </Menu.ItemLabel>
                            </Menu.Item>
                            <Menu.Item>
                                <Menu.ItemLabel>
                                    Level 1 item
                                </Menu.ItemLabel>
                            </Menu.Item>
                            <Menu.Separator />
                            <Menu>
                                <Menu.SubmenuTriggerItem>
                                    <Menu.ItemLabel>
                                        Submenu trigger
                                    </Menu.ItemLabel>
                                </Menu.SubmenuTriggerItem>
                                <Menu.Popover>
                                    <Menu.Item>
                                        <Menu.ItemLabel>
                                            Level 2 item
                                        </Menu.ItemLabel>
                                    </Menu.Item>
                                </Menu.Popover>
                            </Menu>
                        </Menu.Popover>
                    </Menu>
                    <Button
                        __next40pxDefaultSize
                        onClick={ () => setModalOpen( false ) }
                    >
                        Close modal
                    </Button>
                </Modal>
            ) }
        </>
    );
};

MenuGroup

components-menugroup · ../packages/components/src/menu-group/stories/index.story.tsx
`MenuGroup` wraps a series of related `MenuItem` components into a common section. ```jsx import { MenuGroup, MenuItem } from '@wordpress/components'; const MyMenuGroup = () => ( <MenuGroup label="Settings"> <MenuItem>Setting 1</MenuItem> <MenuItem>Setting 2</MenuItem> </MenuGroup> ); ```
Prop types 4 prop types
Component: ../packages/components/src/menu-group/index.tsx::MenuGroup
Props:
/**
 * The children elements.
 */
children?: ReactNode

/**
 * A CSS `class` to give to the container element.
 */
className?: string

/**
 * Hide the top border on the container.
 */
hideSeparator?: boolean

/**
 * Text to be displayed as the menu group header.
 */
label?: string
Imports
import { MenuGroup, MenuItem, MenuItemsChoice } from "@wordpress/components";
Default story ok
const Default = () => {
    return (
        <MenuGroup>
            <MenuItem>Menu Item 1</MenuItem>
            <MenuItem>Menu Item 2</MenuItem>
        </MenuGroup>
    );
};
With Separator story ok
When other menu items exist above or below a MenuGroup, the group should have a divider line between it and the adjacent item.
const WithSeparator = () => {
    const [ mode, setMode ] = useState( 'visual' );
    const choices = [
		{
			value: 'visual',
			label: 'Visual editor',
		},
		{
			value: 'text',
			label: 'Code editor',
		},
	];

    return (
        <>
            <MenuGroup label="View">
                <MenuItem>Top Toolbar</MenuItem>
                <MenuItem>Spotlight Mode</MenuItem>
                <MenuItem>Distraction Free</MenuItem>
            </MenuGroup>
            <MenuGroup hideSeparator={false} label="Editor">
                <MenuItemsChoice
                    choices={ choices }
                    value={ mode }
                    onSelect={ ( newMode: string ) => setMode( newMode ) }
                    onHover={ () => {} } />
            </MenuGroup>
        </>
    );
};

MenuItem

components-menuitem · ../packages/components/src/menu-item/stories/index.story.tsx
MenuItem is a component which renders a button intended to be used in combination with the `DropdownMenu` component. ```jsx import { MenuItem } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyMenuItem = () => { const [ isActive, setIsActive ] = useState( true ); return ( <MenuItem icon={ isActive ? 'yes' : 'no' } isSelected={ isActive } role="menuitemcheckbox" onClick={ () => setIsActive( ( state ) => ! state ) } > Toggle </MenuItem> ); }; ```
Imports
import { MenuGroup, MenuItem, Shortcut } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	return (
		<MenuGroup>
			<MenuItem { ...props }>Menu Item 1</MenuItem>
		</MenuGroup>
	);
};
Is Selected story ok
When the `role` prop is either `"menuitemcheckbox"` or `"menuitemradio"`, the `isSelected` prop should be used so screen readers can tell which item is currently selected.
const IsSelected = ( props ) => {
	return (
		<MenuGroup>
			<MenuItem { ...props }>Menu Item 1</MenuItem>
		</MenuGroup>
	);
};
With Icon story ok
const WithIcon = ( props ) => {
	return (
		<MenuGroup>
			<MenuItem { ...props }>Menu Item 1</MenuItem>
		</MenuGroup>
	);
};
With Info story ok
const WithInfo = ( props ) => {
	return (
		<MenuGroup>
			<MenuItem { ...props }>Menu Item 1</MenuItem>
		</MenuGroup>
	);
};
With Suffix story ok
const WithSuffix = ( props ) => {
	return (
		<MenuGroup>
			<MenuItem { ...props }>Menu Item 1</MenuItem>
		</MenuGroup>
	);
};

MenuItemsChoice

components-menuitemschoice · ../packages/components/src/menu-items-choice/stories/index.story.tsx
`MenuItemsChoice` functions similarly to a set of `MenuItem`s, but allows the user to select one option from a set of multiple choices. ```jsx import { MenuGroup, MenuItemsChoice } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyMenuItemsChoice = () => { const [ mode, setMode ] = useState( 'visual' ); const choices = [ { value: 'visual', label: 'Visual editor', }, { value: 'text', label: 'Code editor', }, ]; return ( <MenuGroup label="Editor"> <MenuItemsChoice choices={ choices } value={ mode } onSelect={ ( newMode ) => setMode( newMode ) } /> </MenuGroup> ); }; ```
Prop types 4 prop types
Component: ../packages/components/src/menu-items-choice/index.tsx::default
Props:
/**
 * Array of choices.
 * 
 * @default []
 */
choices?: unknown = []

/**
 * Callback function to be called with a choice when user
 * hovers over a new choice (will be empty on mouse leave).
 * 
 * @default noop
 */
onHover?: ( value: string | null ) => void = () => {}

/**
 * Callback function to be called with the selected choice when user
 * selects a new choice.
 */
onSelect: ( value: string ) => void

/**
 * Value of currently selected choice (should match a `value` property
 * from a choice in `choices`).
 */
value: string
Imports
import { MenuGroup, MenuItemsChoice } from "@wordpress/components";
Default story ok
const Default = ( {
	onHover,
	onSelect,
	choices,
} ) => {
	const [ choice, setChoice ] = useState( choices[ 0 ]?.value ?? '' );

	return (
		<MenuGroup label="Editor">
			<MenuItemsChoice
				choices={ choices }
				value={ choice }
				onSelect={ ( ...selectArgs ) => {
					onSelect( ...selectArgs );
					setChoice( ...selectArgs );
				} }
				onHover={ onHover }
			/>
		</MenuGroup>
	);
};

Modal

components-modal · ../packages/components/src/modal/stories/index.story.tsx
Modals give users information and choices related to a task they’re trying to accomplish. They can contain critical information, require decisions, or involve multiple tasks. ```jsx import { Button, Modal } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyModal = () => { const [ isOpen, setOpen ] = useState( false ); const openModal = () => setOpen( true ); const closeModal = () => setOpen( false ); return ( <> <Button variant="secondary" onClick={ openModal }> Open Modal </Button> { isOpen && ( <Modal title="This is my modal" onRequestClose={ closeModal }> <Button variant="secondary" onClick={ closeModal }> My custom close button </Button> </Modal> ) } </> ); }; ```
Prop types 21 prop types
Component: ../packages/components/src/modal/index.tsx::Modal
Props:
/**
 * When set to `true`, the Modal's header (including the icon, title and
 * close button) will not be rendered.
 * 
 * _Warning_: This property is still experimental. “Experimental” means this
 * is an early implementation subject to drastic and breaking changes.
 * 
 * @default false
 */
__experimentalHideHeader?: boolean

aria?: {
	/**
	 * If this property is added, it will be added to the modal content
	 * `div` as `aria-describedby`.
	 */
	describedby?: string;
	/**
	 * If this property is added, it will be added to the modal content
	 * `div` as `aria-labelledby`. Use this when you are rendering the title
	 * yourself within the modal's content area instead of using the `title`
	 * prop. This ensures the title is usable by assistive technology.
	 *
	 * Titles are required for accessibility reasons, see `contentLabel` and
	 * `title` for other ways to provide a title.
	 */
	labelledby?: string;
}

/**
 * Class name added to the body element when the modal is open.
 * 
 * @default 'modal-open'
 */
bodyOpenClassName?: string

/**
 * The children elements.
 */
children: React.ReactNode

/**
 * If this property is added, it will an additional class name to the modal
 * content `div`.
 */
className?: string

/**
 * Label on the close button.
 * 
 * @default `__( 'Close' )`
 */
closeButtonLabel?: string

/**
 * If this property is added, it will be added to the modal content `div` as
 * `aria-label`.
 * 
 * Titles are required for accessibility reasons, see `aria.labelledby` and
 * `title` for other ways to provide a title.
 */
contentLabel?: string

/**
 * Determines focus behavior when the modal opens.
 * 
 * - `"firstElement"` focuses the first tabbable element within.
 * - `"firstInputElement"` focuses the first value control within.
 * - `"firstContentElement"` focuses the first tabbable element within the modal’s content element.
 * - `true` focuses the element itself.
 * - `false` does nothing and _should not be used unless an accessible
 *    substitute behavior is implemented_.
 * 
 * @default true
 */
focusOnMount?: useFocusOnMount.Mode | 'firstContentElement'

/**
 * Elements that are injected into the modal header to the left of the close button (if rendered).
 * Hidden if `__experimentalHideHeader` is `true`.
 * 
 * @default null
 */
headerActions?: React.ReactNode

/**
 * If this property is added, an icon will be added before the title.
 */
icon?: React.JSX.Element

/**
 * If this property is set to false, the modal will not display a close icon
 * and cannot be dismissed.
 * 
 * @default true
 */
isDismissible?: boolean

/**
 * This property when set to `true` will render a full screen modal.
 * 
 * @default false
 */
isFullScreen?: boolean

/**
 * Handle the key down on the modal frame `div`.
 */
onKeyDown?: React.KeyboardEventHandler< HTMLDivElement >

/**
 * This function is called to indicate that the modal should be closed.
 */
onRequestClose: (
	event?: React.KeyboardEvent< HTMLDivElement > | React.SyntheticEvent
) => void

/**
 * If this property is added, it will an additional class name to the modal
 * overlay `div`.
 */
overlayClassName?: string

/**
 * If this property is added, it will override the default role of the
 * modal.
 * 
 * @default 'dialog'
 */
role?: React.AriaRole

/**
 * If this property is added, it will determine whether the modal requests
 * to close when a mouse click occurs outside of the modal content.
 * 
 * @default true
 */
shouldCloseOnClickOutside?: boolean

/**
 * If this property is added, it will determine whether the modal requests
 * to close when the escape key is pressed.
 * 
 * @default true
 */
shouldCloseOnEsc?: boolean

/**
 * If this property is added it will cause the modal to render at a preset
 * width, or expand to fill the screen. This prop will be ignored if
 * `isFullScreen` is set to `true`.
 * 
 * Note: `Modal`'s width can also be controlled by adjusting the width of the
 * modal's contents, or via CSS using the `style` prop.
 */
size?: 'small' | 'medium' | 'large' | 'fill'

/**
 * If this property is added, it will be added to the modal frame `div`.
 */
style?: React.CSSProperties

/**
 * This property is used as the modal header's title.
 * 
 * Titles are required for accessibility reasons, see `aria.labelledby` and
 * `contentLabel` for other ways to provide a title.
 */
title?: string
Imports
import { Button, InputControl, Modal } from "@wordpress/components";
Default story ok
const Default = ( { onRequestClose, ...args } ) => {
	const [ isOpen, setOpen ] = useState( false );
	const openModal = () => setOpen( true );
	const closeModal: ModalProps[ 'onRequestClose' ] = ( event ) => {
		setOpen( false );
		onRequestClose( event );
	};

	return (
		<>
			<Button
				__next40pxDefaultSize
				variant="secondary"
				onClick={ openModal }
			>
				Open Modal
			</Button>
			{ isOpen && (
				<Modal onRequestClose={ closeModal } { ...args }>
					<p>
						Lorem ipsum dolor sit amet, consectetur adipiscing elit,
						sed do eiusmod tempor incididunt ut labore et magna
						aliqua. Ut enim ad minim veniam, quis nostrud
						exercitation ullamco laboris nisi ut aliquip ex ea ea
						commodo consequat. Duis aute irure dolor in
						reprehenderit in voluptate velit esse cillum dolore eu
						fugiat nulla pariatur. Excepteur sint occaecat cupidatat
						non proident, sunt in culpa qui officia deserunt mollit
						anim id est laborum.
					</p>

					<InputControl
						__next40pxDefaultSize
						style={ { marginBottom: '20px' } }
					/>

					<Button
						__next40pxDefaultSize
						variant="secondary"
						onClick={ closeModal }
					>
						Close Modal
					</Button>
				</Modal>
			) }
		</>
	);
};
With size: small story ok
const WithsizeSmall = ( { onRequestClose, ...args } ) => {
	const [ isOpen, setOpen ] = useState( false );
	const openModal = () => setOpen( true );
	const closeModal: ModalProps[ 'onRequestClose' ] = ( event ) => {
		setOpen( false );
		onRequestClose( event );
	};

	return (
		<>
			<Button
				__next40pxDefaultSize
				variant="secondary"
				onClick={ openModal }
			>
				Open Modal
			</Button>
			{ isOpen && (
				<Modal onRequestClose={ closeModal } { ...args }>
					<p>
						Lorem ipsum dolor sit amet, consectetur adipiscing elit,
						sed do eiusmod tempor incididunt ut labore et magna
						aliqua. Ut enim ad minim veniam, quis nostrud
						exercitation ullamco laboris nisi ut aliquip ex ea ea
						commodo consequat. Duis aute irure dolor in
						reprehenderit in voluptate velit esse cillum dolore eu
						fugiat nulla pariatur. Excepteur sint occaecat cupidatat
						non proident, sunt in culpa qui officia deserunt mollit
						anim id est laborum.
					</p>

					<InputControl
						__next40pxDefaultSize
						style={ { marginBottom: '20px' } }
					/>

					<Button
						__next40pxDefaultSize
						variant="secondary"
						onClick={ closeModal }
					>
						Close Modal
					</Button>
				</Modal>
			) }
		</>
	);
};
With Header Actions story ok
The `headerActions` prop can be used to add auxiliary actions to the header, for example a fullscreen mode toggle.
const WithHeaderActions = ( { onRequestClose, ...args } ) => {
	const [ isOpen, setOpen ] = useState( false );
	const openModal = () => setOpen( true );
	const closeModal: ModalProps[ 'onRequestClose' ] = ( event ) => {
		setOpen( false );
		onRequestClose( event );
	};

	return (
		<>
			<Button
				__next40pxDefaultSize
				variant="secondary"
				onClick={ openModal }
			>
				Open Modal
			</Button>
			{ isOpen && (
				<Modal onRequestClose={ closeModal } { ...args }>
					<p>
						Lorem ipsum dolor sit amet, consectetur adipiscing elit,
						sed do eiusmod tempor incididunt ut labore et magna
						aliqua. Ut enim ad minim veniam, quis nostrud
						exercitation ullamco laboris nisi ut aliquip ex ea ea
						commodo consequat. Duis aute irure dolor in
						reprehenderit in voluptate velit esse cillum dolore eu
						fugiat nulla pariatur. Excepteur sint occaecat cupidatat
						non proident, sunt in culpa qui officia deserunt mollit
						anim id est laborum.
					</p>

					<InputControl
						__next40pxDefaultSize
						style={ { marginBottom: '20px' } }
					/>

					<Button
						__next40pxDefaultSize
						variant="secondary"
						onClick={ closeModal }
					>
						Close Modal
					</Button>
				</Modal>
			) }
		</>
	);
};

NavigableMenu

components-navigablemenu · ../packages/components/src/navigable-container/stories/navigable-menu.story.tsx
A container for a navigable menu. ```jsx import { NavigableMenu, Button, } from '@wordpress/components'; function onNavigate( index, target ) { console.log( `Navigates to ${ index }`, target ); } const MyNavigableContainer = () => ( <div> <span>Navigable Menu:</span> <NavigableMenu onNavigate={ onNavigate } orientation="horizontal"> <Button variant="secondary">Item 1</Button> <Button variant="secondary">Item 2</Button> <Button variant="secondary">Item 3</Button> </NavigableMenu> </div> ); ```
Prop types 2 prop types
Component: ../packages/components/src/navigable-container/menu.tsx::NavigableMenu
Props:
orientation?: any = 'vertical'

role?: any = 'menu'
Imports
import { NavigableMenu } from "@wordpress/components";
Default story ok
const Default = () => {
    return (
        <>
            <button>Before navigable menu</button>
            <NavigableMenu
                onKeyDown={fn()}
                onNavigate={fn()}
                style={ {
					margin: '32px 0',
					padding: '16px',
					border: '1px solid black',
				} }>
                <div role="menuitem">Item 1 (non-tabbable, non-focusable)</div>
                <button role="menuitem">Item 2 (tabbable, focusable)</button>
                <button role="menuitem" disabled>Item 3 (disabled, therefore non-tabbable and not-focusable)
                                    </button>
                <span role="menuitem" tabIndex={ -1 }>Item 4 (non-tabbable, non-focusable)
                                    </span>
                <div role="menuitem" tabIndex={ 0 }>Item 5 (tabbable, focusable)
                                    </div>
            </NavigableMenu>
            <button>After navigable menu</button>
        </>
    );
};

Navigation

components-navigation · ../packages/components/src/navigation/stories/index.story.tsx
Render a navigation list with optional groupings and hierarchy. This component is deprecated. Consider using `Navigator` instead.
Prop types 5 prop types
Component: ../packages/components/src/navigation/index.tsx::Navigation
Props:
/**
 * The active item slug.
 */
activeItem?: string

/**
 * The active menu slug.
 * 
 * @default 'root'
 */
activeMenu?: string = 'root'

/**
 * The children components.
 */
children?: React.ReactNode

/**
 * Optional classname for the component.
 */
className?: string

/**
 * Callback used to sync the active menu between the external state
 * and the Navigation's internal state.
 */
onActivateMenu?: ( activeMenuSlug: string ) => void = () => {}
Imports
import { Navigation } from "@wordpress/components";
Default story ok
const _default = () => <Navigation onActivateMenu={fn()} />;
Controlled State story ok
const ControlledState = () => <Navigation onActivateMenu={fn()} />;
Groups story ok
const Groups = () => <Navigation onActivateMenu={fn()} />;
Search story ok
const Search = () => <Navigation onActivateMenu={fn()} />;
More Examples story ok
const MoreExamples = () => <Navigation onActivateMenu={fn()} />;
Hide If Empty story ok
const HideIfEmpty = () => <Navigation onActivateMenu={fn()} />;

Navigator

components-navigator · ../packages/components/src/navigator/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Button, HStack, Navigator, VStack } from "@wordpress/components";
Default story ok
const Default = () => <Navigator initialPath="/">(<>
        <Navigator.Screen path="/">
            <h2>This is the home screen.</h2>

            <VStack alignment="left">
                <Navigator.Button variant="primary" path="/child">
                    Go to child screen.
                </Navigator.Button>

                <Navigator.Button variant="primary" path="/product/1">
                    Go to dynamic path screen with id 1.
                </Navigator.Button>

                <Navigator.Button variant="primary" path="/product/2">
                    Go to dynamic path screen with id 2.
                </Navigator.Button>
            </VStack>
        </Navigator.Screen>
        <Navigator.Screen path="/child">
            <h2>This is the child screen.</h2>
            <HStack spacing={ 2 } alignment="left">
                <Navigator.BackButton variant="secondary">
                    Go back
                </Navigator.BackButton>

                <Navigator.Button
                    variant="primary"
                    path="/child/grandchild"
                >
                    Go to grand child screen.
                </Navigator.Button>
            </HStack>
        </Navigator.Screen>
        <Navigator.Screen path="/child/grandchild">
            <h2>This is the grand child screen.</h2>
            <Navigator.BackButton variant="secondary">
                Go back
            </Navigator.BackButton>
        </Navigator.Screen>
        <Navigator.Screen path="/product/:id">
            <DynamicScreen />
        </Navigator.Screen>
    </>)</Navigator>;
With Nested Initial Path story ok
const WithNestedInitialPath = () => <Navigator initialPath="/child/grandchild" />;
Skip Focus story ok
const SkipFocus = () => <Navigator initialPath="/">(<>
        <div
            style={ {
                height: 150,
                outline: '1px solid black',
                outlineOffset: '-1px',
                marginBlockEnd: '1rem',
                display: 'contents',
            } }
        >
            <Navigator.Screen path="/">
                <h2>Home screen</h2>
                <Navigator.Button variant="primary" path="/child">
                    Go to child screen.
                </Navigator.Button>
            </Navigator.Screen>

            <Navigator.Screen path="/child">
                <h2>Child screen</h2>
                <Navigator.BackButton variant="secondary">
                    Go back to home screen
                </Navigator.BackButton>
            </Navigator.Screen>
        </div>
        <NavigatorButtonWithSkipFocus path="/child">
            Go to child screen, but keep focus on this button
        </NavigatorButtonWithSkipFocus>
    </>)</Navigator>;

Notice

components-notice · ../packages/components/src/notice/stories/index.story.tsx
`Notice` is a component used to communicate feedback to the user. ```jsx import { Notice } from `@wordpress/components`; const MyNotice = () => ( <Notice status="error">An unknown error occurred.</Notice> ); ```
Prop types 10 prop types
Component: ../packages/components/src/notice/index.tsx::default
Props:
/**
 * Determines whether or not the message should be parsed as custom HTML
 * instead of a string.
 */
__unstableHTML?: boolean

/**
 * An array of action objects. Each member object should contain:
 * 
 * - `label`: `string` containing the text of the button/link
 * - `url`: `string` OR `onClick`: `( event: SyntheticEvent ) => void` to specify
 *    what the action does.
 * - `className`: `string` (optional) to add custom classes to the button styles.
 * - `noDefaultClasses`: `boolean` (optional) A value of `true` will remove all
 *    default styling.
 * - `variant`: `'primary' | 'secondary' | 'link'` (optional) You can denote a
 *    primary button action for a notice by passing a value of `primary`.
 * 
 * The default appearance of an action button is inferred based on whether
 * `url` or `onClick` are provided, rendering the button as a link if
 * appropriate. If both props are provided, `url` takes precedence, and the
 * action button will render as an anchor tag.
 * 
 * @default []
 */
actions?: Array< NoticeAction > = []

/**
 * The displayed message of a notice. Also used as the spoken message for
 * assistive technology, unless `spokenMessage` is provided as an alternative message.
 */
children: ReactNode

/**
 * A CSS `class` to give to the wrapper element.
 */
className?: string

/**
 * Whether the notice should be dismissible or not
 * 
 * @default true
 */
isDismissible?: boolean = true

/**
 * A deprecated alternative to `onRemove`. This prop is kept for
 * compatibility reasons but should be avoided.
 * 
 * @default noop
 */
onDismiss?: () => void = () => {}

/**
 * Function called when dismissing the notice
 * 
 * @default noop
 */
onRemove?: () => void = () => {}

/**
 * A politeness level for the notice's spoken message. Should be provided as
 * one of the valid options for an `aria-live` attribute value.
 * 
 * A value of `'assertive'` is to be used for important, and usually
 * time-sensitive, information. It will interrupt anything else the screen
 * reader is announcing in that moment.
 * A value of `'polite'` is to be used for advisory information. It should
 * not interrupt what the screen reader is announcing in that moment
 * (the "speech queue") or interrupt the current task.
 * 
 * Note that this value should be considered a suggestion; assistive
 * technologies may override it based on internal heuristics.
 * 
 * @see https://www.w3.org/TR/wai-aria-1.1/#aria-live
 * 
 * @default 'assertive' for 'error' status, 'polite' for all other statuses
 */
politeness?: 'polite' | 'assertive' = getDefaultPoliteness( status )

/**
 * Used to provide a custom spoken message in place of the `children` default.
 * 
 * @default `children`
 */
spokenMessage?: ReactNode = children

/**
 * Determines the color of the notice: `warning` (yellow),
 * `success` (green), `error` (red), or `'info'`.
 * By default `'info'` will be blue, but if there is a parent Theme component
 * with an accent color prop, the notice will take on that color instead.
 * 
 * @default 'info'
 */
status?: 'warning' | 'success' | 'error' | 'info' = 'info'
Imports
import { Button, Notice, NoticeList } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	return <Notice { ...props } />;
};
With Custom Spoken Message story ok
const WithCustomSpokenMessage = ( props ) => {
	return <Notice { ...props } />;
};
With JSX Children story ok
const WithJSXChildren = ( props ) => {
	return <Notice { ...props } />;
};
With Actions story ok
const WithActions = ( props ) => {
	return <Notice { ...props } />;
};
NoticeList Subcomponent story ok
const NoticeListSubcomponent = () => {
	const exampleNotices: NoticeListProps[ 'notices' ] = [
		{
			id: 'second-notice',
			content: 'second notice content',
		},
		{
			id: 'first-notice',
			content: 'first notice content',
			actions: [
				{
					label: 'Click me!',
					onClick: () => {},
					variant: 'primary',
				},
				{
					label: 'Or click me instead!',
					onClick: () => {},
				},
				{
					label: 'Or visit a link for more info',
					url: 'https://wordpress.org',
					variant: 'link',
				},
			],
		},
	];
	const [ notices, setNotices ] = useState( exampleNotices );

	const removeNotice = (
		id: NoticeListProps[ 'notices' ][ number ][ 'id' ]
	) => {
		setNotices( notices.filter( ( notice ) => notice.id !== id ) );
	};

	const resetNotices = () => {
		setNotices( exampleNotices );
	};

	return (
		<>
			<NoticeList notices={ notices } onRemove={ removeNotice } />
			<Button
				__next40pxDefaultSize
				variant="primary"
				onClick={ resetNotices }
			>
				Reset Notices
			</Button>
		</>
	);
};
With Disabled Action story ok
Action buttons can be disabled.
const WithDisabledAction = ( props ) => {
	return <Notice { ...props } />;
};

Notice.Root

design-system-components-notice · ../packages/ui/src/notice/stories/index.story.tsx
A notice component that communicates system status and provides actions. ```jsx import { Notice } from '@wordpress/ui'; function MyComponent() { return ( <Notice.Root intent="info"> <Notice.Title>Heading</Notice.Title> <Notice.Description>Body text</Notice.Description> <Notice.Actions> <Notice.ActionButton>Action</Notice.ActionButton> </Notice.Actions> <Notice.CloseIcon onClick={() => {}} /> </Notice.Root> ); } ```
Prop types 5 prop types
Component: ../packages/ui/src/notice/root.tsx::Root
Props:
/**
 * The content to be rendered inside the notice.
 */
children?: ReactNode

/**
 * Custom icon to override the default intent icon. Pass `null` to hide the icon.
 * Default icons by intent: neutral (none), info (info), warning (caution),
 * success (published), error (error).
 */
icon?: IconProps[ 'icon' ] | null

/**
 * The semantic intent of the notice, communicating its meaning through color.
 * Available intents: neutral, info, warning, success, and error.
 * 
 * @default 'neutral'
 */
intent?: 'warning' | 'success' | 'error' | 'info' | 'neutral' = 'neutral'

/**
 * The politeness level for screen reader announcements.
 * Defaults to 'assertive' for error intent, 'polite' for others.
 */
politeness?: 'polite' | 'assertive' = getDefaultPoliteness( intent )

/**
 * The message to be announced to screen readers. Defaults to the children content.
 * Used by the `speak()` function from `@wordpress/a11y`.
 */
spokenMessage?: ReactNode = children
Imports
import { ActionButton, ActionLink, Actions, CloseIcon, Description, Root, Title } from "@wordpress/ui";
Default story ok
const Default = () => <Notice.Root>(<>
        <Notice.Title>Notice Title</Notice.Title>
        <Notice.Description>
            Description text with details about this notification.
        </Notice.Description>
        <Notice.Actions>
            <Notice.ActionButton>Primary button</Notice.ActionButton>
            <Notice.ActionButton variant="outline">
                Secondary button
            </Notice.ActionButton>
            <Notice.ActionLink href="#">Link</Notice.ActionLink>
        </Notice.Actions>
        <Notice.CloseIcon />
    </>)</Notice.Root>;
Info story ok
const Info = () => <Notice.Root intent="info" />;
Warning story ok
const Warning = () => <Notice.Root intent="warning" />;
Success story ok
const Success = () => <Notice.Root intent="success" />;
Error story ok
const Error = () => <Notice.Root intent="error" />;
Non Dismissible story ok
Omit Notice.CloseIcon to make the notice non-dismissable.
const NonDismissible = () => <Notice.Root intent="warning">(<>
        <Notice.Title>Action Required</Notice.Title>
        <Notice.Description>
            This notice cannot be dismissed by the user.
        </Notice.Description>
        <Notice.Actions>
            <Notice.ActionButton>Take Action</Notice.ActionButton>
            <Notice.ActionLink href="#">Visit link</Notice.ActionLink>
        </Notice.Actions>
    </>)</Notice.Root>;
Without Icon story ok
Pass `icon={ null }` to hide the default decorative icon.
const WithoutIcon = () => <Notice.Root intent="info" icon={null}>(<>
        <Notice.Title>No Icon</Notice.Title>
        <Notice.Description>
            This notice has no decorative icon displayed.
        </Notice.Description>
        <Notice.CloseIcon />
    </>)</Notice.Root>;
Without Actions story ok
const WithoutActions = () => <Notice.Root intent="info">(<>
        <Notice.Title>Simple Notice</Notice.Title>
        <Notice.Description>
            A dismissable notice without any action buttons or links.
        </Notice.Description>
        <Notice.CloseIcon />
    </>)</Notice.Root>;
Title Only story ok
Title only, no description or actions.
const TitleOnly = () => <Notice.Root>(<>
        <Notice.Title>Just a title</Notice.Title>
        <Notice.CloseIcon />
    </>)</Notice.Root>;
Description Only story ok
Description only, no title or actions.
const DescriptionOnly = () => <Notice.Root intent="info">(<>
        <Notice.Description>
            Just a description without title or actions.
        </Notice.Description>
        <Notice.CloseIcon />
    </>)</Notice.Root>;

NumberControl

components-numbercontrol · ../packages/components/src/number-control/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { NumberControl } from "@wordpress/components";
Default story ok
const Default = ( {
	onChange,
	...props
} ) => {
	const [ value, setValue ] = useState< string | undefined >( '0' );
	const [ isValidValue, setIsValidValue ] = useState( true );

	return (
		<>
			<NumberControl
				__next40pxDefaultSize
				{ ...props }
				value={ value }
				onChange={ ( v, extra ) => {
					setValue( v );
					setIsValidValue(
						( extra.event.target as HTMLInputElement ).validity
							.valid
					);
					onChange?.( v, extra );
				} }
			/>
			<p>Is valid? { isValidValue ? 'Yes' : 'No' }</p>
		</>
	);
};

Overview

components-validated-form-controls-overview · ../packages/components/src/validated-form-controls/components/stories/overview.story.tsx
Prop type error
We could not detect the component from your story file. Specify meta.component.
  24 | import { VStack } from '../../../v-stack';
  25 |
> 26 | const meta: Meta< typeof ControlWithError > = {
     | ^
  27 | 	title: 'Components/Selection & Input/Validated Form Controls/Overview',
  28 | 	id: 'components-validated-form-controls-overview',
  29 | 	parameters: {

../packages/components/src/validated-form-controls/components/stories/overview.mdx:
/**
 * External dependencies
 */
import type { Meta, StoryObj } from '@storybook/react-vite';
import { expect, userEvent, waitFor, within } from 'storybook/test';
import clsx from 'clsx';

/**
 * WordPress dependencies
 */
import { useRef, useCallback, useState } from '@wordpress/element';
import { debounce } from '@wordpress/compose';

/**
 * Internal dependencies
 */
import { ValidatedInputControl } from '..';
import { formDecorator } from './story-utils';
import type { ControlWithError } from '../../control-with-error';
import Dropdown from '../../../dropdown';
import { Button } from '../../../button';
import Modal from '../../../modal';
import { HStack } from '../../../h-stack';
import { VStack } from '../../../v-stack';

const meta: Meta< typeof ControlWithError > = {
	title: 'Components/Selection & Input/Validated Form Controls/Overview',
	id: 'components-validated-form-controls-overview',
	parameters: {
		controls: { disable: true },
	},
};
export default meta;

type Story = StoryObj< typeof ControlWithError >;

/**
 * When there are multiple controls with errors, attempting to submit will
 * move focus to the first control with an error.
 */
export const WithMultipleControls: Story = {
	decorators: formDecorator,
	render: function Template() {
		const [ text, setText ] = useState< string | undefined >( '' );
		const [ text2, setText2 ] = useState< string | undefined >( '' );

		return (
			<>
				<ValidatedInputControl
					label="Text"
					required
					value={ text }
					help="The word 'error' will trigger an error."
					onChange={ setText }
					customValidity={
						text?.toLowerCase() === 'error'
							? {
									type: 'invalid',
									message: 'The word "error" is not allowed.',
							  }
							: undefined
					}
				/>
				<ValidatedInputControl
					label="Text"
					required
					value={ text2 }
					help="The word 'error' will trigger an error."
					onChange={ setText2 }
					customValidity={
						text2?.toLowerCase() === 'error'
							? {
									type: 'invalid',
									message: 'The word "error" is not allowed.',
							  }
							: undefined
					}
				/>
			</>
		);
	},
};

/**
 * Help text can be configured to be hidden when a custom error is reported. Whether to opt for this approach
 * will depend on context.
 */
export const WithHelpTextReplacement: Story = {
	decorators: formDecorator,
	render: function Template() {
		const [ text, setText ] = useState< string | undefined >( '' );
		const isInvalid = text?.toLowerCase() === 'error';

		return (
			<>
				<style>
					{ `
				.my-control:has(:invalid[data-validity-visible]) .my-control__help:not(.is-visible) {
					display: none;
				}
				` }
				</style>
				<ValidatedInputControl
					className="my-control"
					label="Text"
					required
					value={ text }
					help={
						<span
							className={ clsx(
								'my-control__help',
								! isInvalid && 'is-visible'
							) }
						>
							The word &quot;error&quot; is not allowed.
						</span>
					}
					onChange={ setText }
					customValidity={
						isInvalid
							? {
									type: 'invalid',
									message: 'The word "error" is not allowed.',
							  }
							: undefined
					}
				/>
			</>
		);
	},
};

/**
 * To provide feedback from server-side validation, the `customValidity` prop can be used
 * to show additional status indicators while waiting for the server response,
 * and after the response is received.
 *
 * These indicators are intended for asynchronous validation calls that may take more than 1 second to complete.
 * They may be unnecessary when responses are generally quick.
 */
export const AsyncValidation: StoryObj< typeof ValidatedInputControl > = {
	decorators: formDecorator,
	render: function Template( { ...args } ) {
		const [ text, setText ] = useState( '' );
		const [ customValidity, setCustomValidity ] =
			useState<
				React.ComponentProps<
					typeof ValidatedInputControl
				>[ 'customValidity' ]
			>( undefined );

		const timeoutRef =
			useRef< ReturnType< typeof setTimeout > >( undefined );

		// eslint-disable-next-line react-hooks/exhaustive-deps
		const debouncedValidate = useCallback(
			debounce( ( v ) => {
				if ( v === '' ) {
					return;
				}

				setCustomValidity( {
					type: 'validating',
					message: 'Validating...',
				} );

				timeoutRef.current = setTimeout( () => {
					if ( v?.toString().toLowerCase() === 'error' ) {
						setCustomValidity( {
							type: 'invalid',
							message: 'The word "error" is not allowed.',
						} );
					} else {
						setCustomValidity( {
							type: 'valid',
							message: 'Validated',
						} );
					}
				}, 1500 );
			}, 500 ),
			[]
		);

		return (
			<ValidatedInputControl
				{ ...args }
				value={ text }
				onChange={ ( newValue ) => {
					setText( newValue ?? '' );
					setCustomValidity( undefined );
					clearTimeout( timeoutRef.current );
					debouncedValidate( newValue );
				} }
				customValidity={ customValidity }
			/>
		);
	},
	args: {
		label: 'Text',
		help: 'The word "error" will trigger an error asynchronously.',
		required: true,
	},
};

// Not exported - Only for testing purposes.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const AsyncValidationWithTest: StoryObj< typeof ValidatedInputControl > = {
	...AsyncValidation,
	decorators: formDecorator,
	play: async ( { canvasElement } ) => {
		const canvas = within( canvasElement );
		await userEvent.click( canvas.getByRole( 'textbox' ) );
		await userEvent.type( canvas.getByRole( 'textbox' ), 'valid text', {
			delay: 10,
		} );
		await userEvent.tab();

		await waitFor(
			() => {
				expect( canvas.getByText( 'Validated' ) ).toBeVisible();
			},
			{ timeout: 2500 }
		);

		await new Promise( ( resolve ) => setTimeout( resolve, 500 ) );
		await userEvent.clear( canvas.getByRole( 'textbox' ) );

		await waitFor(
			() => {
				expect(
					canvas.getByText( 'Please fill out this field.' )
				).toBeVisible();
			},
			{ timeout: 2500 }
		);

		// Should not show validating state if there were no changes
		// after a valid/invalid state was already shown.
		await new Promise( ( resolve ) => setTimeout( resolve, 1500 ) );
		await expect(
			canvas.queryByText( 'Validating...' )
		).not.toBeInTheDocument();

		await userEvent.type( canvas.getByRole( 'textbox' ), 'e', {
			delay: 10,
		} );

		// Should not show valid state if server has not yet responded.
		await expect(
			canvas.queryByText( 'Validated' )
		).not.toBeInTheDocument();

		// Should show validating state when transitioning from invalid to valid.
		await waitFor(
			() => {
				expect( canvas.getByText( 'Validating...' ) ).toBeVisible();
			},
			{ timeout: 2500 }
		);

		await waitFor(
			() => {
				expect( canvas.getByText( 'Validated' ) ).toBeVisible();
			},
			{ timeout: 2500 }
		);

		await new Promise( ( resolve ) => setTimeout( resolve, 1000 ) );
		await userEvent.type( canvas.getByRole( 'textbox' ), 'rror', {
			delay: 10,
		} );

		await waitFor(
			() => {
				expect(
					canvas.getByText( 'The word "error" is not allowed.' )
				).toBeVisible();
			},
			{ timeout: 2500 }
		);
	},
};

/**
 * Custom validity errors are effective immediately, even when they are not yet visible
 * to the user. For example, in this form where the initial value is already invalid,
 * the error message will be shown to the user once the submit button is clicked,
 * even if the input has never been interacted with.
 */
export const CustomErrorsOnSubmit: StoryObj< typeof ValidatedInputControl > = {
	decorators: formDecorator,
	args: {
		label: 'Text',
		required: true,
		help: 'The word "error" will trigger an error.',
	},
	render: function Template( { ...args } ) {
		const [ text, setText ] = useState< string | undefined >( 'error' );

		return (
			<>
				<ValidatedInputControl
					{ ...args }
					value={ text }
					onChange={ setText }
					customValidity={
						text === 'error'
							? {
									type: 'invalid',
									message: 'The word "error" is not allowed.',
							  }
							: undefined
					}
				/>
			</>
		);
	},
};

/**
 * While it is recommended to rely on the built-in behavior for showing errors by
 * using a `form` element and `type="submit"` button around validated fields,
 * it is also possible to show errors at arbitrary times.
 * This can be done by calling the [`reportValidity()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reportValidity)
 * on a ref of the field itself, or the wrapping `form` element.
 */
export const ShowingErrorsAtArbitraryTimes: StoryObj<
	typeof ValidatedInputControl
> = {
	args: {
		label: 'Text',
		required: true,
		help: 'The word "error" will trigger an error.',
	},
	decorators: [],
	render: function Template( { ...args } ) {
		const [ text, setText ] = useState< string | undefined >( 'error' );
		const ref = useRef< HTMLInputElement >( null );

		return (
			<VStack spacing={ 4 } alignment="left">
				<ValidatedInputControl
					ref={ ref }
					{ ...args }
					value={ text }
					onChange={ setText }
					customValidity={
						text === 'error'
							? {
									type: 'invalid',
									message: 'The word "error" is not allowed.',
							  }
							: undefined
					}
				/>
				<Button
					__next40pxDefaultSize
					variant="secondary"
					onClick={ () => ref.current?.reportValidity() }
				>
					Report validity
				</Button>
			</VStack>
		);
	},
};

/**
 * A `form` wrapper and `type="submit"` button can be used to force validation when
 * the user tries to commit their changes, while still allowing the modal to be closed by canceling.
 * Optionally, the `shouldCloseOnClickOutside`, `isDismissible`, and `shouldCloseOnEsc` props
 * on `Modal` can be disabled to force users to more explicitly signal whether they are trying to
 * "submit close" or "cancel close" the dialog, as well as preventing data loss on accidental closures.
 */
export const ValidateInModal: StoryObj< typeof ValidatedInputControl > = {
	render: function Template( { ...args } ) {
		const [ isOpen, setIsOpen ] = useState( false );
		const [ text, setText ] = useState< string | undefined >( '' );

		return (
			<>
				<Button
					variant="secondary"
					__next40pxDefaultSize
					onClick={ () => setIsOpen( true ) }
				>
					Open in modal
				</Button>
				{ isOpen && (
					<Modal
						title="Dialog title"
						onRequestClose={ () => setIsOpen( false ) }
						shouldCloseOnClickOutside={ false }
						shouldCloseOnEsc={ false }
						isDismissible={ false }
					>
						<form
							onSubmit={ ( event ) => {
								event.preventDefault();
								setIsOpen( false );
							} }
						>
							<VStack spacing={ 2 }>
								<ValidatedInputControl
									{ ...args }
									value={ text }
									onChange={ setText }
									customValidity={
										text === 'error'
											? {
													type: 'invalid',
													message:
														'The word "error" is not allowed.',
											  }
											: undefined
									}
								/>

								<HStack justify="flex-end" spacing={ 2 }>
									<Button
										variant="tertiary"
										__next40pxDefaultSize
										onClick={ () => setIsOpen( false ) }
									>
										Cancel
									</Button>
									<Button
										variant="primary"
										__next40pxDefaultSize
										type="submit"
									>
										Save
									</Button>
								</HStack>
							</VStack>
						</form>
					</Modal>
				) }
			</>
		);
	},
	args: {
		label: 'Text',
		required: true,
		help: 'The word "error" will trigger an error.',
	},
};

/**
 * [Form methods](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement#instance_methods) like
 * `reportValidity()` can be used to validate the fields when a popover is about to be closed,
 * and prevent the closing of the popover when invalid.
 */
export const ValidateOnPopoverClose: StoryObj< typeof ValidatedInputControl > =
	{
		render: function Template( { ...args } ) {
			const [ isOpen, setIsOpen ] = useState( false );
			const formRef = useRef< HTMLFormElement >( null );
			const [ text, setText ] = useState< string | undefined >( '' );

			return (
				<Dropdown
					popoverProps={ { placement: 'bottom-start' } }
					open={ isOpen }
					onToggle={ ( willOpen ) => {
						if ( ! willOpen ) {
							const isValid = formRef.current?.reportValidity();
							setIsOpen( ! isValid );
						} else {
							setIsOpen( true );
						}
					} }
					renderContent={ () => (
						<form
							ref={ formRef }
							onSubmit={ ( event ) => {
								event.preventDefault();
								setIsOpen( false );
							} }
						>
							<ValidatedInputControl
								{ ...args }
								value={ text }
								onChange={ setText }
								customValidity={
									text === 'error'
										? {
												type: 'invalid',
												message:
													'The word "error" is not allowed.',
										  }
										: undefined
								}
							/>
						</form>
					) }
					renderToggle={ () => {
						return (
							<Button
								__next40pxDefaultSize
								variant="secondary"
								onClick={ () => setIsOpen( ! isOpen ) }
								aria-expanded={ isOpen }
							>
								Open in popover
							</Button>
						);
					} }
				/>
			);
		},
		args: {
			label: 'Text',
			help: 'The word "error" will trigger an error.',
			required: true,
			style: {
				width: '200px',
			},
		},
	};
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Button, Dropdown, HStack, Modal, ValidatedInputControl, VStack } from "@wordpress/components";
With Multiple Controls story ok
When there are multiple controls with errors, attempting to submit will move focus to the first control with an error.
const WithMultipleControls = function Template() {
    const [ text, setText ] = useState< string | undefined >( '' );
    const [ text2, setText2 ] = useState< string | undefined >( '' );

    return (
        <>
            <ValidatedInputControl
                label="Text"
                required
                value={ text }
                help="The word 'error' will trigger an error."
                onChange={ setText }
                customValidity={
                    text?.toLowerCase() === 'error'
                        ? {
                                type: 'invalid',
                                message: 'The word "error" is not allowed.',
                          }
                        : undefined
                }
            />
            <ValidatedInputControl
                label="Text"
                required
                value={ text2 }
                help="The word 'error' will trigger an error."
                onChange={ setText2 }
                customValidity={
                    text2?.toLowerCase() === 'error'
                        ? {
                                type: 'invalid',
                                message: 'The word "error" is not allowed.',
                          }
                        : undefined
                }
            />
        </>
    );
};
With Help Text Replacement story ok
Help text can be configured to be hidden when a custom error is reported. Whether to opt for this approach will depend on context.
const WithHelpTextReplacement = function Template() {
    const [ text, setText ] = useState< string | undefined >( '' );
    const isInvalid = text?.toLowerCase() === 'error';

    return (
        <>
            <style>
                { `
            .my-control:has(:invalid[data-validity-visible]) .my-control__help:not(.is-visible) {
                display: none;
            }
            ` }
            </style>
            <ValidatedInputControl
                className="my-control"
                label="Text"
                required
                value={ text }
                help={
                    <span
                        className={ clsx(
                            'my-control__help',
                            ! isInvalid && 'is-visible'
                        ) }
                    >
                        The word &quot;error&quot; is not allowed.
                    </span>
                }
                onChange={ setText }
                customValidity={
                    isInvalid
                        ? {
                                type: 'invalid',
                                message: 'The word "error" is not allowed.',
                          }
                        : undefined
                }
            />
        </>
    );
};
Async Validation story ok
To provide feedback from server-side validation, the `customValidity` prop can be used to show additional status indicators while waiting for the server response, and after the response is received. These indicators are intended for asynchronous validation calls that may take more than 1 second to complete. They may be unnecessary when responses are generally quick.
const AsyncValidation = () => {
    const [ text, setText ] = useState( '' );
    const [ customValidity, setCustomValidity ] =
        useState<
            React.ComponentProps<
                typeof ValidatedInputControl
            >[ 'customValidity' ]
        >( undefined );

    const timeoutRef =
        useRef< ReturnType< typeof setTimeout > >( undefined );

    // eslint-disable-next-line react-hooks/exhaustive-deps
    const debouncedValidate = useCallback(
        debounce( ( v ) => {
            if ( v === '' ) {
                return;
            }

            setCustomValidity( {
                type: 'validating',
                message: 'Validating...',
            } );

            timeoutRef.current = setTimeout( () => {
                if ( v?.toString().toLowerCase() === 'error' ) {
                    setCustomValidity( {
                        type: 'invalid',
                        message: 'The word "error" is not allowed.',
                    } );
                } else {
                    setCustomValidity( {
                        type: 'valid',
                        message: 'Validated',
                    } );
                }
            }, 1500 );
        }, 500 ),
        []
    );

    return (
        <ValidatedInputControl
            label="Text"
            help="The word \"error\" will trigger an error asynchronously."
            required
            value={ text }
            onChange={ ( newValue ) => {
                setText( newValue ?? '' );
                setCustomValidity( undefined );
                clearTimeout( timeoutRef.current );
                debouncedValidate( newValue );
            } }
            customValidity={ customValidity } />
    );
};
Custom Errors On Submit story ok
Custom validity errors are effective immediately, even when they are not yet visible to the user. For example, in this form where the initial value is already invalid, the error message will be shown to the user once the submit button is clicked, even if the input has never been interacted with.
const CustomErrorsOnSubmit = () => {
    const [ text, setText ] = useState< string | undefined >( 'error' );

    return (
        <>
            <ValidatedInputControl
                label="Text"
                required
                help="The word \"error\" will trigger an error."
                value={ text }
                onChange={ setText }
                customValidity={
                    text === 'error'
                        ? {
                                type: 'invalid',
                                message: 'The word "error" is not allowed.',
                          }
                        : undefined
                } />
        </>
    );
};
Showing Errors At Arbitrary Times story ok
While it is recommended to rely on the built-in behavior for showing errors by using a `form` element and `type="submit"` button around validated fields, it is also possible to show errors at arbitrary times. This can be done by calling the [`reportValidity()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reportValidity) on a ref of the field itself, or the wrapping `form` element.
const ShowingErrorsAtArbitraryTimes = () => {
    const [ text, setText ] = useState< string | undefined >( 'error' );
    const ref = useRef< HTMLInputElement >( null );

    return (
        <VStack spacing={ 4 } alignment="left">
            <ValidatedInputControl
                ref={ ref }
                label="Text"
                required
                help="The word \"error\" will trigger an error."
                value={ text }
                onChange={ setText }
                customValidity={
                    text === 'error'
                        ? {
                                type: 'invalid',
                                message: 'The word "error" is not allowed.',
                          }
                        : undefined
                } />
            <Button
                __next40pxDefaultSize
                variant="secondary"
                onClick={ () => ref.current?.reportValidity() }>Report validity
                                </Button>
        </VStack>
    );
};
Validate In Modal story ok
A `form` wrapper and `type="submit"` button can be used to force validation when the user tries to commit their changes, while still allowing the modal to be closed by canceling. Optionally, the `shouldCloseOnClickOutside`, `isDismissible`, and `shouldCloseOnEsc` props on `Modal` can be disabled to force users to more explicitly signal whether they are trying to "submit close" or "cancel close" the dialog, as well as preventing data loss on accidental closures.
const ValidateInModal = function Template( { ...args } ) {
    const [ isOpen, setIsOpen ] = useState( false );
    const [ text, setText ] = useState< string | undefined >( '' );

    return (
        <>
            <Button
                variant="secondary"
                __next40pxDefaultSize
                onClick={ () => setIsOpen( true ) }
            >
                Open in modal
            </Button>
            { isOpen && (
                <Modal
                    title="Dialog title"
                    onRequestClose={ () => setIsOpen( false ) }
                    shouldCloseOnClickOutside={ false }
                    shouldCloseOnEsc={ false }
                    isDismissible={ false }
                >
                    <form
                        onSubmit={ ( event ) => {
                            event.preventDefault();
                            setIsOpen( false );
                        } }
                    >
                        <VStack spacing={ 2 }>
                            <ValidatedInputControl
                                { ...args }
                                value={ text }
                                onChange={ setText }
                                customValidity={
                                    text === 'error'
                                        ? {
                                                type: 'invalid',
                                                message:
                                                    'The word "error" is not allowed.',
                                          }
                                        : undefined
                                }
                            />

                            <HStack justify="flex-end" spacing={ 2 }>
                                <Button
                                    variant="tertiary"
                                    __next40pxDefaultSize
                                    onClick={ () => setIsOpen( false ) }
                                >
                                    Cancel
                                </Button>
                                <Button
                                    variant="primary"
                                    __next40pxDefaultSize
                                    type="submit"
                                >
                                    Save
                                </Button>
                            </HStack>
                        </VStack>
                    </form>
                </Modal>
            ) }
        </>
    );
};
Validate On Popover Close story ok
[Form methods](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement#instance_methods) like `reportValidity()` can be used to validate the fields when a popover is about to be closed, and prevent the closing of the popover when invalid.
const ValidateOnPopoverClose = function Template( { ...args } ) {
    const [ isOpen, setIsOpen ] = useState( false );
    const formRef = useRef< HTMLFormElement >( null );
    const [ text, setText ] = useState< string | undefined >( '' );

    return (
        <Dropdown
            popoverProps={ { placement: 'bottom-start' } }
            open={ isOpen }
            onToggle={ ( willOpen ) => {
                if ( ! willOpen ) {
                    const isValid = formRef.current?.reportValidity();
                    setIsOpen( ! isValid );
                } else {
                    setIsOpen( true );
                }
            } }
            renderContent={ () => (
                <form
                    ref={ formRef }
                    onSubmit={ ( event ) => {
                        event.preventDefault();
                        setIsOpen( false );
                    } }
                >
                    <ValidatedInputControl
                        { ...args }
                        value={ text }
                        onChange={ setText }
                        customValidity={
                            text === 'error'
                                ? {
                                        type: 'invalid',
                                        message:
                                            'The word "error" is not allowed.',
                                  }
                                : undefined
                        }
                    />
                </form>
            ) }
            renderToggle={ () => {
                return (
                    <Button
                        __next40pxDefaultSize
                        variant="secondary"
                        onClick={ () => setIsOpen( ! isOpen ) }
                        aria-expanded={ isOpen }
                    >
                        Open in popover
                    </Button>
                );
            } }
        />
    );
};

Page

admin-ui-page · ../packages/admin-ui/src/page/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 11 prop types
Component: ../packages/admin-ui/src/page/index.tsx::default
Props:
actions?: React.ReactNode

ariaLabel?: string

badges?: React.ReactNode

breadcrumbs?: React.ReactNode

children: React.ReactNode

className?: string

hasPadding?: boolean = false

headingLevel?: 1 | 2 | 3 | 4 | 5 | 6

showSidebarToggle?: boolean = true

subTitle?: React.ReactNode

title?: React.ReactNode
Imports
import { Badge, Button, Text } from "@wordpress/ui";
import { Breadcrumbs, Page } from "@wordpress/admin-ui";
Default story ok
const Default = () => <Page title="Page title" showSidebarToggle={false} hasPadding><Text>Page content here</Text></Page>;
With Subtitle story ok
const WithSubtitle = () => <Page
    title="Page title"
    subTitle="All of the subtitle text you need goes here."
    showSidebarToggle={false}
    hasPadding><Text>Page content here</Text></Page>;
With Breadcrumbs story ok
const WithBreadcrumbs = () => <Page
    showSidebarToggle={false}
    breadcrumbs={(<Breadcrumbs
        items={ [
            { label: 'Root breadcrumb', to: '/connectors' },
            { label: 'Level 1 breadcrumb' },
        ] }
    />)}
    hasPadding><Text>Page content here</Text></Page>;
With Breadcrumbs And Subtitle story ok
const WithBreadcrumbsAndSubtitle = () => <Page
    showSidebarToggle={false}
    subTitle="All of the subtitle text you need goes here."
    breadcrumbs={(<Breadcrumbs
        items={ [
            { label: 'Root breadcrumb', to: '/connectors' },
            { label: 'Level 1 breadcrumb' },
        ] }
    />)}
    hasPadding><Text>Page content here</Text></Page>;
Without Header story ok
const WithoutHeader = () => <Page showSidebarToggle={false} hasPadding><Text>Page content here</Text></Page>;
With Title And Badges story ok
const WithTitleAndBadges = () => <Page
    title="Page title"
    badges={<Badge intent="informational">Status</Badge>}
    showSidebarToggle={false}
    hasPadding><Text>Page content here</Text></Page>;
With Breadcrumbs And Badges story ok
const WithBreadcrumbsAndBadges = () => <Page
    showSidebarToggle={false}
    breadcrumbs={(<Breadcrumbs
        items={ [
            { label: 'Root breadcrumb', to: '/connectors' },
            { label: 'Level 1 breadcrumb' },
        ] }
    />)}
    badges={<Badge intent="none">Published</Badge>}
    hasPadding><Text>Page content here</Text></Page>;
With Actions story ok
const WithActions = () => <Page
    title="Page title"
    actions={(<>
        <Button size="compact" variant="outline">
            Cancel
        </Button>
        <Button size="compact" variant="solid">
            Save
        </Button>
    </>)}
    showSidebarToggle={false}
    hasPadding><Text>Page content here</Text></Page>;
Full Header story ok
const FullHeader = () => <Page
    subTitle="All of the subtitle text you need goes here."
    breadcrumbs={(<Breadcrumbs
        items={ [
            { label: 'Root breadcrumb', to: '/connectors' },
            { label: 'Level 1 breadcrumb' },
        ] }
    />)}
    badges={<Badge intent="informational">Status</Badge>}
    actions={(<>
        <Button size="compact" variant="outline">
            Cancel
        </Button>
        <Button size="compact" variant="solid">
            Save
        </Button>
    </>)}
    showSidebarToggle={false}
    hasPadding><Text>Page content here</Text></Page>;

PaletteEdit

components-paletteedit · ../packages/components/src/palette-edit/stories/index.story.tsx
Allows editing a palette of colors or gradients. ```jsx import { PaletteEdit } from '@wordpress/components'; const MyPaletteEdit = () => { const [ controlledColors, setControlledColors ] = useState( colors ); return ( <PaletteEdit colors={ controlledColors } onChange={ ( newColors?: Color[] ) => { setControlledColors( newColors ); } } paletteLabel="Here is a label" /> ); }; ```
Prop types 8 prop types
Component: ../packages/components/src/palette-edit/index.tsx::PaletteEdit
Props:
/**
 * Whether the user can only change the color or gradient values.
 * If true, they cannot change names or delete values.
 * 
 * @default false
 */
canOnlyChangeValues?: boolean

/**
 * Whether the user can reset the editor.
 * 
 * @default false
 */
canReset?: boolean

colors?: any = []

/**
 * A message to show if there's nothing to edit.
 */
emptyMessage?: string

/**
 * A heading label for the palette.
 */
paletteLabel: string

/**
 * The label's heading level.
 * 
 * @default 2
 */
paletteLabelHeadingLevel?: | 1
| 2
| 3
| 4
| 5
| 6
| '1'
| '2'
| '3'
| '4'
| '5'
| '6' = 2

/**
 * Props to pass through to the underlying Popover component.
 */
popoverProps?: Omit<
	React.ComponentPropsWithoutRef< typeof Popover >,
	'children'
>

/**
 * The prefix for the element slug.
 * 
 * @default ''
 */
slugPrefix?: string = ''
Imports
import { PaletteEdit } from "@wordpress/components";
Default story ok
const Default = ( args ) => {
	const { colors, gradients, onChange, ...props } = args;
	const [ value, setValue ] = useState( gradients || colors );

	return (
		<PaletteEdit
			{ ...( gradients
				? {
						gradients: value as Gradient[],
						onChange: ( newValue?: Gradient[] ) => {
							setValue( newValue );
							onChange( newValue );
						},
				  }
				: {
						colors: value as Color[],
						onChange: ( newValue?: Color[] ) => {
							setValue( newValue );
							onChange( newValue );
						},
				  } ) }
			{ ...props }
		/>
	);
};
Gradients story ok
const Gradients = ( args ) => {
	const { colors, gradients, onChange, ...props } = args;
	const [ value, setValue ] = useState( gradients || colors );

	return (
		<PaletteEdit
			{ ...( gradients
				? {
						gradients: value as Gradient[],
						onChange: ( newValue?: Gradient[] ) => {
							setValue( newValue );
							onChange( newValue );
						},
				  }
				: {
						colors: value as Color[],
						onChange: ( newValue?: Color[] ) => {
							setValue( newValue );
							onChange( newValue );
						},
				  } ) }
			{ ...props }
		/>
	);
};

Panel

components-panel · ../packages/components/src/panel/stories/index.story.tsx
`Panel` expands and collapses multiple sections of content. ```jsx import { Panel, PanelBody, PanelRow } from '@wordpress/components'; import { more } from '@wordpress/icons'; const MyPanel = () => ( <Panel header="My Panel"> <PanelBody title="My Block Settings" icon={ more } initialOpen={ true }> <PanelRow>My Panel Inputs and Labels</PanelRow> </PanelBody> </Panel> ); ```
Prop types 3 prop types
Component: ../packages/components/src/panel/index.tsx::Panel
Props:
/**
 * The content to display within the panel.
 */
children: React.ReactNode

/**
 * The CSS class to apply to the wrapper element.
 */
className?: string

/**
 * The text that will be rendered as the title of the panel.
 * Text will be rendered inside an `<h2>` tag.
 */
header?: PanelHeaderProps[ 'label' ]
Imports
import { InputControl, Panel, PanelBody, PanelRow } from "@wordpress/components";
Default story ok
const Default = ( props ) => <Panel { ...props } />;
Panel Row story ok
`PanelRow` is a generic container for rows within a `PanelBody`. It is a flex container with a top margin for spacing.
const _PanelRow = ( props ) => <Panel { ...props } />;
Disabled Section story ok
const DisabledSection = ( props ) => <Panel { ...props } />;
With Icon story ok
const WithIcon = ( props ) => <Panel { ...props } />;

Placeholder

components-placeholder · ../packages/components/src/placeholder/stories/index.story.tsx
Renders a placeholder. Normally used by blocks to render their empty state. ```jsx import { Placeholder } from '@wordpress/components'; import { more } from '@wordpress/icons'; const MyPlaceholder = () => <Placeholder icon={ more } label="Placeholder" />; ```
Imports
import { Placeholder, TextControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState( '' );

    return (
        <Placeholder
            icon="wordpress"
            label="My Placeholder Label"
            instructions="Here are instructions you should follow">
            <div>
                <TextControl
                    __next40pxDefaultSize
                    label="Sample Field"
                    placeholder="Enter something here"
                    value={ value }
                    onChange={ setValue } />
            </div>
        </Placeholder>
    );
};

PlainText

blockeditor-plaintext · ../packages/block-editor/src/components/plain-text/stories/index.story.jsx
Render an auto-growing textarea allow users to fill any textual content.
see: https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/plain-text/README.md example: ```jsx import { registerBlockType } from '@wordpress/blocks'; import { PlainText } from '@wordpress/block-editor'; registerBlockType( 'my-plugin/example-block', { // ... attributes: { content: { type: 'string', }, }, edit( { className, attributes, setAttributes } ) { return ( <PlainText className={ className } value={ attributes.content } onChange={ ( content ) => setAttributes( { content } ) } /> ); }, } ); ````param: {Object} props Component props.param: {string} props.value String value of the textarea.param: {Function} props.onChange Function called when the text value changes.param: {Object} props.ref The component forwards the `ref` property to the `TextareaAutosize` component.return: {Element} Plain text component
Imports
import { PlainText } from "@wordpress/block-editor";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState();

    return (
        <PlainText
            onChange={ ( ...changeArgs ) => {
                onChange( ...changeArgs );
                setValue( ...changeArgs );
            } }
            value={ value } />
    );
};

Popover

components-popover · ../packages/components/src/popover/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 1 prop type
Component: ../packages/components/src/popover/index.tsx::PopoverSlot
Props:
/**
 * The name of the Slot in which the popover should be rendered. It should
 * be also passed to the corresponding `PopoverSlot` component.
 * 
 * @default 'Popover'
 */
name?: string = 'Popover'
Imports
import { Button, Popover, PopoverInsideIframeRenderedInExternalSlot } from "@wordpress/components";
Default story ok
const Default = () => <Popover>(<div style={ { width: '280px', whiteSpace: 'normal' } }>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.
                    </div>)</Popover>;
Unstyled story ok
const Unstyled = () => <Popover variant="unstyled" />;
All Placements story ok
const AllPlacements = ( { children, ...args } ) => (
    <div
        style={ {
            minWidth: '600px',
            marginLeft: 'auto',
            marginRight: 'auto',
        } }
    >
        <h2>
            Resize / scroll the viewport to test the behavior of the
            popovers when they reach the viewport boundaries.
        </h2>
        <div>
            { AVAILABLE_PLACEMENTS.map( ( p ) => (
                <PopoverWithAnchor
                    key={ p }
                    placement={ p }
                    { ...args }
                    resize={ p === 'overlay' ? true : args.resize }
                >
                    { children }
                    <div>
                        <small>(placement: { p })</small>
                    </div>
                </PopoverWithAnchor>
            ) ) }
        </div>
    </div>
);
Dynamic Height story ok
const DynamicHeight = () => <Popover>(<div
        style={ {
            height: 'var(--dynamic-height)',
            background: '#eee',
            padding: '20px',
        } }
    >Content with dynamic height
                    </div>)</Popover>;
With Slot Outside Iframe story ok
const WithSlotOutsideIframe = () => <PopoverInsideIframeRenderedInExternalSlot />;
With Close Handlers story ok
const WithCloseHandlers = function WithCloseHandlersStory( args ) {
    const [ isVisible, setIsVisible ] = useState( false );
    const buttonRef = useRef< HTMLButtonElement >( null );

    const toggleVisible = ( event: React.MouseEvent ) => {
        if ( buttonRef.current && event.target !== buttonRef.current ) {
            return;
        }
        setIsVisible( ( prev ) => ! prev );
    };

    const handleClose = () => {
        args.onClose?.();
        setIsVisible( false );
    };

    const handleFocusOutside = ( e: React.SyntheticEvent ) => {
        args.onFocusOutside?.( e );
        setIsVisible( false );
    };

    useEffect( () => {
        buttonRef.current?.scrollIntoView( {
            block: 'center',
            inline: 'center',
        } );
    }, [] );

    return (
        <div
            style={ {
                width: '300vw',
                height: '300vh',
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
            } }
        >
            <Button
                __next40pxDefaultSize
                variant="secondary"
                onClick={ toggleVisible }
                ref={ buttonRef }
            >
                Toggle Popover
                { isVisible && (
                    <Popover
                        { ...args }
                        onClose={ handleClose }
                        onFocusOutside={ handleFocusOutside }
                    >
                        { args.children }
                    </Popover>
                ) }
            </Button>
        </div>
    );
};

ProgressBar

components-progressbar · ../packages/components/src/progress-bar/stories/index.story.tsx
A simple horizontal progress bar component. Supports two modes: determinate and indeterminate. A progress bar is determinate when a specific progress value has been specified (from 0 to 100), and indeterminate when a value hasn't been specified. ```jsx import { ProgressBar } from '@wordpress/components'; const MyLoadingComponent = () => { return <ProgressBar />; }; ```
Imports
import { ProgressBar } from "@wordpress/components";
Default story ok
const Default = () => {
    return <ProgressBar />;
};
With Custom Width story ok
A progress bar with a custom width. You can override the default `width` by passing a custom CSS class via the `className` prop. This example shows a progress bar with an overridden `width` of `100%` which makes it fit all available horizontal space of the parent element. The CSS class looks like this: ```css .custom-progress-bar { width: 100%; } ```
const WithCustomWidth = () => {
    return <ProgressBar className="custom-progress-bar" />;
};

QueryControls

components-querycontrols · ../packages/components/src/query-controls/stories/index.story.tsx
Controls to query for posts. ```jsx const MyQueryControls = () => ( <QueryControls { ...{ maxItems, minItems, numberOfItems, order, orderBy, orderByOptions } } onOrderByChange={ ( newOrderBy ) => { updateQuery( { orderBy: newOrderBy } ) } onOrderChange={ ( newOrder ) => { updateQuery( { order: newOrder } ) } categoriesList={ categories } selectedCategoryId={ category } onCategoryChange={ ( newCategory ) => { updateQuery( { category: newCategory } ) } onNumberOfItemsChange={ ( newNumberOfItems ) => { updateQuery( { numberOfItems: newNumberOfItems } ) } } /> ); ```
Prop types 3 prop types
Component: ../packages/components/src/query-controls/index.tsx::QueryControls
Props:
maxItems?: any = 100

minItems?: any = 1

orderByOptions?: any = [
	{
		label: __( 'Newest to oldest' ),
		value: 'date/desc',
	},
	{
		label: __( 'Oldest to newest' ),
		value: 'date/asc',
	},
	{
		/* translators: Label for ordering posts by title in ascending order. */
		label: __( 'A → Z' ),
		value: 'title/asc',
	},
	{
		/* translators: Label for ordering posts by title in descending order. */
		label: __( 'Z → A' ),
		value: 'title/desc',
	},
]
Imports
import { QueryControls } from "@wordpress/components";
Default story ok
const Default = ( args ) => {
	const {
		onAuthorChange,
		onCategoryChange,
		onNumberOfItemsChange,
		onOrderByChange,
		onOrderChange,
		...props
	} = args as QueryControlsWithMultipleCategorySelectionProps;
	const [ ownNumberOfItems, setOwnNumberOfItems ] = useState(
		props.numberOfItems
	);
	const [ ownOrder, setOwnOrder ] = useState( props.order );
	const [ ownOrderBy, setOwnOrderBy ] = useState( props.orderBy );
	const [ ownSelectedAuthorId, setOwnSelectedAuthorId ] = useState(
		props.selectedAuthorId
	);
	const [ ownSelectedCategories, setOwnSelectedCategories ] = useState(
		props.selectedCategories
	);

	const handleCategoryChange: QueryControlsWithMultipleCategorySelectionProps[ 'onCategoryChange' ] =
		( tokens ) => {
			onCategoryChange?.( tokens );

			const hasNoSuggestion = tokens.some(
				( token ) =>
					typeof token === 'string' &&
					! props.categorySuggestions?.[ token ]
			);
			if ( hasNoSuggestion ) {
				return;
			}
			const allCategories = tokens
				.map( ( token ) => {
					return typeof token === 'string'
						? props.categorySuggestions?.[ token ]
						: token;
				} )
				.filter( Boolean ) as Array< Required< Category > >;

			setOwnSelectedCategories( allCategories );
		};

	return (
		<QueryControls
			{ ...props }
			numberOfItems={ ownNumberOfItems }
			onCategoryChange={ handleCategoryChange }
			onOrderByChange={ ( newOrderBy ) => {
				onOrderByChange?.( newOrderBy );
				setOwnOrderBy( newOrderBy );
			} }
			onOrderChange={ ( newOrder ) => {
				onOrderChange?.( newOrder );
				setOwnOrder( newOrder );
			} }
			order={ ownOrder }
			orderBy={ ownOrderBy }
			onNumberOfItemsChange={ ( newNumber ) => {
				onNumberOfItemsChange?.( newNumber );
				setOwnNumberOfItems( newNumber );
			} }
			onAuthorChange={ ( newAuthor ) => {
				onAuthorChange?.( newAuthor );
				setOwnSelectedAuthorId( Number( newAuthor ) );
			} }
			selectedAuthorId={ ownSelectedAuthorId }
			selectedCategories={ ownSelectedCategories }
		/>
	);
};
Select Single Category story ok
const SelectSingleCategory = ( args ) => {
	const {
		onAuthorChange,
		onCategoryChange,
		onNumberOfItemsChange,
		onOrderByChange,
		onOrderChange,
		...props
	} = args as QueryControlsWithSingleCategorySelectionProps;
	const [ ownOrder, setOwnOrder ] = useState( props.order );
	const [ ownOrderBy, setOwnOrderBy ] = useState( props.orderBy );
	const [ ownSelectedCategoryId, setSelectedCategoryId ] = useState(
		props.selectedCategoryId
	);

	const handleCategoryChange: QueryControlsWithSingleCategorySelectionProps[ 'onCategoryChange' ] =
		( newCategory ) => {
			onCategoryChange?.( newCategory );
			setSelectedCategoryId( Number( newCategory ) );
		};

	return (
		<QueryControls
			{ ...props }
			onCategoryChange={ handleCategoryChange }
			onOrderByChange={ ( newOrderBy ) => {
				setOwnOrderBy( newOrderBy );
			} }
			onOrderChange={ ( newOrder ) => {
				onOrderChange?.( newOrder );
				setOwnOrder( newOrder );
			} }
			order={ ownOrder }
			orderBy={ ownOrderBy }
			selectedCategoryId={ ownSelectedCategoryId }
		/>
	);
};

RadioControl

components-radiocontrol · ../packages/components/src/radio-control/stories/index.story.tsx
Render a user interface to select the user type using radio inputs. ```jsx import { RadioControl } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyRadioControl = () => { const [ option, setOption ] = useState( 'a' ); return ( <RadioControl label="User type" help="The type of the current user" selected={ option } options={ [ { label: 'Author', value: 'a' }, { label: 'Editor', value: 'e' }, ] } onChange={ ( value ) => setOption( value ) } /> ); }; ```
Imports
import { RadioControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState( options?.[ 0 ]?.value );

    return (
        <RadioControl
            label="Post visibility"
            selected={ value }
            options={ options }
            onChange={ ( v ) => {
				setValue( v );
				onChange( v );
			} } />
    );
};
With Option Descriptions story ok
const WithOptionDescriptions = () => {
    const [ value, setValue ] = useState( options?.[ 0 ]?.value );

    return (
        <RadioControl
            selected={ value }
            options={ options }
            onChange={ ( v ) => {
				setValue( v );
				onChange( v );
			} } />
    );
};

RadioGroup

components-radiogroup · ../packages/components/src/radio-group/stories/index.story.tsx
deprecated: Use `RadioControl` or `ToggleGroupControl` instead.
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Radio, RadioGroup } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	return <RadioGroup { ...props } />;
};
Disabled story ok
const Disabled = ( props ) => {
	return <RadioGroup { ...props } />;
};
Controlled story ok
const Controlled = ( {
	checked: checkedProp,
	onChange: onChangeProp,
	...props
} ) => {
	const [ checked, setChecked ] =
		useState< React.ComponentProps< typeof RadioGroup >[ 'checked' ] >(
			checkedProp
		);

	const onChange: typeof onChangeProp = ( value ) => {
		setChecked( value );
		onChangeProp?.( value );
	};

	return (
		<RadioGroup { ...props } onChange={ onChange } checked={ checked } />
	);
};

RangeControl

components-rangecontrol · ../packages/components/src/range-control/stories/index.story.tsx
RangeControls are used to make selections from a range of incremental values. ```jsx import { RangeControl } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyRangeControl = () => { const [ value, setValue ] = useState(); return ( <RangeControl __next40pxDefaultSize help="Please select how transparent you would like this." initialPosition={ 50 } label="Opacity" max={ 100 } min={ 0 } value={ value } onChange={ setValue } /> ); }; ```
Imports
import { RangeControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState< number >();

    return (
        <RangeControl
            __next40pxDefaultSize
            onBlur={fn()}
            onFocus={fn()}
            onMouseLeave={fn()}
            onMouseMove={fn()}
            help="Please select how transparent you would like this."
            initialPosition={50}
            label="Opacity"
            max={100}
            min={0}
            value={ value }
            onChange={ ( v ) => {
				setValue( v );
				onChange?.( v );
			} } />
    );
};
With Any Step story ok
Setting the `step` prop to `"any"` will allow users to select non-integer values. This also overrides both `withInputField` and `showTooltip` props to `false`.
const WithAnyStep = () => {
    const [ value, setValue ] = useState< number >();

    return (
        <>
            <RangeControl
                __next40pxDefaultSize
                onBlur={fn()}
                onFocus={fn()}
                onMouseLeave={fn()}
                onMouseMove={fn()}
                label="Brightness"
                step="any"
                value={ value }
                onChange={ ( v ) => {
					setValue( v );
					onChange?.( v );
				} } />
            <hr style={ { marginTop: '5em' } } />
            <p>Current value: { value }</p>
        </>
    );
};
With Integer Step And Marks story ok
Use `marks` to render a visual representation of `step` ticks. Marks may be automatically generated or custom mark indicators can be provided by an `Array`.
const WithIntegerStepAndMarks = () => {
    const [ automaticValue, setAutomaticValue ] = useState< number >();
    const [ customValue, setCustomValue ] = useState< number >();

    return (
        <>
            <h2>{ label }</h2>
            <RangeControl
                __next40pxDefaultSize
                onBlur={fn()}
                onFocus={fn()}
                onMouseLeave={fn()}
                onMouseMove={fn()}
                max={10}
                min={0}
                step={1}
                label="Automatic marks"
                marks
                onChange={ ( v ) => {
					setAutomaticValue( v );
					onChange?.( v );
				} }
                value={ automaticValue } />
            <RangeControl
                __next40pxDefaultSize
                onBlur={fn()}
                onFocus={fn()}
                onMouseLeave={fn()}
                onMouseMove={fn()}
                marks={marksBase}
                max={10}
                min={0}
                step={1}
                label="Custom marks"
                onChange={ ( v ) => {
					setCustomValue( v );
					onChange?.( v );
				} }
                value={ customValue } />
        </>
    );
};
With Decimal Step And Marks story ok
Decimal values may be used for `marks` rendered as a visual representation of `step` ticks. Marks may be automatically generated or custom mark indicators can be provided by an `Array`.
const WithDecimalStepAndMarks = () => {
    const [ automaticValue, setAutomaticValue ] = useState< number >();
    const [ customValue, setCustomValue ] = useState< number >();

    return (
        <>
            <h2>{ label }</h2>
            <RangeControl
                __next40pxDefaultSize
                onBlur={fn()}
                onFocus={fn()}
                onMouseLeave={fn()}
                onMouseMove={fn()}
                max={10}
                min={0}
                step={0.1}
                label="Automatic marks"
                marks
                onChange={ ( v ) => {
					setAutomaticValue( v );
					onChange?.( v );
				} }
                value={ automaticValue } />
            <RangeControl
                __next40pxDefaultSize
                onBlur={fn()}
                onFocus={fn()}
                onMouseLeave={fn()}
                onMouseMove={fn()}
                marks={[
                    ...marksBase,
                    { value: 3.5, label: '3.5' },
                    { value: 5.8, label: '5.8' },
                ]}
                max={10}
                min={0}
                step={0.1}
                label="Custom marks"
                onChange={ ( v ) => {
					setCustomValue( v );
					onChange?.( v );
				} }
                value={ customValue } />
        </>
    );
};
With Negative Minimum And Marks story ok
A negative `min` value can be used to constrain `RangeControl` values. Mark indicators can represent negative values as well. Marks may be automatically generated or custom mark indicators can be provided by an `Array`.
const WithNegativeMinimumAndMarks = () => {
    const [ automaticValue, setAutomaticValue ] = useState< number >();
    const [ customValue, setCustomValue ] = useState< number >();

    return (
        <>
            <h2>{ label }</h2>
            <RangeControl
                __next40pxDefaultSize
                onBlur={fn()}
                onFocus={fn()}
                onMouseLeave={fn()}
                onMouseMove={fn()}
                max={10}
                min={-10}
                step={1}
                label="Automatic marks"
                marks
                onChange={ ( v ) => {
					setAutomaticValue( v );
					onChange?.( v );
				} }
                value={ automaticValue } />
            <RangeControl
                __next40pxDefaultSize
                onBlur={fn()}
                onFocus={fn()}
                onMouseLeave={fn()}
                onMouseMove={fn()}
                marks={marksWithNegatives}
                max={10}
                min={-10}
                step={1}
                label="Custom marks"
                onChange={ ( v ) => {
					setCustomValue( v );
					onChange?.( v );
				} }
                value={ customValue } />
        </>
    );
};
With Negative Range And Marks story ok
The entire range of valid values for a `RangeControl` may be negative. Mark indicators can represent negative values as well. Marks may be automatically generated or custom mark indicators can be provided by an `Array`.
const WithNegativeRangeAndMarks = () => {
    const [ automaticValue, setAutomaticValue ] = useState< number >();
    const [ customValue, setCustomValue ] = useState< number >();

    return (
        <>
            <h2>{ label }</h2>
            <RangeControl
                __next40pxDefaultSize
                onBlur={fn()}
                onFocus={fn()}
                onMouseLeave={fn()}
                onMouseMove={fn()}
                max={-1}
                min={-10}
                step={1}
                label="Automatic marks"
                marks
                onChange={ ( v ) => {
					setAutomaticValue( v );
					onChange?.( v );
				} }
                value={ automaticValue } />
            <RangeControl
                __next40pxDefaultSize
                onBlur={fn()}
                onFocus={fn()}
                onMouseLeave={fn()}
                onMouseMove={fn()}
                marks={marksWithNegatives}
                max={-1}
                min={-10}
                step={1}
                label="Custom marks"
                onChange={ ( v ) => {
					setCustomValue( v );
					onChange?.( v );
				} }
                value={ customValue } />
        </>
    );
};
With Any Step And Marks story ok
When a `RangeControl` has a `step` value of `any` a user may select non-integer values. This may still be used in conjunction with `marks` rendering a visual representation of `step` ticks.
const WithAnyStepAndMarks = () => {
    const [ automaticValue, setAutomaticValue ] = useState< number >();
    const [ customValue, setCustomValue ] = useState< number >();

    return (
        <>
            <h2>{ label }</h2>
            <RangeControl
                __next40pxDefaultSize
                onBlur={fn()}
                onFocus={fn()}
                onMouseLeave={fn()}
                onMouseMove={fn()}
                max={10}
                min={0}
                step="any"
                label="Automatic marks"
                marks
                onChange={ ( v ) => {
					setAutomaticValue( v );
					onChange?.( v );
				} }
                value={ automaticValue } />
            <RangeControl
                __next40pxDefaultSize
                onBlur={fn()}
                onFocus={fn()}
                onMouseLeave={fn()}
                onMouseMove={fn()}
                marks={marksBase}
                max={10}
                min={0}
                step="any"
                label="Custom marks"
                onChange={ ( v ) => {
					setCustomValue( v );
					onChange?.( v );
				} }
                value={ customValue } />
        </>
    );
};

ResizableBox

components-resizablebox · ../packages/components/src/resizable-box/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 4 prop types
Component: ../packages/components/src/resizable-box/index.tsx::ResizableBox
Props:
__experimentalShowTooltip?: boolean = false

__experimentalTooltipProps?: Parameters< typeof ResizeTooltip >[ 0 ] = {}

children: ReactNode

showHandle?: boolean = true
Imports
import { ResizableBox } from "@wordpress/components";
Default story ok
const Default = ( {
	onResizeStop,
	...props
} ) => {
	const [ { height, width }, setAttributes ] = useState( {
		height: 200,
		width: 400,
	} );

	return (
		<ResizableBox
			{ ...props }
			size={ {
				height,
				width,
			} }
			onResizeStop={ ( event, direction, elt, delta ) => {
				onResizeStop?.( event, direction, elt, delta );
				setAttributes( {
					height: height + delta.height,
					width: width + delta.width,
				} );
			} }
		/>
	);
};
Disabled Directions story ok
The `enable` prop can be used to disable resizing in specific directions.
const DisabledDirections = ( {
	onResizeStop,
	...props
} ) => {
	const [ { height, width }, setAttributes ] = useState( {
		height: 200,
		width: 400,
	} );

	return (
		<ResizableBox
			{ ...props }
			size={ {
				height,
				width,
			} }
			onResizeStop={ ( event, direction, elt, delta ) => {
				onResizeStop?.( event, direction, elt, delta );
				setAttributes( {
					height: height + delta.height,
					width: width + delta.width,
				} );
			} }
		/>
	);
};

ResolutionTool

blockeditor-resolutioncontrol · ../packages/block-editor/src/components/resolution-tool/stories/index.story.jsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 3 prop types
Component: ../packages/block-editor/src/components/resolution-tool/index.js::default
Props:
defaultValue?: any = DEFAULT_SIZE_OPTIONS[ 0 ].value

isShownByDefault?: any = true

options?: any = [
	{
		label: _x( 'Thumbnail', 'Image size option for resolution control' ),
		value: 'thumbnail',
	},
	{
		label: _x( 'Medium', 'Image size option for resolution control' ),
		value: 'medium',
	},
	{
		label: _x( 'Large', 'Image size option for resolution control' ),
		value: 'large',
	},
	{
		label: _x( 'Full Size', 'Image size option for resolution control' ),
		value: 'full',
	},
]
Imports
import { Panel, __experimentalToolsPanel as ToolsPanel } from "@wordpress/components";
import { ResolutionTool } from "@wordpress/block-editor";
Default story ok
const Default = ( {
	label,
	panelId,
	onChange: onChangeProp,
	...props
} ) => {
	const [ attributes, setAttributes ] = useReducer(
		( prevState, nextState ) => ( { ...prevState, ...nextState } ),
		{}
	);
	const { resolution } = attributes;
	const resetAll = ( resetFilters = [] ) => {
		let newAttributes = {};

		resetFilters.forEach( ( resetFilter ) => {
			newAttributes = {
				...newAttributes,
				...resetFilter( newAttributes ),
			};
		} );

		setAttributes( newAttributes );
		onChangeProp( undefined );
	};
	return (
		<Panel>
			<ToolsPanel
				label={ label }
				panelId={ panelId }
				resetAll={ resetAll }
			>
				<ResolutionTool
					panelId={ panelId }
					onChange={ ( newValue ) => {
						setAttributes( { resolution: newValue } );
						onChangeProp( newValue );
					} }
					value={ resolution }
					resetAllFilter={ () => ( {
						resolution: undefined,
					} ) }
					{ ...props }
				/>
			</ToolsPanel>
		</Panel>
	);
};

ResponsiveWrapper

components-responsivewrapper · ../packages/components/src/responsive-wrapper/stories/index.story.tsx
A wrapper component that maintains its aspect ratio when resized. ```jsx import { ResponsiveWrapper } from '@wordpress/components'; const MyResponsiveWrapper = () => ( <ResponsiveWrapper naturalWidth={ 2000 } naturalHeight={ 680 }> <img src="https://s.w.org/style/images/about/WordPress-logotype-standard.png" alt="WordPress" /> </ResponsiveWrapper> ); ```
Prop types 4 prop types
Component: ../packages/components/src/responsive-wrapper/index.tsx::default
Props:
/**
 * The element to wrap.
 */
children: React.ReactElement

/**
 * If true, the wrapper will be `span` instead of `div`.
 * 
 * @default false
 */
isInline?: boolean = false

/**
 * The intrinsic height of the element to wrap. Will be used to determine the aspect ratio.
 */
naturalHeight?: number

/**
 * The intrinsic width of the element to wrap. Will be used to determine the aspect ratio.
 */
naturalWidth?: number
Imports
import { ResponsiveWrapper } from "@wordpress/components";
Default story ok
const Default = () => <ResponsiveWrapper naturalWidth={2000} naturalHeight={680}><img
        src="https://s.w.org/style/images/about/WordPress-logotype-standard.png"
        alt="WordPress" /></ResponsiveWrapper>;
With SVG story ok
When passing an `SVG` element as the `<ResponsiveWrapper />`'s child, make sure that it has the `viewbox` and the `preserveAspectRatio` set. When dealing with SVGs, it may not be possible to derive its `naturalWidth` and `naturalHeight` and therefore passing them as propertied to `<ResponsiveWrapper />`. In this case, the SVG simply keeps scaling up to fill its container, unless the `height` and `width` attributes are specified.
const WithSVG = () => <ResponsiveWrapper><svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 280 640"
        preserveAspectRatio="xMinYMin meet"
        width="280px"
        height="640px">
        <rect x="0" y="0" width="280" height="640" style={ { fill: 'blue' } } />
        <g>
            <circle style={ { fill: 'red' } } cx="140" cy="160" r="60" />
            <circle style={ { fill: 'yellow' } } cx="140" cy="320" r="60" />
            <circle style={ { fill: '#40CC40' } } cx="140" cy="480" r="60" />
        </g>
    </svg></ResponsiveWrapper>;

SandBox

components-sandbox · ../packages/components/src/sandbox/stories/index.story.tsx
This component provides an isolated environment for arbitrary HTML via iframes. ```jsx import { SandBox } from '@wordpress/components'; const MySandBox = () => ( <SandBox html="<p>Content</p>" title="SandBox" type="embed" /> ); ```
Prop types 7 prop types
Component: ../packages/components/src/sandbox/index.tsx::default
Props:
/**
 * The HTML to render in the body of the iframe document.
 * 
 * @default ''
 */
html?: string = ''

/**
 * The `onFocus` callback for the iframe.
 */
onFocus?: React.DOMAttributes< HTMLIFrameElement >[ 'onFocus' ]

/**
 * An array of script URLs to inject as `<script>` tags into the bottom of the `<body>` of the iframe document.
 * 
 * @default []
 */
scripts?: string[] = []

/**
 * An array of CSS strings to inject into the `<head>` of the iframe document.
 * 
 * @default []
 */
styles?: string[] = []

/**
 * The `tabindex` the iframe should receive.
 * 
 * @default 0
 */
tabIndex?: HTMLElement[ 'tabIndex' ]

/**
 * The `<title>` of the iframe document.
 * 
 * @default ''
 */
title?: string = ''

/**
 * The CSS class name to apply to the `<html>` and `<body>` elements of the iframe.
 */
type?: string
Imports
import { SandBox } from "@wordpress/components";
Default story ok
const Default = () => <SandBox onFocus={fn()} html="<p>Arbitrary HTML content</p>" />;

ScaleTool

blockeditor-dimensionstool-scaletool · ../packages/block-editor/src/components/dimensions-tool/stories/scale-tool.story.jsx
A tool to select the CSS object-fit property for the image.
param: {ScaleToolProps} props return: {React.ReactElement} The scale tool.
Prop types 3 prop types
Component: ../packages/block-editor/src/components/dimensions-tool/scale-tool.js::default
Props:
defaultValue?: any = DEFAULT_SCALE_OPTIONS[ 0 ].value

isShownByDefault?: any = true

options?: any = [
	{
		value: 'fill',
		label: _x( 'Fill', 'Scale option for dimensions control' ),
		help: __( 'Fill the space by stretching the content.' ),
	},
	{
		value: 'contain',
		label: _x( 'Contain', 'Scale option for dimensions control' ),
		help: __( 'Fit the content to the space without clipping.' ),
	},
	{
		value: 'cover',
		label: _x( 'Cover', 'Scale option for dimensions control' ),
		help: __( "Fill the space by clipping what doesn't fit." ),
	},
	{
		value: 'none',
		label: _x( 'None', 'Scale option for dimensions control' ),
		help: __(
			'Do not adjust the sizing of the content. Content that is too large will be clipped, and content that is too small will have additional padding.'
		),
	},
	{
		value: 'scale-down',
		label: _x( 'Scale down', 'Scale option for dimensions control' ),
		help: __(
			'Scale down the content to fit the space if it is too big. Content that is too small will have additional padding.'
		),
	},
]
Imports
import { Panel, __experimentalToolsPanel as ToolsPanel } from "@wordpress/components";
import { ScaleTool } from "@wordpress/block-editor";
Default story ok
const Default = ( { panelId, onChange: onChangeProp, ...props } ) => {
	const [ value, setValue ] = useState( undefined );
	const resetAll = () => {
		setValue( undefined );
		onChangeProp( undefined );
	};
	return (
		<Panel>
			<ToolsPanel label="Scale" panelId={ panelId } resetAll={ resetAll }>
				<ScaleTool
					panelId={ panelId }
					onChange={ ( nextValue ) => {
						setValue( nextValue );
						onChangeProp( nextValue );
					} }
					value={ value }
					{ ...props }
				/>
			</ToolsPanel>
		</Panel>
	);
};

Scrollable

components-scrollable · ../packages/components/src/scrollable/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Scrollable, View } from "@wordpress/components";
Default story ok
const Default = () => {
    const targetRef = useRef< HTMLInputElement >( null );

    const onButtonClick = () => {
		targetRef.current?.focus();
	};

    const containerWidth = 300;
    const containerHeight = 400;

    return (
        <Scrollable
            style={ { height: containerHeight, width: containerWidth } }
            smoothScroll={false}
            scrollDirection="y">
            <View
                style={ {
					backgroundColor: '#eee',
					height:
						args.scrollDirection === 'x' ? containerHeight : 1000,
					width: args.scrollDirection === 'y' ? containerWidth : 1000,
					position: 'relative',
				} }>
                <button onClick={ onButtonClick }>Move focus to an element out of view
                                    </button>
                <input
                    ref={ targetRef }
                    style={ {
						position: 'absolute',
						bottom: args.scrollDirection === 'x' ? 'initial' : 0,
						right: 0,
					} }
                    type="text"
                    value="Focus me"
                    readOnly />
            </View>
        </Scrollable>
    );
};

ScrollLock

components-scrolllock · ../packages/components/src/scroll-lock/stories/index.story.tsx
Prop type error
File: /home/runner/work/gutenberg/gutenberg/packages/components/src/scroll-lock/index.tsx
Error:
No suitable component definition found.
You can debug your component file in this playground: https://react-docgen.dev/playground
Code:
/**
 * WordPress dependencies
 */
import { useEffect } from '@wordpress/element';

/*
 * Setting `overflow: hidden` on html and body elements resets body scroll in iOS.
 * Save scroll top so we can restore it after locking scroll.
 *
 * NOTE: It would be cleaner and possibly safer to find a localized solution such
 * as preventing default on certain touchmove events.
 */
let previousScrollTop = 0;

function setLocked( locked: boolean ) {
	const scrollingElement = document.scrollingElement || document.body;

	if ( locked ) {
		previousScrollTop = scrollingElement.scrollTop;
	}

	const methodName = locked ? 'add' : 'remove';
	scrollingElement.classList[ methodName ]( 'lockscroll' );

	// Adding the class to the document element seems to be necessary in iOS.
	document.documentElement.classList[ methodName ]( 'lockscroll' );

	if ( ! locked ) {
		scrollingElement.scrollTop = previousScrollTop;
	}
}

let lockCounter = 0;

/**
 * ScrollLock is a content-free React component for declaratively preventing
 * scroll bleed from modal UI to the page body. This component applies a
 * `lockscroll` class to the `document.documentElement` and
 * `document.scrollingElement` elements to stop the body from scrolling. When it
 * is present, the lock is applied.
 *
 * ```jsx
 * import { ScrollLock, Button } from '@wordpress/components';
 * import { useState } from '@wordpress/element';
 *
 * const MyScrollLock = () => {
 *   const [ isScrollLocked, setIsScrollLocked ] = useState( false );
 *
 *   const toggleLock = () => {
 *     setIsScrollLocked( ( locked ) => ! locked ) );
 *   };
 *
 *   return (
 *     <div>
 *       <Button variant="secondary" onClick={ toggleLock }>
 *         Toggle scroll lock
 *       </Button>
 *       { isScrollLocked && <ScrollLock /> }
 *       <p>
 *         Scroll locked:
 *         <strong>{ isScrollLocked ? 'Yes' : 'No' }</strong>
 *       </p>
 *     </div>
 *   );
 * };
 * ```
 */
export function ScrollLock(): null {
	useEffect( () => {
		if ( lockCounter === 0 ) {
			setLocked( true );
		}

		++lockCounter;

		return () => {
			if ( lockCounter === 1 ) {
				setLocked( false );
			}

			--lockCounter;
		};
	}, [] );

	return null;
}

export default ScrollLock;
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Button, ScrollLock } from "@wordpress/components";
Default story ok
const Default = () => {
	const [ isScrollLocked, setScrollLocked ] = useState( false );
	const toggleLock = () => setScrollLocked( ! isScrollLocked );

	return (
		<div style={ { height: 1000 } }>
			<div
				style={ {
					overflow: 'auto',
					height: 240,
					border: '1px solid lightgray',
				} }
			>
				<StripedBackground>
					<div>
						Start scrolling down. Once you scroll to the end of this
						container with the stripes, the rest of the page will
						continue scrolling. <code>ScrollLock</code> prevents
						this &quot;scroll bleed&quot; from happening.
					</div>
					<ToggleContainer>
						<Button
							__next40pxDefaultSize
							variant="primary"
							onClick={ toggleLock }
						>
							Toggle Scroll Lock
						</Button>
						{ isScrollLocked && <ScrollLock /> }
						<p>
							Scroll locked:{ ' ' }
							<strong>{ isScrollLocked ? 'Yes' : 'No' }</strong>
						</p>
					</ToggleContainer>
				</StripedBackground>
			</div>
		</div>
	);
};

SearchControl

components-searchcontrol · ../packages/components/src/search-control/stories/index.story.tsx
SearchControl components let users display a search control. ```jsx import { SearchControl } from '@wordpress/components'; import { useState } from '@wordpress/element'; function MySearchControl( { className, setState } ) { const [ searchInput, setSearchInput ] = useState( '' ); return ( <SearchControl value={ searchInput } onChange={ setSearchInput } /> ); } ```
Prop types 4 prop types
Component: ../packages/components/src/search-control/index.tsx::SearchControl
Props:
hideLabelFromVision?: any = true

label?: any = __( 'Search' )

placeholder?: any = __( 'Search' )

size?: any = 'default'
Imports
import { SearchControl } from "@wordpress/components";
Default story ok
const Default = ( {
	onChange,
	...props
} ) => {
	const [ value, setValue ] = useState< string >();

	return (
		<SearchControl
			{ ...props }
			value={ value }
			onChange={ ( ...changeArgs ) => {
				setValue( ...changeArgs );
				onChange( ...changeArgs );
			} }
		/>
	);
};

Select.Root

design-system-components-form-primitives-select · ../packages/ui/src/form/primitives/select/stories/index.story.tsx
A badge component for displaying labels with semantic intent.
Prop types 4 prop types
Component: ../packages/ui/src/badge/badge.tsx::Badge
Props:
/**
 * The text to display in the badge.
 */
children: string

/**
 * CSS class name to apply to the component.
 */
className?: string

/**
 * The semantic intent of the badge, communicating its meaning through color.
 * 
 * @default "none"
 */
intent?: | 'high'
| 'medium'
| 'low'
| 'stable'
| 'informational'
| 'draft'
| 'none' = 'none'

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: | ComponentRenderFn< HTMLAttributesWithRef >
| React.ReactElement< Record< string, unknown > >
Imports
import { Select } from "@wordpress/ui";
Default story ok
const Default = () => <Select.Root>(<>
        <Select.Trigger />
        <Select.Popup>
            { Array.from( { length: 6 }, ( _, index ) => (
                <Select.Item
                    key={ index }
                    value={ `Item ${ index + 1 }` }
                />
            ) ) }
        </Select.Popup>
    </>)</Select.Root>;
Compact story ok
const Compact = () => <Select.Root defaultValue="Item 1">(<>
        <Select.Trigger size="compact" />
        <Select.Popup>
            { Array.from( { length: 6 }, ( _, index ) => (
                <Select.Item
                    key={ index }
                    value={ `Item ${ index + 1 }` }
                    size="compact"
                />
            ) ) }
        </Select.Popup>
    </>)</Select.Root>;
Minimal story ok
The `minimal` variant must be used judiciously, because in many contexts it can be unclear to users that it is a select trigger. Combined with the `small` size, `minimal` can be used to create a very low-profile `Select`, intended for rare use cases like a pagination control.
const Minimal = () => <Select.Root defaultValue="1">(<>
        <Select.Trigger size="small" variant="minimal" />
        <Select.Popup>
            { Array.from( { length: 6 }, ( _, index ) => (
                <Select.Item
                    key={ index }
                    value={ `${ index + 1 }` }
                    size="small"
                />
            ) ) }
        </Select.Popup>
    </>)</Select.Root>;
With Empty Value Option story ok
By passing an `items` array to `Select.Root`, the `Select.Trigger` will be able to render a `label` string for each item rather than the raw `value` string. In this case, the option with an empty string value has a `"Select"` label string. This may be easier than writing a custom render function for the `Select.Trigger`.
const WithEmptyValueOption = () => <Select.Root items={withEmptyOptionItems} defaultValue="">(<>
        <Select.Trigger />
        <Select.Popup>
            { withEmptyOptionItems.map( ( item ) => (
                <Select.Item
                    key={ item.value }
                    value={ item.value }
                    label={ item.label }
                    disabled={ item.disabled }
                >
                    { item.label }
                </Select.Item>
            ) ) }
        </Select.Popup>
    </>)</Select.Root>;
Labeling story ok
When accessibly labeling a `Select`, note that the label must be associated with the `Select.Trigger`, not the `Select.Root`. Whether labeling with `aria-label`, `htmlFor`, or `aria-labelledby`, the association must be made to the `Select.Trigger`.
const Labeling = () => <Select.Root defaultValue="Administrator">(<>
        <Select.Trigger aria-label="User role" />
        <Select.Popup>
            <Select.Item value="Administrator" />
            <Select.Item value="Editor" />
        </Select.Popup>
    </>)</Select.Root>;
With Overflow story ok
const WithOverflow = () => <Select.Root defaultValue={longItemValue}>(<>
        <Select.Trigger />
        <Select.Popup>
            <Select.Item value={ longItemValue } />
            <Select.Item value="Item 2" />
        </Select.Popup>
    </>)</Select.Root>;
Disabled story ok
const Disabled = () => <Select.Root defaultValue="Item 1" disabled>(<>
        <Select.Trigger />
        <Select.Popup>
            <Select.Item value="Item 1" />
            <Select.Item value="Item 2" />
        </Select.Popup>
    </>)</Select.Root>;
With Disabled Item story ok
const WithDisabledItem = () => <Select.Root defaultValue="Item 1">(<>
        <Select.Trigger />
        <Select.Popup>
            <Select.Item value="Item 1" />
            <Select.Item value="Item 2" disabled />
        </Select.Popup>
    </>)</Select.Root>;
With Custom Trigger And Item story ok
For custom needs, a `Select.Trigger` can take a custom render function as its children, while `Select.Item` can take arbitrary content as children.
const WithCustomTriggerAndItem = () => <Select.Root defaultValue="User 1">(<>
        <Select.Trigger>
            { ( value ) => (
                <span
                    style={ {
                        display: 'flex',
                        alignItems: 'center',
                        gap: 8,
                    } }
                >
                    <img
                        src={ `https://gravatar.com/avatar/?d=initials&name=${ value }` }
                        alt=""
                        width="20"
                        style={ {
                            borderRadius: '50%',
                        } }
                    />
                    { value }
                </span>
            ) }
        </Select.Trigger>
        <Select.Popup>
            { customOptions.map( ( item ) => (
                <Select.Item
                    key={ item.value }
                    value={ item.value }
                    label={ item.label }
                >
                    { item.label }
                </Select.Item>
            ) ) }
        </Select.Popup>
    </>)</Select.Root>;
With Custom z-index story ok
Popovers in Gutenberg are managed with explicit z-index values, which can create situations where a popover renders below another popover, when you want it to be rendered above. The `--wp-ui-select-z-index` CSS variable, available on the `Select.Popup` component, is an escape hatch that can be used to override the z-index of a given `Select` popover on a case-by-case basis.
const WithCustomZIndex = () => <Select.Root defaultValue="Item 1">(<>
        <Select.Trigger />
        <Select.Popup style={ { '--wp-ui-select-z-index': '1000001' } }>
            <Select.Item value="Item 1" />
            <Select.Item value="Item 2" />
        </Select.Popup>
    </>)</Select.Root>;

SelectControl

components-selectcontrol · ../packages/components/src/select-control/stories/index.story.tsx
`SelectControl` allows users to select from a single or multiple option menu. It functions as a wrapper around the browser's native `<select>` element. ```jsx import { SelectControl } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MySelectControl = () => { const [ size, setSize ] = useState( '50%' ); return ( <SelectControl __next40pxDefaultSize label="Size" value={ size } options={ [ { label: 'Big', value: '100%' }, { label: 'Medium', value: '50%' }, { label: 'Small', value: '25%' }, ] } onChange={ setSize } /> ); }; ```
Imports
import { InputControlPrefixWrapper, SelectControl } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	const [ selection, setSelection ] = useState< string[] >();

	if ( props.multiple ) {
		return (
			<SelectControl
				__next40pxDefaultSize
				{ ...props }
				multiple
				value={ selection }
				onChange={ ( value ) => {
					setSelection( value );
					props.onChange?.( value );
				} }
			/>
		);
	}

	return (
		<SelectControl
			__next40pxDefaultSize
			{ ...props }
			multiple={ false }
			value={ selection?.[ 0 ] }
			onChange={ ( value ) => {
				setSelection( [ value ] );
				props.onChange?.( value );
			} }
		/>
	);
};
With Label And Help Text story ok
const WithLabelAndHelpText = ( props ) => {
	const [ selection, setSelection ] = useState< string[] >();

	if ( props.multiple ) {
		return (
			<SelectControl
				__next40pxDefaultSize
				{ ...props }
				multiple
				value={ selection }
				onChange={ ( value ) => {
					setSelection( value );
					props.onChange?.( value );
				} }
			/>
		);
	}

	return (
		<SelectControl
			__next40pxDefaultSize
			{ ...props }
			multiple={ false }
			value={ selection?.[ 0 ] }
			onChange={ ( value ) => {
				setSelection( [ value ] );
				props.onChange?.( value );
			} }
		/>
	);
};
With Custom Children story ok
As an alternative to the `options` prop, `optgroup`s and `options` can be passed in as `children` for more customizeability.
const WithCustomChildren = ( props ) => {
	const [ selection, setSelection ] = useState< string[] >();

	if ( props.multiple ) {
		return (
			<SelectControl
				__next40pxDefaultSize
				{ ...props }
				multiple
				value={ selection }
				onChange={ ( value ) => {
					setSelection( value );
					props.onChange?.( value );
				} }
			/>
		);
	}

	return (
		<SelectControl
			__next40pxDefaultSize
			{ ...props }
			multiple={ false }
			value={ selection?.[ 0 ] }
			onChange={ ( value ) => {
				setSelection( [ value ] );
				props.onChange?.( value );
			} }
		/>
	);
};
With Prefix story ok
By default, the prefix is aligned with the edge of the input border, with no padding. If you want to apply standard padding in accordance with the size variant, wrap the element in the `<InputControlPrefixWrapper>` component.
const WithPrefix = ( props ) => {
	const [ selection, setSelection ] = useState< string[] >();

	if ( props.multiple ) {
		return (
			<SelectControl
				__next40pxDefaultSize
				{ ...props }
				multiple
				value={ selection }
				onChange={ ( value ) => {
					setSelection( value );
					props.onChange?.( value );
				} }
			/>
		);
	}

	return (
		<SelectControl
			__next40pxDefaultSize
			{ ...props }
			multiple={ false }
			value={ selection?.[ 0 ] }
			onChange={ ( value ) => {
				setSelection( [ value ] );
				props.onChange?.( value );
			} }
		/>
	);
};
Minimal story ok
const Minimal = ( props ) => {
	const [ selection, setSelection ] = useState< string[] >();

	if ( props.multiple ) {
		return (
			<SelectControl
				__next40pxDefaultSize
				{ ...props }
				multiple
				value={ selection }
				onChange={ ( value ) => {
					setSelection( value );
					props.onChange?.( value );
				} }
			/>
		);
	}

	return (
		<SelectControl
			__next40pxDefaultSize
			{ ...props }
			multiple={ false }
			value={ selection?.[ 0 ] }
			onChange={ ( value ) => {
				setSelection( [ value ] );
				props.onChange?.( value );
			} }
		/>
	);
};

Shortcut

components-shortcut · ../packages/components/src/shortcut/stories/index.story.tsx
Shortcut component is used to display keyboard shortcuts, and it can be customized with a custom display and aria label if needed. ```jsx import { Shortcut } from '@wordpress/components'; const MyShortcut = () => { return ( <Shortcut shortcut={{ display: 'Ctrl + S', ariaLabel: 'Save' }} /> ); }; ```
Prop types 2 prop types
Component: ../packages/components/src/shortcut/index.tsx::default
Props:
/**
 * Classname to apply to the shortcut.
 */
className?: string

/**
 * Shortcut configuration
 */
shortcut?: string | { display: string; ariaLabel: string }
Imports
import { Shortcut } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	return <Shortcut shortcut="Ctrl + S" { ...props } />;
};
With Aria Label story ok
const WithAriaLabel = ( props ) => {
	return <Shortcut shortcut="Ctrl + S" { ...props } />;
};

Slot

components-slotfill · ../packages/components/src/slot-fill/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Fill, Slot, Provider as SlotFillProvider } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	return (
		<SlotFillProvider>
			<h2>Profile</h2>
			<p>
				Name: <Slot { ...props } name="name" />
			</p>
			<p>
				Age: <Slot { ...props } name="age" />
			</p>
			<Fill name="name">Grace</Fill>
			<Fill name="age">33</Fill>
		</SlotFillProvider>
	);
};
With Fill Props story ok
const WithFillProps = ( props ) => {
	return (
		<SlotFillProvider>
			<h2>Profile</h2>
			<p>
				Name:{ ' ' }
				<Slot
					{ ...props }
					name="name"
					fillProps={ { name: 'Grace' } }
				/>
			</p>
			<p>
				Age: <Slot { ...props } name="age" fillProps={ { age: 33 } } />
			</p>

			<Fill name="name">{ ( fillProps ) => fillProps.name }</Fill>
			<Fill name="age">{ ( fillProps ) => fillProps.age }</Fill>
		</SlotFillProvider>
	);
};
With Slot Children story ok
const WithSlotChildren = ( props ) => {
	return (
		<SlotFillProvider>
			<h2>Profile</h2>
			<p>
				Name:
				{ /* @ts-expect-error Not supported children for `<Slot />` when `bubblesVirtually` is true. */ }
				<Slot { ...props } name="name">
					{ ( fills ) => {
						return (
							<span style={ { color: 'red' } }>{ fills }</span>
						);
					} }
				</Slot>
			</p>
			<p>
				Age:
				{ /* @ts-expect-error Not support children for `<Slot />` when `bubblesVirtually` is true. */ }
				<Slot { ...props } name="age">
					{ ( fills ) => {
						return (
							<span style={ { color: 'red' } }>{ fills }</span>
						);
					} }
				</Slot>
			</p>
			<Fill name="name">Alice</Fill>
			<Fill name="age">18</Fill>
		</SlotFillProvider>
	);
};
With Context story ok
const WithContext = ( props ) => {
	const Context = createContext< string | number >( '' );
	const ContextFill = ( { name }: { name: string } ) => {
		const value = useContext( Context );
		return <Fill name={ name }>{ value }</Fill>;
	};
	return (
		<SlotFillProvider>
			<h2>Profile</h2>
			<p>
				Name: <Slot { ...props } name="name" />
			</p>
			<p>
				Age: <Slot { ...props } name="age" />
			</p>
			<Context.Provider value="Grace">
				<ContextFill name="name" />
			</Context.Provider>
			<Context.Provider value={ 33 }>
				<ContextFill name="age" />
			</Context.Provider>
		</SlotFillProvider>
	);
};

Snackbar

components-snackbar · ../packages/components/src/snackbar/stories/index.story.tsx
A Snackbar displays a succinct message that is cleared out after a small delay. It can also offer the user options, like viewing a published post. But these options should also be available elsewhere in the UI. ```jsx const MySnackbarNotice = () => ( <Snackbar>Post published successfully.</Snackbar> ); ```
Prop types 5 prop types
Component: ../packages/components/src/snackbar/index.tsx::Snackbar
Props:
actions?: any = []

explicitDismiss?: any = false

icon?: any = null

politeness?: any = 'polite'

spokenMessage?: any = children
Imports
import { Icon, Snackbar } from "@wordpress/components";
Default story ok
const Default = ( {
	children,
	...props
} ) => {
	return <Snackbar { ...props }>{ children }</Snackbar>;
};
With Actions story ok
const WithActions = ( {
	children,
	...props
} ) => {
	return <Snackbar { ...props }>{ children }</Snackbar>;
};
With Icon story ok
const WithIcon = ( {
	children,
	...props
} ) => {
	return <Snackbar { ...props }>{ children }</Snackbar>;
};
With Explicit Dismiss story ok
const WithExplicitDismiss = ( {
	children,
	...props
} ) => {
	return <Snackbar { ...props }>{ children }</Snackbar>;
};
With Action And Explicit Dismiss story ok
const WithActionAndExplicitDismiss = ( {
	children,
	...props
} ) => {
	return <Snackbar { ...props }>{ children }</Snackbar>;
};

SnackbarList

components-snackbarlist · ../packages/components/src/snackbar/stories/list.story.tsx
Renders a list of notices. ```jsx const MySnackbarListNotice = () => ( <SnackbarList notices={ notices } onRemove={ removeNotice } /> ); ```
Imports
import { SnackbarList } from "@wordpress/components";
Default story ok
const Default = ( {
	children,
	notices: noticesProp,
	...props
} ) => {
	const [ notices, setNotices ] = useState( noticesProp );

	const onRemove = ( id: string ) => {
		const matchIndex = notices.findIndex( ( n ) => n.id === id );
		if ( matchIndex > -1 ) {
			setNotices( [
				...notices.slice( 0, matchIndex ),
				...notices.slice( matchIndex + 1 ),
			] );
		}
	};

	return (
		<SnackbarList { ...props } notices={ notices } onRemove={ onRemove }>
			{ children }
		</SnackbarList>
	);
};

Spacer

components-spacer · ../packages/components/src/spacer/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Spacer } from "@wordpress/components";
Default story ok
const Default = () => {
    return (
        <>
            <BlackBox />
            <Spacer>This is the spacer</Spacer>
            <BlackBox />
        </>
    );
};

Spinner

components-spinner · ../packages/components/src/spinner/stories/index.story.tsx
`Spinner` is a component used to notify users that their action is being processed. ```jsx import { Spinner } from '@wordpress/components'; function Example() { return <Spinner />; } ```
Imports
import { Spinner } from "@wordpress/components";
Default story ok
const Default = () => {
    return <Spinner />;
};
Custom Size story ok
const CustomSize = () => {
    return <Spinner style={{ width: space( 20 ), height: space( 20 ) }} />;
};

Stack

design-system-components-stack · ../packages/ui/src/stack/stories/index.story.tsx
A flexible layout component using CSS Flexbox for consistent spacing and alignment. Built on design tokens for predictable spacing values.
Prop types 8 prop types
Component: ../packages/ui/src/stack/stack.tsx::Stack
Props:
/**
 * The alignment of the stack items along the cross axis.
 * 
 * @default 'initial'
 */
align?: React.CSSProperties[ 'alignItems' ]

/**
 * The content to be rendered inside the component.
 */
children?: React.ReactNode

/**
 * CSS class name to apply to the component.
 */
className?: string

/**
 * The direction of the stack.
 */
direction?: Exclude<
	React.CSSProperties[ 'flexDirection' ],
	'row-reverse' | 'column-reverse'
>

/**
 * The amount of space between each child element using design system tokens.
 * 
 * @default undefined
 */
gap?: GapSize

/**
 * The alignment of the stack items along the main axis.
 * 
 * @default 'initial'
 */
justify?: React.CSSProperties[ 'justifyContent' ]

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: | ComponentRenderFn< HTMLAttributesWithRef >
| React.ReactElement< Record< string, unknown > >

/**
 * Whether the stack items should wrap to the next line.
 */
wrap?: Exclude< React.CSSProperties[ 'flexWrap' ], 'wrap-reverse' >
Imports
import { Stack } from "@wordpress/ui";
Default story ok
const Default = () => <Stack gap="md">(<>
        <DemoBox />
        <DemoBox variant="lg" />
        <DemoBox />
        <DemoBox />
        <DemoBox variant="lg" />
        <DemoBox />
    </>)</Stack>;
Nested story ok
const Nested = () => <Stack align="center" justify="center">(<>
        <DemoBox variant="lg" />
        <Stack gap="lg">
            <DemoBox />
            <DemoBox />
        </Stack>
        <DemoBox variant="lg" />
        <Stack direction="column">
            <DemoBox />
            <DemoBox />
        </Stack>
        <DemoBox variant="lg" />
    </>)</Stack>;

Surface

components-surface · ../packages/components/src/surface/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Surface, Text } from "@wordpress/components";
Default story ok
const Default = () => {
    return (
        <Surface style={ { padding: 20, maxWidth: 400, margin: '20vh auto' } }>
            <Text>Code is Poetry</Text>
        </Surface>
    );
};

TabbableContainer

components-tabbablecontainer · ../packages/components/src/navigable-container/stories/tabbable-container.story.tsx
A container for tabbable elements. ```jsx import { TabbableContainer, Button, } from '@wordpress/components'; function onNavigate( index, target ) { console.log( `Navigates to ${ index }`, target ); } const MyTabbableContainer = () => ( <div> <span>Tabbable Container:</span> <TabbableContainer onNavigate={ onNavigate }> <Button variant="secondary" tabIndex="0"> Section 1 </Button> <Button variant="secondary" tabIndex="0"> Section 2 </Button> <Button variant="secondary" tabIndex="0"> Section 3 </Button> <Button variant="secondary" tabIndex="0"> Section 4 </Button> </TabbableContainer> </div> ); ```
Imports
import { TabbableContainer } from "@wordpress/components";
Default story ok
const Default = () => {
    return (
        <>
            <button>Before tabbable container</button>
            <TabbableContainer
                onKeyDown={fn()}
                onNavigate={fn()}
                style={ {
					margin: '32px 0',
					padding: '16px',
					border: '1px solid black',
				} }>
                <button>Item 1</button>
                <button>Item 2</button>
                <button disabled>Item 3 (disabled)</button>
                <button tabIndex={ -1 }>Item 4 (non-tabbable)</button>
                <button tabIndex={ 0 }>Item 5</button>
                <button>Item 6</button>
            </TabbableContainer>
            <button>After tabbable container</button>
        </>
    );
};

TabbedSidebar

blockeditor-tabbedsidebar · ../packages/block-editor/src/components/tabbed-sidebar/stories/index.story.jsx
A component that creates a tabbed sidebar with a close button.
see: https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/tabbed-sidebar/README.md example: ```jsx function MyTabbedSidebar() { return ( <TabbedSidebar tabs={ [ { name: 'tab1', title: 'Settings', panel: <PanelContents />, } ] } onClose={ () => {} } onSelect={ () => {} } defaultTabId="tab1" selectedTab="tab1" closeButtonLabel="Close sidebar" /> ); } ```param: {Object} props Component props.param: {string} props.defaultTabId The ID of the tab to be selected by default when the component renders.param: {Function} props.onClose Function called when the close button is clicked.param: {Function} props.onSelect Function called when a tab is selected. Receives the selected tab's ID as an argument.param: {string} props.selectedTab The ID of the currently selected tab.param: {Array} props.tabs Array of tab objects. Each tab should have: name (string), title (string), panel (React.Node), and optionally panelRef (React.Ref).param: {string} props.closeButtonLabel Accessibility label for the close button.param: {Object} ref Forward ref to the tabs list element.return: {Element} The tabbed sidebar component.
Imports
import { TabbedSidebar } from "@wordpress/block-editor";
Default story ok
const Default = () => {
    const [ selectedTab, setSelectedTab ] = useState();

    return (
        <TabbedSidebar
            tabs={DEMO_TABS}
            defaultTabId="tab1"
            closeButtonLabel="Close Sidebar"
            selectedTab={ selectedTab }
            onSelect={ ( ...changeArgs ) => {
                onSelect( ...changeArgs );
                setSelectedTab( ...changeArgs );
            } }
            onClose={ onClose } />
    );
};

TabPanel

components-tabpanel · ../packages/components/src/tab-panel/stories/index.story.tsx
TabPanel is an ARIA-compliant tabpanel. TabPanels organize content across different screens, data sets, and interactions. It has two sections: a list of tabs, and the view to show when tabs are chosen. ```jsx import { TabPanel } from '@wordpress/components'; const onSelect = ( tabName ) => { console.log( 'Selecting tab', tabName ); }; const MyTabPanel = () => ( <TabPanel className="my-tab-panel" activeClass="active-tab" onSelect={ onSelect } tabs={ [ { name: 'tab1', title: 'Tab 1', className: 'tab-one', }, { name: 'tab2', title: 'Tab 2', className: 'tab-two', }, ] } > { ( tab ) => <p>{ tab.title }</p> } </TabPanel> ); ```
Prop types 3 prop types
Component: ../packages/components/src/tab-panel/index.tsx::TabPanel
Props:
activeClass?: any = 'is-active'

orientation?: any = 'horizontal'

selectOnMove?: any = true
Imports
import { TabPanel } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	return <TabPanel { ...props } />;
};
Disabled Tab story ok
const DisabledTab = ( props ) => {
	return <TabPanel { ...props } />;
};
With Tab Icons And Tooltips story ok
const WithTabIconsAndTooltips = ( props ) => {
	return <TabPanel { ...props } />;
};
Manual Activation story ok
const ManualActivation = ( props ) => {
	return <TabPanel { ...props } />;
};

Tabs

components-tabs · ../packages/components/src/tabs/stories/index.story.tsx
Tabs is a collection of React components that combine to render an [ARIA-compliant tabs pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/). Tabs organizes content across different screens, data sets, and interactions. It has two sections: a list of tabs, and the view to show when a tab is chosen. `Tabs` itself is a wrapper component and context provider. It is responsible for managing the state of the tabs, and rendering one instance of the `Tabs.TabList` component and one or more instances of the `Tab.TabPanel` component.
Prop types 9 prop types
Component: ../packages/components/src/tabs/index.tsx::Tabs
Props:
/**
 * The current active tab `id`. The active tab is the tab element within the
 * tablist widget that has DOM focus.
 * 
 * - `null` represents the tablist (ie. the base composite element). Users
 *   will be able to navigate out of it using arrow keys.
 * - If `activeTabId` is initially set to `null`, the base composite element
 *   itself will have focus and users will be able to navigate to it using
 *   arrow keys.
 */
activeTabId?: Ariakit.TabProviderProps[ 'activeId' ]

/**
 * The children elements, which should include one instance of the
 * `Tabs.Tablist` component and as many instances of the `Tabs.TabPanel`
 * components as there are `Tabs.Tab` components.
 */
children: Ariakit.TabProviderProps[ 'children' ]

/**
 * The tab id that should be active by default when the composite widget is
 * rendered. If `null`, the tablist element itself will have focus
 * and users will be able to navigate to it using arrow keys. If `undefined`,
 * the first enabled item will be focused.
 * 
 * Note: this prop will be overridden by the `activeTabId` prop if it is
 * provided.
 */
defaultActiveTabId?: Ariakit.TabProviderProps[ 'defaultActiveId' ]

/**
 * The id of the tab whose panel is currently visible.
 * 
 * If left `undefined`, it will be automatically set to the first enabled
 * tab. If set to `null`, no tab will be selected, and the tablist will be
 * tabbable.
 * 
 * Note: this prop will be overridden by the `selectedTabId` prop if it is
 * provided (meaning the component will be used in "controlled" mode).
 */
defaultTabId?: Ariakit.TabProviderProps[ 'defaultSelectedId' ]

/**
 * A callback that gets called when the `activeTabId` state changes.
 */
onActiveTabIdChange?: Ariakit.TabProviderProps[ 'setActiveId' ]

/**
 * The function called when the `selectedTabId` changes.
 */
onSelect?: Ariakit.TabProviderProps[ 'setSelectedId' ]

/**
 * Defines the orientation of the tablist and determines which arrow keys
 * can be used to move focus:
 * 
 * - `both`: all arrow keys work.
 * - `horizontal`: only left and right arrow keys work.
 * - `vertical`: only up and down arrow keys work.
 * 
 * @default "horizontal"
 */
orientation?: Ariakit.TabProviderProps[ 'orientation' ] = 'horizontal'

/**
 * The id of the tab whose panel is currently visible.
 * 
 * If left `undefined`, it will be automatically set to the first enabled
 * tab, and the component assumes it is being used in "uncontrolled" mode.
 * 
 * Consequently, any value different than `undefined` will set the component
 * in "controlled" mode. When in "controlled" mode, the `null` value will
 * result in no tabs being selected, and the tablist becoming tabbable.
 */
selectedTabId?: Ariakit.TabProviderProps[ 'selectedId' ]

/**
 * Determines if the tab should be selected when it receives focus. If set to
 * `false`, the tab will only be selected upon clicking, not when using arrow
 * keys to shift focus (manual tab activation). See the [official W3C docs](https://www.w3.org/WAI/ARIA/apg/patterns/tabpanel/)
 * for more info.
 * 
 * @default true
 */
selectOnMove?: Ariakit.TabProviderProps[ 'selectOnMove' ] = true
Imports
import { Button, Fill, Icon, Slot, Provider as SlotFillProvider, Tabs, Tooltip } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	return (
		<Tabs { ...props }>
			<Tabs.TabList>
				<Tabs.Tab tabId="tab1">Tab 1</Tabs.Tab>
				<Tabs.Tab tabId="tab2">Tab 2</Tabs.Tab>
				<Tabs.Tab tabId="tab3">Tab 3</Tabs.Tab>
			</Tabs.TabList>
			<Tabs.TabPanel tabId="tab1">
				<p>Selected tab: Tab 1</p>
			</Tabs.TabPanel>
			<Tabs.TabPanel tabId="tab2">
				<p>Selected tab: Tab 2</p>
			</Tabs.TabPanel>
			<Tabs.TabPanel tabId="tab3" focusable={ false }>
				<p>Selected tab: Tab 3</p>
				<p>
					This tabpanel has its <code>focusable</code> prop set to
					<code> false</code>, so it won&apos;t get a tab stop.
					<br />
					Instead, the [Tab] key will move focus to the first
					focusable element within the panel.
				</p>
				<Button __next40pxDefaultSize variant="primary">
					I&apos;m a button!
				</Button>
			</Tabs.TabPanel>
		</Tabs>
	);
};
Size And Overflow Playground story ok
const SizeAndOverflowPlayground = ( props ) => {
	const [ fullWidth, setFullWidth ] = useState( false );
	return (
		<div>
			<div style={ { maxWidth: '40rem', marginBottom: '1rem' } }>
				<p>
					This story helps understand how the TabList component
					behaves under different conditions. The container below
					(with the dotted red border) can be horizontally resized,
					and it has a bit of padding to be out of the way of the
					TabList.
				</p>
				<p>
					The button will toggle between full width (adding{ ' ' }
					<code>width: 100%</code>) and the default width.
				</p>
				<p>Try the following:</p>
				<ul>
					<li>
						<strong>Small container</strong> that causes tabs to
						overflow with scroll.
					</li>
					<li>
						<strong>Large container</strong> that exceeds the normal
						width of the tabs.
						<ul>
							<li>
								<strong>
									With <code>width: 100%</code>
								</strong>{ ' ' }
								set on the TabList (tabs fill up the space).
							</li>
							<li>
								<strong>
									Without <code>width: 100%</code>
								</strong>{ ' ' }
								(defaults to <code>auto</code>) set on the
								TabList (tabs take up space proportional to
								their content).
							</li>
						</ul>
					</li>
				</ul>
			</div>
			<Button
				__next40pxDefaultSize
				style={ { marginBottom: '1rem' } }
				variant="primary"
				onClick={ () => setFullWidth( ! fullWidth ) }
			>
				{ fullWidth
					? 'Remove width: 100% from TabList'
					: 'Set width: 100% in TabList' }
			</Button>
			<Tabs { ...props }>
				<div
					style={ {
						width: '20rem',
						border: '2px dotted red',
						padding: '1rem',
						resize: 'horizontal',
						overflow: 'auto',
					} }
				>
					<Tabs.TabList
						style={ {
							maxWidth: '100%',
							width: fullWidth ? '100%' : undefined,
						} }
					>
						<Tabs.Tab tabId="tab1">
							Label with multiple words
						</Tabs.Tab>
						<Tabs.Tab tabId="tab2">Short</Tabs.Tab>
						<Tabs.Tab tabId="tab3">
							Hippopotomonstrosesquippedaliophobia
						</Tabs.Tab>
						<Tabs.Tab tabId="tab4">Tab 4</Tabs.Tab>
						<Tabs.Tab tabId="tab5">Tab 5</Tabs.Tab>
					</Tabs.TabList>
				</div>
				<Tabs.TabPanel tabId="tab1">
					<p>Selected tab: Tab 1</p>
					<p>(Label with multiple words)</p>
				</Tabs.TabPanel>
				<Tabs.TabPanel tabId="tab2">
					<p>Selected tab: Tab 2</p>
					<p>(Short)</p>
				</Tabs.TabPanel>
				<Tabs.TabPanel tabId="tab3">
					<p>Selected tab: Tab 3</p>
					<p>(Hippopotomonstrosesquippedaliophobia)</p>
				</Tabs.TabPanel>
				<Tabs.TabPanel tabId="tab4">
					<p>Selected tab: Tab 4</p>
				</Tabs.TabPanel>
				<Tabs.TabPanel tabId="tab5">
					<p>Selected tab: Tab 5</p>
				</Tabs.TabPanel>
			</Tabs>
		</div>
	);
};
Vertical story ok
const Vertical = ( props ) => {
	return (
		<Tabs orientation="vertical" { ...props }>
			<Tabs.TabList style={ { maxWidth: '10rem' } }>
				<Tabs.Tab tabId="tab1">Tab 1</Tabs.Tab>
				<Tabs.Tab tabId="tab2">Tab 2</Tabs.Tab>
				<Tabs.Tab tabId="tab3">Tab 3</Tabs.Tab>
			</Tabs.TabList>
		</Tabs>
	);
};
Disabled Tab story ok
const DisabledTab = ( props ) => {
	return (
		<Tabs { ...props }>
			<Tabs.TabList>
				<Tabs.Tab tabId="tab1" disabled>
					Tab 1
				</Tabs.Tab>
				<Tabs.Tab tabId="tab2">Tab 2</Tabs.Tab>
				<Tabs.Tab tabId="tab3">Tab 3</Tabs.Tab>
			</Tabs.TabList>
			<Tabs.TabPanel tabId="tab1">
				<p>Selected tab: Tab 1</p>
			</Tabs.TabPanel>
			<Tabs.TabPanel tabId="tab2">
				<p>Selected tab: Tab 2</p>
			</Tabs.TabPanel>
			<Tabs.TabPanel tabId="tab3">
				<p>Selected tab: Tab 3</p>
			</Tabs.TabPanel>
		</Tabs>
	);
};
With Tab Icons And Tooltips story ok
const WithTabIconsAndTooltips = ( props ) => {
	return (
		<Tabs { ...props }>
			<Tabs.TabList>
				{ [
					{
						id: 'tab1',
						label: 'Tab one',
						icon: wordpress,
					},
					{
						id: 'tab2',
						label: 'Tab two',
						icon: link,
					},
					{
						id: 'tab3',
						label: 'Tab three',
						icon: more,
					},
				].map( ( { id, label, icon } ) => (
					<Tooltip text={ label } key={ id }>
						<Tabs.Tab tabId={ id } aria-label={ label }>
							<Icon icon={ icon } />
						</Tabs.Tab>
					</Tooltip>
				) ) }
			</Tabs.TabList>
			<Tabs.TabPanel tabId="tab1">
				<p>Selected tab: Tab 1</p>
			</Tabs.TabPanel>
			<Tabs.TabPanel tabId="tab2">
				<p>Selected tab: Tab 2</p>
			</Tabs.TabPanel>
			<Tabs.TabPanel tabId="tab3">
				<p>Selected tab: Tab 3</p>
			</Tabs.TabPanel>
		</Tabs>
	);
};
Manual Activation story ok
const ManualActivation = ( props ) => {
	return (
		<Tabs { ...props }>
			<Tabs.TabList>
				<Tabs.Tab tabId="tab1">Tab 1</Tabs.Tab>
				<Tabs.Tab tabId="tab2">Tab 2</Tabs.Tab>
				<Tabs.Tab tabId="tab3">Tab 3</Tabs.Tab>
			</Tabs.TabList>
			<Tabs.TabPanel tabId="tab1">
				<p>Selected tab: Tab 1</p>
			</Tabs.TabPanel>
			<Tabs.TabPanel tabId="tab2">
				<p>Selected tab: Tab 2</p>
			</Tabs.TabPanel>
			<Tabs.TabPanel tabId="tab3" focusable={ false }>
				<p>Selected tab: Tab 3</p>
				<p>
					This tabpanel has its <code>focusable</code> prop set to
					<code> false</code>, so it won&apos;t get a tab stop.
					<br />
					Instead, the [Tab] key will move focus to the first
					focusable element within the panel.
				</p>
				<Button __next40pxDefaultSize variant="primary">
					I&apos;m a button!
				</Button>
			</Tabs.TabPanel>
		</Tabs>
	);
};
Using SlotFill story ok
const UsingSlotFill = ( props ) => {
	return (
		<SlotFillProvider>
			<Tabs { ...props }>
				<Tabs.TabList>
					<Tabs.Tab tabId="tab1">Tab 1</Tabs.Tab>
					<Tabs.Tab tabId="tab2">Tab 2</Tabs.Tab>
					<Tabs.Tab tabId="tab3">Tab 3</Tabs.Tab>
				</Tabs.TabList>
				<Fill name="tabs-are-fun">
					<Tabs.TabPanel tabId="tab1">
						<p>Selected tab: Tab 1</p>
					</Tabs.TabPanel>
					<Tabs.TabPanel tabId="tab2">
						<p>Selected tab: Tab 2</p>
					</Tabs.TabPanel>
					<Tabs.TabPanel tabId="tab3">
						<p>Selected tab: Tab 3</p>
					</Tabs.TabPanel>
				</Fill>
			</Tabs>
			<div
				style={ {
					border: '2px solid #999',
					width: '300px',
					margin: '20px auto',
				} }
			>
				<p>other stuff</p>
				<p>other stuff</p>
				<p>this is fun!</p>
				<p>other stuff</p>
				<Slot bubblesVirtually as="div" name="tabs-are-fun" />
			</div>
		</SlotFillProvider>
	);
};
Insert Custom Elements story ok
const InsertCustomElements = ( props ) => {
	const [ isOpen, setIsOpen ] = useState( true );

	return (
		<>
			{ isOpen ? (
				<div
					style={ {
						width: '400px',
						height: '100vh',
						borderRight: '1px solid #333',
					} }
				>
					<Tabs { ...props }>
						<div
							style={ {
								display: 'flex',
								borderBottom: '1px solid #333',
							} }
						>
							<Tabs.TabList>
								<Tabs.Tab tabId="tab1">Tab 1</Tabs.Tab>
								<Tabs.Tab tabId="tab2">Tab 2</Tabs.Tab>
								<Tabs.Tab tabId="tab3">Tab 3</Tabs.Tab>
							</Tabs.TabList>
							<Button
								__next40pxDefaultSize
								variant="tertiary"
								style={ {
									marginLeft: 'auto',
									alignSelf: 'center',
								} }
								onClick={ () => setIsOpen( false ) }
							>
								Close Tabs
							</Button>
						</div>
						<Tabs.TabPanel tabId="tab1">
							<p>Selected tab: Tab 1</p>
						</Tabs.TabPanel>
						<Tabs.TabPanel tabId="tab2">
							<p>Selected tab: Tab 2</p>
						</Tabs.TabPanel>
						<Tabs.TabPanel tabId="tab3">
							<p>Selected tab: Tab 3</p>
						</Tabs.TabPanel>
					</Tabs>
				</div>
			) : (
				<Button
					__next40pxDefaultSize
					variant="tertiary"
					onClick={ () => setIsOpen( true ) }
				>
					Open Tabs
				</Button>
			) }
		</>
	);
};

Tabs.Root

design-system-components-tabs · ../packages/ui/src/tabs/stories/index.story.tsx
A badge component for displaying labels with semantic intent.
Prop types 4 prop types
Component: ../packages/ui/src/badge/badge.tsx::Badge
Props:
/**
 * The text to display in the badge.
 */
children: string

/**
 * CSS class name to apply to the component.
 */
className?: string

/**
 * The semantic intent of the badge, communicating its meaning through color.
 * 
 * @default "none"
 */
intent?: | 'high'
| 'medium'
| 'low'
| 'stable'
| 'informational'
| 'draft'
| 'none' = 'none'

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: | ComponentRenderFn< HTMLAttributesWithRef >
| React.ReactElement< Record< string, unknown > >
Imports
import { Tabs, Tooltip } from "@wordpress/ui";
Default story ok
const Default = () => <Tabs.Root defaultValue="tab1">(<>
        <Tabs.List>
            <Tabs.Tab value="tab1">Tab 1</Tabs.Tab>
            <Tabs.Tab value="tab2">Tab 2</Tabs.Tab>
            <Tabs.Tab value="tab3">Tab 3</Tabs.Tab>
        </Tabs.List>
        <Tabs.Panel value="tab1">
            <ThemedParagraph>Selected tab: Tab 1</ThemedParagraph>
        </Tabs.Panel>
        <Tabs.Panel value="tab2">
            <ThemedParagraph>Selected tab: Tab 2</ThemedParagraph>
        </Tabs.Panel>
        <Tabs.Panel value="tab3">
            <ThemedParagraph>Selected tab: Tab 3</ThemedParagraph>
        </Tabs.Panel>
    </>)</Tabs.Root>;
Minimal story ok
const Minimal = () => <Tabs.Root>(<>
        <Tabs.List variant="minimal">
            <Tabs.Tab value="tab1">Tab 1</Tabs.Tab>
            <Tabs.Tab value="tab2">Tab 2</Tabs.Tab>
            <Tabs.Tab value="tab3">Tab 3</Tabs.Tab>
        </Tabs.List>
        <Tabs.Panel value="tab1">
            <ThemedParagraph>Selected tab: Tab 1</ThemedParagraph>
        </Tabs.Panel>
        <Tabs.Panel value="tab2">
            <ThemedParagraph>Selected tab: Tab 2</ThemedParagraph>
        </Tabs.Panel>
        <Tabs.Panel value="tab3">
            <ThemedParagraph>Selected tab: Tab 3</ThemedParagraph>
        </Tabs.Panel>
    </>)</Tabs.Root>;
Size And Overflow Playground story ok
const SizeAndOverflowPlayground = function SizeAndOverflowPlayground( props ) {
    const [ fullWidth, setFullWidth ] = useState( false );
    return (
        <div>
            <div
                style={ {
                    maxWidth: '40rem',
                    marginBottom: '1rem',
                    color: 'var( --wpds-color-fg-content-neutral )',
                } }
            >
                <p>
                    This story helps understand how the TabList component
                    behaves under different conditions. The container below
                    (with the dotted red border) can be horizontally
                    resized, and it has a bit of padding to be out of the
                    way of the TabList.
                </p>
                <p>
                    The button will toggle between full width (adding{ ' ' }
                    <code>width: 100%</code>) and the default width.
                </p>
                <p>Try the following:</p>
                <ul>
                    <li>
                        <strong>Small container</strong> that causes tabs to
                        overflow with scroll.
                    </li>
                    <li>
                        <strong>Large container</strong> that exceeds the
                        normal width of the tabs.
                        <ul>
                            <li>
                                <strong>
                                    With <code>width: 100%</code>
                                </strong>{ ' ' }
                                set on the TabList (tabs fill up the space).
                            </li>
                            <li>
                                <strong>
                                    Without <code>width: 100%</code>
                                </strong>{ ' ' }
                                (defaults to <code>auto</code>) set on the
                                TabList (tabs take up space proportional to
                                their content).
                            </li>
                        </ul>
                    </li>
                </ul>
            </div>
            <button
                style={ { marginBottom: '1rem' } }
                onClick={ () => setFullWidth( ! fullWidth ) }
            >
                { fullWidth
                    ? 'Remove width: 100% from TabList'
                    : 'Set width: 100% in TabList' }
            </button>
            <Tabs.Root
                { ...props }
                style={ {
                    ...props.style,
                    width: '20rem',
                    border: '2px dotted red',
                    padding: '1rem',
                    resize: 'horizontal',
                    overflow: 'auto',
                } }
            >
                <Tabs.List
                    style={ {
                        maxWidth: '100%',
                        width: fullWidth ? '100%' : undefined,
                    } }
                >
                    <Tabs.Tab value="tab1">
                        Label with multiple words
                    </Tabs.Tab>
                    <Tabs.Tab value="tab2">Short</Tabs.Tab>
                    <Tabs.Tab value="tab3">
                        Hippopotomonstrosesquippedaliophobia
                    </Tabs.Tab>
                    <Tabs.Tab value="tab4">Tab 4</Tabs.Tab>
                    <Tabs.Tab value="tab5">Tab 5</Tabs.Tab>
                </Tabs.List>

                <Tabs.Panel value="tab1">
                    <ThemedParagraph>Selected tab: Tab 1</ThemedParagraph>
                    <ThemedParagraph>
                        (Label with multiple words)
                    </ThemedParagraph>
                </Tabs.Panel>
                <Tabs.Panel value="tab2">
                    <ThemedParagraph>Selected tab: Tab 2</ThemedParagraph>
                    <ThemedParagraph>(Short)</ThemedParagraph>
                </Tabs.Panel>
                <Tabs.Panel value="tab3">
                    <ThemedParagraph>Selected tab: Tab 3</ThemedParagraph>
                    <ThemedParagraph>
                        (Hippopotomonstrosesquippedaliophobia)
                    </ThemedParagraph>
                </Tabs.Panel>
                <Tabs.Panel value="tab4">
                    <ThemedParagraph>Selected tab: Tab 4</ThemedParagraph>
                </Tabs.Panel>
                <Tabs.Panel value="tab5">
                    <ThemedParagraph>Selected tab: Tab 5</ThemedParagraph>
                </Tabs.Panel>
            </Tabs.Root>
        </div>
    );
};
Vertical story ok
const Vertical = () => <Tabs.Root
    orientation="vertical"
    style={{
        minWidth: '320px',
        display: 'grid',
        gridTemplateColumns: '120px 1fr',
        gap: '24px',
    }} />;
With Disabled Tab story ok
const WithDisabledTab = () => <Tabs.Root defaultValue="tab3">(<>
        <Tabs.List>
            <Tabs.Tab value="tab1" disabled>
                Tab 1
            </Tabs.Tab>
            <Tabs.Tab value="tab2">Tab 2</Tabs.Tab>
            <Tabs.Tab value="tab3">Tab 3</Tabs.Tab>
        </Tabs.List>
        <Tabs.Panel value="tab1">
            <ThemedParagraph>Selected tab: Tab 1</ThemedParagraph>
        </Tabs.Panel>
        <Tabs.Panel value="tab2">
            <ThemedParagraph>Selected tab: Tab 2</ThemedParagraph>
        </Tabs.Panel>
        <Tabs.Panel value="tab3">
            <ThemedParagraph>Selected tab: Tab 3</ThemedParagraph>
        </Tabs.Panel>
    </>)</Tabs.Root>;
With Tab Icons And Tooltips story ok
const WithTabIconsAndTooltips = () => <Tabs.Root>(<>
        <Tabs.List>
            { tabWithIconsData.map(
                ( { value, label, icon: Icon } ) => (
                    <Tooltip.Root key={ value }>
                        <Tooltip.Trigger
                            aria-label={ label }
                            render={ <Tabs.Tab value={ value } /> }
                        >
                            { /* TODO: potentially refactor with new Icon component */ }
                            <Icon
                                style={ {
                                    width: '20px',
                                    height: '20px',
                                } }
                            />
                        </Tooltip.Trigger>
                        <Tooltip.Popup align="center" side="top">
                            { label }
                        </Tooltip.Popup>
                    </Tooltip.Root>
                )
            ) }
        </Tabs.List>
        { tabWithIconsData.map( ( { value, label } ) => (
            <Tabs.Panel value={ value } key={ value }>
                <ThemedParagraph>
                    Selected tab: { label }
                </ThemedParagraph>
            </Tabs.Panel>
        ) ) }
    </>)</Tabs.Root>;
With Panels Always Mounted story ok
const WithPanelsAlwaysMounted = () => <Tabs.Root>(<>
        <Tabs.List>
            <Tabs.Tab value="tab1">Tab 1</Tabs.Tab>
            <Tabs.Tab value="tab2">Tab 2</Tabs.Tab>
            <Tabs.Tab value="tab3">Tab 3</Tabs.Tab>
        </Tabs.List>
        <Tabs.Panel value="tab1" keepMounted>
            <ThemedParagraph>Selected tab: Tab 1</ThemedParagraph>
        </Tabs.Panel>
        <Tabs.Panel value="tab2" keepMounted>
            <ThemedParagraph>Selected tab: Tab 2</ThemedParagraph>
        </Tabs.Panel>
        <Tabs.Panel value="tab3" keepMounted>
            <ThemedParagraph>Selected tab: Tab 3</ThemedParagraph>
        </Tabs.Panel>
    </>)</Tabs.Root>;
With Non Focusable Panels story ok
const WithNonFocusablePanels = () => <Tabs.Root>(<>
        <Tabs.List>
            <Tabs.Tab value="tab1">Tab 1</Tabs.Tab>
            <Tabs.Tab value="tab2">Tab 2</Tabs.Tab>
            <Tabs.Tab value="tab3">Tab 3</Tabs.Tab>
        </Tabs.List>
        <Tabs.Panel value="tab1" tabIndex={ -1 }>
            <ThemedParagraph>Selected tab: Tab 1</ThemedParagraph>
            <ThemedParagraph>
                This tabpanel is not focusable, therefore tabbing into
                it will focus its first tabbable child.
            </ThemedParagraph>
            <button>Focus me</button>
        </Tabs.Panel>
        <Tabs.Panel value="tab2" tabIndex={ -1 }>
            <ThemedParagraph>Selected tab: Tab 2</ThemedParagraph>
            <ThemedParagraph>
                This tabpanel is not focusable, therefore tabbing into
                it will focus its first tabbable child.
            </ThemedParagraph>
            <button>Focus me</button>
        </Tabs.Panel>
        <Tabs.Panel value="tab3" tabIndex={ -1 }>
            <ThemedParagraph>Selected tab: Tab 3</ThemedParagraph>
            <ThemedParagraph>
                This tabpanel is not focusable, therefore tabbing into
                it will focus its first tabbable child.
            </ThemedParagraph>
            <button>Focus me</button>
        </Tabs.Panel>
    </>)</Tabs.Root>;

Text

components-text · ../packages/components/src/text/stories/index.story.tsx
param: props param: forwardedRef
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Text } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	return <Text { ...props } />;
};
Truncate story ok
const Truncate = ( props ) => {
	return <Text { ...props } />;
};
Highlight story ok
const Highlight = ( props ) => {
	return <Text { ...props } />;
};

Text

design-system-components-text · ../packages/ui/src/text/stories/index.story.tsx
A text component for rendering content with predefined typographic variants. Built on design tokens for consistent typography across the UI.
Prop types 4 prop types
Component: ../packages/ui/src/text/text.tsx::Text
Props:
/**
 * The content to be rendered inside the component.
 */
children?: React.ReactNode

/**
 * CSS class name to apply to the component.
 */
className?: string

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: | ComponentRenderFn< HTMLAttributesWithRef >
| React.ReactElement< Record< string, unknown > >

/**
 * The typographic variant to apply, controlling font family, size,
 * line height, and weight.
 * 
 * @default "body-md"
 */
variant?: | 'heading-2xl'
| 'heading-xl'
| 'heading-lg'
| 'heading-md'
| 'heading-sm'
| 'body-xl'
| 'body-lg'
| 'body-md'
| 'body-sm' = 'body-md'
Imports
import { Stack, Text } from "@wordpress/ui";
Default story ok
const Default = () => <Text variant="body-md">The quick brown fox jumps over the lazy dog.</Text>;
All Variants story ok
Important: Setting the `variant` prop to a `heading` variant will not automatically render a heading element. Use the `render` prop to render a heading element with the appropriate level.
const AllVariants = () => (
    <Stack
        direction="column"
        gap="lg"
        style={ { color: 'var(--wpds-color-fg-content-neutral)' } }
    >
        { (
            [
                'heading-2xl',
                'heading-xl',
                'heading-lg',
                'heading-md',
                'heading-sm',
                'body-xl',
                'body-lg',
                'body-md',
                'body-sm',
            ] as const
         ).map( ( variant ) => (
            <Stack key={ variant } direction="column" gap="xs">
                <Text variant="heading-sm">{ variant }</Text>
                <Text variant={ variant }>
                    The quick brown fox jumps over the lazy dog.
                </Text>
            </Stack>
        ) ) }
    </Stack>
);
With Render Prop story ok
const WithRenderProp = () => (
    <Stack direction="column" gap="md">
        <Text variant="heading-2xl" render={ <h1 /> }>
            Page Title
        </Text>
        <Text variant="heading-xl" render={ <h2 /> }>
            Section Heading
        </Text>
        <Text variant="body-md" render={ <p /> }>
            A paragraph of body text rendered as a semantic paragraph
            element.
        </Text>
    </Stack>
);

TextAlignmentControl

blockeditor-textalignmentcontrol · ../packages/block-editor/src/components/text-alignment-control/stories/index.story.jsx
Control to facilitate text alignment selections.
param: {Object} props Component props.param: {string} props.className Class name to add to the control.param: {string} props.value Currently selected text alignment.param: {Function} props.onChange Handles change in text alignment selection.param: {string[]} props.options Array of text alignment options to display.return: {Element} Text alignment control.
Prop types 1 prop type
Component: ../packages/block-editor/src/components/text-alignment-control/index.js::default
Props:
options?: any = [ 'left', 'center', 'right' ]
Imports
import { TextAlignmentControl } from "@wordpress/block-editor";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState();

    return (
        <TextAlignmentControl
            onChange={ ( ...changeArgs ) => {
                onChange( ...changeArgs );
                setValue( ...changeArgs );
            } }
            value={ value } />
    );
};

Textarea

design-system-components-form-primitives-textarea · ../packages/ui/src/form/primitives/textarea/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 1 prop type
Component: ../packages/ui/src/form/primitives/textarea/textarea.tsx::Textarea
Props:
/**
 * The number of rows the textarea should contain.
 * 
 * @default 4
 */
rows?: React.ComponentProps< 'textarea' >[ 'rows' ] = 4
Imports
import { Textarea } from "@wordpress/ui";
Default story ok
const Default = () => <Textarea placeholder="Placeholder" />;
Disabled story ok
const Disabled = () => <Textarea disabled />;
With Overflow story ok
const WithOverflow = () => <Textarea
    defaultValue={`Lorem ipsum dolor sit amet, consectetur adipisicing 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`} />;
With One Row story ok
When `rows` is set to `1`, the textarea will have the same footprint as a default `Input`.
const WithOneRow = () => <Textarea rows={1} />;

TextareaControl

components-textareacontrol · ../packages/components/src/textarea-control/stories/index.story.tsx
TextareaControls are TextControls that allow for multiple lines of text, and wrap overflow text onto a new line. They are a fixed height and scroll vertically when the cursor reaches the bottom of the field. ```jsx import { TextareaControl } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyTextareaControl = () => { const [ text, setText ] = useState( '' ); return ( <TextareaControl label="Text" help="Enter some text" value={ text } onChange={ ( value ) => setText( value ) } /> ); }; ```
Imports
import { TextareaControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState( '' );

    return (
        <TextareaControl
            label="Text"
            help="Enter some text"
            placeholder="Placeholder"
            value={ value }
            onChange={ ( v ) => {
				setValue( v );
				onChange( v );
			} } />
    );
};

TextControl

components-textcontrol · ../packages/components/src/text-control/stories/index.story.tsx
TextControl components let users enter and edit text. ```jsx import { TextControl } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyTextControl = () => { const [ className, setClassName ] = useState( '' ); return ( <TextControl __next40pxDefaultSize label="Additional CSS Class" value={ className } onChange={ ( value ) => setClassName( value ) } /> ); }; ```
Imports
import { TextControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState( '' );

    return (
        <TextControl
            __next40pxDefaultSize
            placeholder="Placeholder"
            value={ value }
            onChange={ ( v ) => {
				setValue( v );
				onChange( v );
			} } />
    );
};
With Label And Help Text story ok
const WithLabelAndHelpText = () => {
    const [ value, setValue ] = useState( '' );

    return (
        <TextControl
            __next40pxDefaultSize
            label="Label Text"
            help="Help text to explain the input."
            value={ value }
            onChange={ ( v ) => {
				setValue( v );
				onChange( v );
			} } />
    );
};

TextDecorationControl

blockeditor-textdecorationcontrol · ../packages/block-editor/src/components/text-decoration-control/stories/index.story.jsx
Control to facilitate text decoration selections.
param: {Object} props Component props.param: {string} props.value Currently selected text decoration.param: {Function} props.onChange Handles change in text decoration selection.param: {string} props.className Additional class name to apply.return: {Element} Text decoration control.
Imports
import { TextDecorationControl } from "@wordpress/block-editor";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState();

    return (
        <TextDecorationControl
            onChange={ ( ...changeArgs ) => {
                onChange( ...changeArgs );
                setValue( ...changeArgs );
            } }
            value={ value } />
    );
};

TextHighlight

components-texthighlight · ../packages/components/src/text-highlight/stories/index.story.tsx
Highlights occurrences of a given string within another string of text. Wraps each match with a `<mark>` tag which provides browser default styling. ```jsx import { TextHighlight } from '@wordpress/components'; const MyTextHighlight = () => ( <TextHighlight text="Why do we like Gutenberg? Because Gutenberg is the best!" highlight="Gutenberg" /> ); ```
Prop types 2 prop types
Component: ../packages/components/src/text-highlight/index.tsx::TextHighlight
Props:
/**
 * The string to search for and highlight within the `text`. Case
 * insensitive. Multiple matches.
 * 
 * @default ''
 */
highlight: string

/**
 * The string of text to be tested for occurrences of then given
 * `highlight`.
 * 
 * @default ''
 */
text: string
Imports
import { TextHighlight } from "@wordpress/components";
Default story ok
const Default = () => {
    return (
        <TextHighlight
            text="We call the new editor Gutenberg. The entire editing experience has been rebuilt for media rich pages and posts."
            highlight="Gutenberg" />
    );
};

TextTransformControl

blockeditor-texttransformcontrol · ../packages/block-editor/src/components/text-transform-control/stories/index.story.jsx
Control to facilitate text transform selections.
param: {Object} props Component props.param: {string} props.className Class name to add to the control.param: {string} props.value Currently selected text transform.param: {Function} props.onChange Handles change in text transform selection.return: {Element} Text transform control.
Imports
import { TextTransformControl } from "@wordpress/block-editor";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState();

    return (
        <TextTransformControl
            onChange={ ( ...changeArgs ) => {
                onChange( ...changeArgs );
                setValue( ...changeArgs );
            } }
            value={ value } />
    );
};

Theme

components-theme · ../packages/components/src/theme/stories/index.story.tsx
`Theme` allows defining theme variables for components in the `@wordpress/components` package. Multiple `Theme` components can be nested in order to override specific theme variables. ```jsx const Example = () => { return ( <Theme accent="red"> <Button variant="primary">I'm red</Button> <Theme accent="blue"> <Button variant="primary">I'm blue</Button> </Theme> </Theme> ); }; ```
Imports
import { Button, HStack, Theme } from "@wordpress/components";
Default story ok
const Default = () => <Theme>
    <Button __next40pxDefaultSize variant="primary">Hello
                </Button>
</Theme>;
Nested story ok
const Nested = () => <Theme accent="crimson">
    <Button __next40pxDefaultSize variant="primary">Outer theme (hardcoded)
                </Button>
    <Theme accent="blue">
        <Button __next40pxDefaultSize variant="primary">Inner theme (set via Storybook controls)
                        </Button>
    </Theme>
</Theme>;
Color Scheme story ok
The rest of the required colors are generated based on the given accent and background colors.
const ColorScheme = ( {
	accent,
	background,
} ) => {
	const { colors } = generateThemeVariables( { accent, background } );
	const { gray, ...otherColors } = colors;
	/* eslint-disable @typescript-eslint/no-unused-vars */
	const contrastIssues = Object.entries(
		checkContrasts( { accent, background }, colors )
	).filter( ( [ _, error ] ) => !! error );
	/* eslint-enable @typescript-eslint/no-unused-vars */

	const Chip = ( { color, name }: { color: string; name: string } ) => (
		<HStack justify="flex-start">
			<div
				style={ {
					backgroundColor: color,
					height: '1.25em',
					width: 40,
				} }
			/>
			<div style={ { fontSize: 14 } }>{ name }</div>
		</HStack>
	);

	return (
		<>
			{ Object.entries( otherColors ).map( ( [ key, value ] ) => (
				<Chip color={ value } name={ key } key={ key } />
			) ) }
			{ Object.entries( gray as NonNullable< typeof gray > ).map(
				( [ key, value ] ) => (
					<Chip
						color={ value }
						name={ `gray ${ key }` }
						key={ key }
					/>
				)
			) }
			{ !! contrastIssues.length && (
				<>
					<h2>Contrast issues</h2>
					<ul>
						{ contrastIssues.map( ( [ key, error ] ) => (
							<li key={ key }>{ error }</li>
						) ) }
					</ul>
				</>
			) }
		</>
	);
};

ThemeProvider

design-system-theme-theme-provider · ../packages/theme/src/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 5 prop types
Component: ../packages/theme/src/theme-provider.tsx::ThemeProvider
Props:
/**
 * The children to render.
 */
children?: ReactNode

/**
 * The set of color options to apply to the theme.
 */
color?: {
	/**
	 * The primary seed color to use for the theme.
	 *
	 * By default, it inherits from parent `ThemeProvider`,
	 * and fallbacks to statically built CSS.
	 */
	primary?: string;
	/**
	 * The background seed color to use for the theme.
	 *
	 * By default, it inherits from parent `ThemeProvider`,
	 * and fallbacks to statically built CSS.
	 */
	bg?: string;
} = {}

/**
 * The set of cursor options to apply to the theme.
 */
cursor?: {
	/**
	 * The cursor style for interactive controls that are not links
	 * (e.g. buttons, checkboxes, and toggles).
	 *
	 * By default, it inherits from the parent `ThemeProvider`,
	 * and falls back to the prebuilt default (`default`).
	 */
	control?: 'default' | 'pointer';
}

/**
 * The density of the theme. If left unspecified, the theme inherits from
 * the density of the closest `ThemeProvider`, or uses the default density
 * if there is no inherited density.
 * 
 * @default undefined
 */
density?: undefined | 'default' | 'compact' | 'comfortable'

/**
 * When a ThemeProvider is the root provider, it will apply its theming
 * settings also to the root document element (e.g. the html element).
 * This is useful, for example, to make sure that the `html` element can
 * consume the right background color, or that overlays rendered inside a
 * portal can inherit the correct color scheme.
 * 
 * @default false
 */
isRoot?: boolean = false
Imports
import { ThemeProvider } from "@wordpress/theme";
Default story ok
const Default = () => <ThemeProvider isRoot><DSTokensList /></ThemeProvider>;
With Picker story ok
const WithPicker = () => {
    const id = useId();
    const [ primary, setPrimary ] = useState< undefined | string >();

    return (
        <ThemeProvider
            isRoot
            color={ {
                primary,
            } }>
            <div style={ { position: 'relative' } }>
                <div
                    style={ {
                        position: 'sticky',
                        top: 0,
                        right: 0,
                        backgroundColor:
                            'var(--wpds-color-bg-surface-neutral)',
                        color: 'var( --wpds-color-fg-content-neutral )',
                        padding: '0.5rem',
                        borderRadius: '0.5rem',
                        boxShadow: '0 0 0.5rem 0 rgba(0, 0, 0, 0.1)',
                    } }>
                    <div>
                        <input
                            type="color"
                            id={ id }
                            name="primary"
                            value={ primary }
                            onChange={ ( e ) =>
                                setPrimary( e.target.value )
                            } />
                        <label htmlFor={ id }>Pick the primary color</label>
                    </div>
                </div>
                <DSTokensList />
            </div>
        </ThemeProvider>
    );
};
Nesting And Inheriting story ok
const NestingAndInheriting = () => {
    return (
        <ThemeProvider>
            <NestingDebug
                bg="inherit (root)"
                primary="inherit (root)"
                density="inherit (root)"
            />
            <div style={ { paddingInlineStart: '1rem' } }>
                <ThemeProvider
                    color={ {
                        bg: '#1e1e1e',
                    } }
                    density="compact"
                >
                    <NestingDebug
                        bg="#1e1e1e"
                        primary="inherit (root)"
                        density="compact"
                    />
                    <div style={ { paddingInlineStart: '1rem' } }>
                        <ThemeProvider>
                            <NestingDebug
                                bg="inherit (#1e1e1e)"
                                primary="inherit (root)"
                                density="inherit (compact)"
                            />
                            <div style={ { paddingInlineStart: '1rem' } }>
                                <ThemeProvider
                                    color={ { primary: 'hotpink' } }
                                    density="default"
                                >
                                    <NestingDebug
                                        bg="inherit (#1e1e1e)"
                                        primary="hotpink"
                                        density="default"
                                    />
                                    <div
                                        style={ {
                                            paddingInlineStart: '1rem',
                                        } }
                                    >
                                        <ThemeProvider
                                            color={ { bg: '#f8f8f8' } }
                                        >
                                            <NestingDebug
                                                bg="#f8f8f8"
                                                primary="inherit (hotpink)"
                                                density="inherit (default)"
                                            />
                                        </ThemeProvider>
                                    </div>
                                </ThemeProvider>
                            </div>
                        </ThemeProvider>
                    </div>
                </ThemeProvider>
            </div>
        </ThemeProvider>
    );
};
Across Iframes story ok
const AcrossIframes = () => {
    return (
        <ThemeProvider isRoot>
            (<div style={ { color: 'var(--wpds-color-fg-content-neutral)' } }>Code is poetry.{ ' ' }
                <span
					style={ {
						display: 'inline-block',
						padding: 'var(--wpds-dimension-padding-sm)',
						borderRadius: '0.25rem',
						backgroundColor:
							'var(--wpds-color-bg-interactive-brand-strong)',
						color: 'var(--wpds-color-fg-interactive-brand-strong)',
					} }
				>
					primary
				</span>
            </div>)
            <IframeWithClonedTokenStyles>
                <div
                    style={ {
                        color: 'var(--wpds-color-fg-content-neutral)',
                    } }>In the iframe, but outside of `ThemeProvider`
                                        </div>
                <ThemeProvider
                    // Note: the isRoot prop is necessary to apply the DS tokens to any
                    // UI rendered outside of the ThemeProvider (including overlays, etc)
                    isRoot>
                    (<div style={ { color: 'var(--wpds-color-fg-content-neutral)' } }>Code is poetry.{ ' ' }
                        <span
                            style={ {
                                display: 'inline-block',
                                padding: 'var(--wpds-dimension-padding-sm)',
                                borderRadius: '0.25rem',
                                backgroundColor:
                                    'var(--wpds-color-bg-interactive-brand-strong)',
                                color: 'var(--wpds-color-fg-interactive-brand-strong)',
                            } }
                        >
                            primary
                        </span>
                    </div>)
                </ThemeProvider>
            </IframeWithClonedTokenStyles>
        </ThemeProvider>
    );
};

ThemeProvider

design-system-theme-theme-provider-example-application · ./stories/design-system/theme-example-application.story.tsx
Prop type error
No component file found for the "ThemeProvider" component.
  30 | ];
  31 |
> 32 | const meta: Meta< typeof ThemeProvider > = {
     | ^
  33 | 	title: 'Design System/Theme/Theme Provider/Example Application',
  34 | 	component: ThemeProvider,
  35 | 	parameters: {

./stories/design-system/theme-example-application.story.tsx:
import type { Meta, StoryObj } from '@storybook/react-vite';
import { useState } from '@wordpress/element';
import { privateApis as themeApis } from '@wordpress/theme';
import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis';
import {
	Badge,
	Button,
	Card,
	Link,
	Notice,
	Stack,
	Tabs,
	Text,
} from '@wordpress/ui';

const { unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules(
	'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.',
	'@wordpress/theme'
);

const { ThemeProvider } = unlock( themeApis );

const sidebarNavItems = [
	'Dashboard',
	'Posts',
	'Pages',
	'Comments',
	'Appearance',
	'Settings',
];

const meta: Meta< typeof ThemeProvider > = {
	title: 'Design System/Theme/Theme Provider/Example Application',
	component: ThemeProvider,
	parameters: {
		controls: { expanded: true },
		docs: { canvas: { sourceState: 'hidden' } },
	},
};
export default meta;

/**
 * A mock application page demonstrating how `ThemeProvider` affects multiple
 * `@wordpress/ui` components in concert. Use the inline controls to adjust
 * the `primary` seed color, `bg` seed color, and `density`, and observe how
 * every surface, text element, and interactive control adapts accordingly.
 */
export const ExampleApplication: StoryObj< typeof ThemeProvider > = {
	render: () => {
		const [ primary, setPrimary ] = useState< string | undefined >();
		const [ bg, setBg ] = useState< string | undefined >();
		const [ density, setDensity ] = useState<
			'default' | 'compact' | 'comfortable' | undefined
		>();

		return (
			<div>
				<div
					style={ {
						display: 'flex',
						alignItems: 'center',
						gap: '16px',
						padding: '12px 16px',
						marginBlockEnd: '16px',
						borderRadius: '8px',
						background: '#f0f0f0',
						fontSize: '13px',
						flexWrap: 'wrap',
					} }
				>
					{ /* eslint-disable jsx-a11y/label-has-associated-control */ }
					<label
						style={ {
							display: 'inline-flex',
							alignItems: 'center',
							gap: '6px',
						} }
					>
						Primary
						<input
							type="color"
							value={ primary ?? '#3858e9' }
							onChange={ ( e ) => setPrimary( e.target.value ) }
						/>
					</label>
					<label
						style={ {
							display: 'inline-flex',
							alignItems: 'center',
							gap: '6px',
						} }
					>
						Background
						<input
							type="color"
							value={ bg ?? '#ffffff' }
							onChange={ ( e ) => setBg( e.target.value ) }
						/>
					</label>
					<label
						style={ {
							display: 'inline-flex',
							alignItems: 'center',
							gap: '6px',
						} }
					>
						Density
						<select
							value={ density ?? '' }
							onChange={ ( e ) =>
								setDensity(
									( e.target.value || undefined ) as
										| 'default'
										| 'compact'
										| 'comfortable'
										| undefined
								)
							}
						>
							<option value="">Default</option>
							<option value="compact">Compact</option>
							<option value="comfortable">Comfortable</option>
						</select>
					</label>
					{ /* eslint-enable jsx-a11y/label-has-associated-control */ }
				</div>
				<ThemeProvider
					color={ { primary, bg } }
					density={ density }
					isRoot
				>
					<div
						style={ {
							display: 'grid',
							gridTemplateColumns: '200px 1fr',
							minHeight: '500px',
							color: 'var(--wpds-color-fg-content-neutral)',
						} }
					>
						{ /* Sidebar */ }
						<div
							style={ {
								backgroundColor:
									'var(--wpds-color-bg-surface-neutral-weak)',
								padding:
									'var(--wpds-dimension-padding-xl) var(--wpds-dimension-padding-lg)',
							} }
						>
							<Text
								variant="heading-sm"
								render={ <h2 /> }
								style={ {
									marginBlockEnd:
										'var(--wpds-dimension-gap-xl)',
								} }
							>
								My App
							</Text>
							<nav>
								<Stack
									direction="column"
									gap="xs"
									render={ <ul /> }
									style={ {
										listStyle: 'none',
										margin: 0,
										padding: 0,
									} }
								>
									{ sidebarNavItems.map( ( item ) => (
										<li key={ item }>
											<Text variant="body-md">
												{ item }
											</Text>
										</li>
									) ) }
								</Stack>
							</nav>
						</div>

						{ /* Page content (header + content area) */ }
						<div
							style={ {
								backgroundColor:
									'var(--wpds-color-bg-surface-neutral-weak)',
								padding: 'var(--wpds-dimension-padding-lg)',
							} }
						>
							<div
								style={ {
									display: 'flex',
									flexDirection: 'column',
									borderRadius:
										'var(--wpds-border-radius-lg)',
									border: '1px solid var(--wpds-color-stroke-surface-neutral-weak)',
									overflow: 'hidden',
									height: '100%',
								} }
							>
								{ /* Header */ }
								<div
									style={ {
										backgroundColor:
											'var(--wpds-color-bg-surface-neutral-strong)',
										padding:
											'var(--wpds-dimension-padding-xl)',
										display: 'flex',
										alignItems: 'center',
										justifyContent: 'space-between',
										gap: 'var(--wpds-dimension-gap-lg)',
										borderBlockEnd:
											'1px solid var(--wpds-color-stroke-surface-neutral-weak)',
									} }
								>
									<div
										style={ {
											display: 'flex',
											alignItems: 'center',
											gap: 'var(--wpds-dimension-gap-md)',
										} }
									>
										<Text
											variant="heading-lg"
											render={ <h1 /> }
											style={ {
												margin: 0,
											} }
										>
											Settings
										</Text>
										<Badge intent="informational">
											Beta
										</Badge>
									</div>
									<Button
										variant="solid"
										tone="brand"
										size="compact"
									>
										Save changes
									</Button>
								</div>

								{ /* Content area */ }
								<div
									style={ {
										backgroundColor:
											'var(--wpds-color-bg-surface-neutral)',
										padding:
											'var(--wpds-dimension-padding-xl)',
										flexGrow: 1,
									} }
								>
									<Stack
										direction="column"
										gap="xl"
										style={ {
											maxWidth: '640px',
											marginInline: 'auto',
										} }
									>
										<Notice.Root intent="info">
											<Notice.Title>
												Welcome to your new site
											</Notice.Title>
											<Notice.Description>
												Complete the steps below to
												finish setting up.
											</Notice.Description>
										</Notice.Root>

										{ /* Card 1: General */ }
										<Card.Root>
											<Card.Header>
												<Card.Title>General</Card.Title>
											</Card.Header>
											<Card.Content>
												<Stack
													direction="column"
													gap="md"
												>
													<Text>
														Configure the basic
														settings for your site.
														You can update your{ ' ' }
														<Link href="#">
															site title
														</Link>
														, tagline, and{ ' ' }
														<Link href="#">
															admin email address
														</Link>{ ' ' }
														at any time.
													</Text>
													<Text>
														For more advanced
														options, visit the{ ' ' }
														<Link href="#">
															developer
															documentation
														</Link>
														.
													</Text>
												</Stack>
											</Card.Content>
										</Card.Root>

										{ /* Card 2: Display */ }
										<Card.Root>
											<Card.Header>
												<Card.Title>Display</Card.Title>
											</Card.Header>
											<Card.Content>
												<Tabs.Root defaultValue="appearance">
													<Tabs.List variant="minimal">
														<Tabs.Tab value="appearance">
															Appearance
														</Tabs.Tab>
														<Tabs.Tab value="layout">
															Layout
														</Tabs.Tab>
														<Tabs.Tab value="accessibility">
															Accessibility
														</Tabs.Tab>
													</Tabs.List>
													<Tabs.Panel value="appearance">
														<Text
															style={ {
																paddingBlockStart:
																	'var(--wpds-dimension-padding-lg)',
															} }
														>
															Control how your
															site looks to
															visitors. Adjust{ ' ' }
															<Link href="#">
																typography
															</Link>
															,{ ' ' }
															<Link href="#">
																colors
															</Link>
															, and spacing to
															match your brand.
														</Text>
													</Tabs.Panel>
													<Tabs.Panel value="layout">
														<Text
															style={ {
																paddingBlockStart:
																	'var(--wpds-dimension-padding-lg)',
															} }
														>
															Choose a layout
															structure for your
															pages. Options
															include full-width,
															boxed, and{ ' ' }
															<Link href="#">
																custom layouts
															</Link>
															.
														</Text>
													</Tabs.Panel>
													<Tabs.Panel value="accessibility">
														<Text
															style={ {
																paddingBlockStart:
																	'var(--wpds-dimension-padding-lg)',
															} }
														>
															Review your
															site&apos;s{ ' ' }
															<Link href="#">
																accessibility
																settings
															</Link>{ ' ' }
															to ensure it meets
															WCAG guidelines.
														</Text>
													</Tabs.Panel>
												</Tabs.Root>
											</Card.Content>
										</Card.Root>
									</Stack>
								</div>
							</div>
						</div>
					</div>
				</ThemeProvider>
			</div>
		);
	},
	parameters: {
		controls: { disable: true },
	},
};
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Badge, Button, Card, Link, Notice, Stack, Tabs, Text } from "@wordpress/ui";
Example Application story ok
A mock application page demonstrating how `ThemeProvider` affects multiple `@wordpress/ui` components in concert. Use the inline controls to adjust the `primary` seed color, `bg` seed color, and `density`, and observe how every surface, text element, and interactive control adapts accordingly.
const ExampleApplication = () => {
    const [ primary, setPrimary ] = useState< string | undefined >();
    const [ bg, setBg ] = useState< string | undefined >();
    const [ density, setDensity ] = useState<
        'default' | 'compact' | 'comfortable' | undefined
    >();

    return (
        <div>
            <div
                style={ {
                    display: 'flex',
                    alignItems: 'center',
                    gap: '16px',
                    padding: '12px 16px',
                    marginBlockEnd: '16px',
                    borderRadius: '8px',
                    background: '#f0f0f0',
                    fontSize: '13px',
                    flexWrap: 'wrap',
                } }
            >
                { /* eslint-disable jsx-a11y/label-has-associated-control */ }
                <label
                    style={ {
                        display: 'inline-flex',
                        alignItems: 'center',
                        gap: '6px',
                    } }
                >
                    Primary
                    <input
                        type="color"
                        value={ primary ?? '#3858e9' }
                        onChange={ ( e ) => setPrimary( e.target.value ) }
                    />
                </label>
                <label
                    style={ {
                        display: 'inline-flex',
                        alignItems: 'center',
                        gap: '6px',
                    } }
                >
                    Background
                    <input
                        type="color"
                        value={ bg ?? '#ffffff' }
                        onChange={ ( e ) => setBg( e.target.value ) }
                    />
                </label>
                <label
                    style={ {
                        display: 'inline-flex',
                        alignItems: 'center',
                        gap: '6px',
                    } }
                >
                    Density
                    <select
                        value={ density ?? '' }
                        onChange={ ( e ) =>
                            setDensity(
                                ( e.target.value || undefined ) as
                                    | 'default'
                                    | 'compact'
                                    | 'comfortable'
                                    | undefined
                            )
                        }
                    >
                        <option value="">Default</option>
                        <option value="compact">Compact</option>
                        <option value="comfortable">Comfortable</option>
                    </select>
                </label>
                { /* eslint-enable jsx-a11y/label-has-associated-control */ }
            </div>
            <ThemeProvider
                color={ { primary, bg } }
                density={ density }
                isRoot
            >
                <div
                    style={ {
                        display: 'grid',
                        gridTemplateColumns: '200px 1fr',
                        minHeight: '500px',
                        color: 'var(--wpds-color-fg-content-neutral)',
                    } }
                >
                    { /* Sidebar */ }
                    <div
                        style={ {
                            backgroundColor:
                                'var(--wpds-color-bg-surface-neutral-weak)',
                            padding:
                                'var(--wpds-dimension-padding-xl) var(--wpds-dimension-padding-lg)',
                        } }
                    >
                        <Text
                            variant="heading-sm"
                            render={ <h2 /> }
                            style={ {
                                marginBlockEnd:
                                    'var(--wpds-dimension-gap-xl)',
                            } }
                        >
                            My App
                        </Text>
                        <nav>
                            <Stack
                                direction="column"
                                gap="xs"
                                render={ <ul /> }
                                style={ {
                                    listStyle: 'none',
                                    margin: 0,
                                    padding: 0,
                                } }
                            >
                                { sidebarNavItems.map( ( item ) => (
                                    <li key={ item }>
                                        <Text variant="body-md">
                                            { item }
                                        </Text>
                                    </li>
                                ) ) }
                            </Stack>
                        </nav>
                    </div>

                    { /* Page content (header + content area) */ }
                    <div
                        style={ {
                            backgroundColor:
                                'var(--wpds-color-bg-surface-neutral-weak)',
                            padding: 'var(--wpds-dimension-padding-lg)',
                        } }
                    >
                        <div
                            style={ {
                                display: 'flex',
                                flexDirection: 'column',
                                borderRadius:
                                    'var(--wpds-border-radius-lg)',
                                border: '1px solid var(--wpds-color-stroke-surface-neutral-weak)',
                                overflow: 'hidden',
                                height: '100%',
                            } }
                        >
                            { /* Header */ }
                            <div
                                style={ {
                                    backgroundColor:
                                        'var(--wpds-color-bg-surface-neutral-strong)',
                                    padding:
                                        'var(--wpds-dimension-padding-xl)',
                                    display: 'flex',
                                    alignItems: 'center',
                                    justifyContent: 'space-between',
                                    gap: 'var(--wpds-dimension-gap-lg)',
                                    borderBlockEnd:
                                        '1px solid var(--wpds-color-stroke-surface-neutral-weak)',
                                } }
                            >
                                <div
                                    style={ {
                                        display: 'flex',
                                        alignItems: 'center',
                                        gap: 'var(--wpds-dimension-gap-md)',
                                    } }
                                >
                                    <Text
                                        variant="heading-lg"
                                        render={ <h1 /> }
                                        style={ {
                                            margin: 0,
                                        } }
                                    >
                                        Settings
                                    </Text>
                                    <Badge intent="informational">
                                        Beta
                                    </Badge>
                                </div>
                                <Button
                                    variant="solid"
                                    tone="brand"
                                    size="compact"
                                >
                                    Save changes
                                </Button>
                            </div>

                            { /* Content area */ }
                            <div
                                style={ {
                                    backgroundColor:
                                        'var(--wpds-color-bg-surface-neutral)',
                                    padding:
                                        'var(--wpds-dimension-padding-xl)',
                                    flexGrow: 1,
                                } }
                            >
                                <Stack
                                    direction="column"
                                    gap="xl"
                                    style={ {
                                        maxWidth: '640px',
                                        marginInline: 'auto',
                                    } }
                                >
                                    <Notice.Root intent="info">
                                        <Notice.Title>
                                            Welcome to your new site
                                        </Notice.Title>
                                        <Notice.Description>
                                            Complete the steps below to
                                            finish setting up.
                                        </Notice.Description>
                                    </Notice.Root>

                                    { /* Card 1: General */ }
                                    <Card.Root>
                                        <Card.Header>
                                            <Card.Title>General</Card.Title>
                                        </Card.Header>
                                        <Card.Content>
                                            <Stack
                                                direction="column"
                                                gap="md"
                                            >
                                                <Text>
                                                    Configure the basic
                                                    settings for your site.
                                                    You can update your{ ' ' }
                                                    <Link href="#">
                                                        site title
                                                    </Link>
                                                    , tagline, and{ ' ' }
                                                    <Link href="#">
                                                        admin email address
                                                    </Link>{ ' ' }
                                                    at any time.
                                                </Text>
                                                <Text>
                                                    For more advanced
                                                    options, visit the{ ' ' }
                                                    <Link href="#">
                                                        developer
                                                        documentation
                                                    </Link>
                                                    .
                                                </Text>
                                            </Stack>
                                        </Card.Content>
                                    </Card.Root>

                                    { /* Card 2: Display */ }
                                    <Card.Root>
                                        <Card.Header>
                                            <Card.Title>Display</Card.Title>
                                        </Card.Header>
                                        <Card.Content>
                                            <Tabs.Root defaultValue="appearance">
                                                <Tabs.List variant="minimal">
                                                    <Tabs.Tab value="appearance">
                                                        Appearance
                                                    </Tabs.Tab>
                                                    <Tabs.Tab value="layout">
                                                        Layout
                                                    </Tabs.Tab>
                                                    <Tabs.Tab value="accessibility">
                                                        Accessibility
                                                    </Tabs.Tab>
                                                </Tabs.List>
                                                <Tabs.Panel value="appearance">
                                                    <Text
                                                        style={ {
                                                            paddingBlockStart:
                                                                'var(--wpds-dimension-padding-lg)',
                                                        } }
                                                    >
                                                        Control how your
                                                        site looks to
                                                        visitors. Adjust{ ' ' }
                                                        <Link href="#">
                                                            typography
                                                        </Link>
                                                        ,{ ' ' }
                                                        <Link href="#">
                                                            colors
                                                        </Link>
                                                        , and spacing to
                                                        match your brand.
                                                    </Text>
                                                </Tabs.Panel>
                                                <Tabs.Panel value="layout">
                                                    <Text
                                                        style={ {
                                                            paddingBlockStart:
                                                                'var(--wpds-dimension-padding-lg)',
                                                        } }
                                                    >
                                                        Choose a layout
                                                        structure for your
                                                        pages. Options
                                                        include full-width,
                                                        boxed, and{ ' ' }
                                                        <Link href="#">
                                                            custom layouts
                                                        </Link>
                                                        .
                                                    </Text>
                                                </Tabs.Panel>
                                                <Tabs.Panel value="accessibility">
                                                    <Text
                                                        style={ {
                                                            paddingBlockStart:
                                                                'var(--wpds-dimension-padding-lg)',
                                                        } }
                                                    >
                                                        Review your
                                                        site&apos;s{ ' ' }
                                                        <Link href="#">
                                                            accessibility
                                                            settings
                                                        </Link>{ ' ' }
                                                        to ensure it meets
                                                        WCAG guidelines.
                                                    </Text>
                                                </Tabs.Panel>
                                            </Tabs.Root>
                                        </Card.Content>
                                    </Card.Root>
                                </Stack>
                            </div>
                        </div>
                    </div>
                </div>
            </ThemeProvider>
        </div>
    );
};

TimePicker

components-timepicker · ../packages/components/src/date-time/stories/time.story.tsx
TimePicker is a React component that renders a clock for time selection. ```jsx import { TimePicker } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyTimePicker = () => { const [ time, setTime ] = useState( new Date() ); return ( <TimePicker currentTime={ date } onChange={ ( newTime ) => setTime( newTime ) } is12Hour /> ); }; ```
Prop types 5 prop types
Component: ../packages/components/src/date-time/time/index.tsx::TimePicker
Props:
/**
 * The initial current time the time picker should render.
 */
currentTime?: Date | string | number | null

/**
 * The order of day, month, and year. This prop overrides the time format
 * determined by `is12Hour` prop.
 * 
 * @default 'dmy'
 */
dateOrder?: 'dmy' | 'mdy' | 'ymd'

/**
 * If true, the label will only be visible to screen readers.
 * 
 * @default false
 */
hideLabelFromVision?: boolean = false

/**
 * Whether we use a 12-hour clock. With a 12-hour clock, an AM/PM widget is
 * displayed and the time format is assumed to be `MM-DD-YYYY` (as opposed
 * to the default format `DD-MM-YYYY`).
 */
is12Hour?: boolean

/**
 * The function called when a new time has been selected. It is passed the
 * time as an argument.
 */
onChange?: ( time: string ) => void
Imports
import { TimePicker } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ time, setTime ] = useState( currentTime );
    useEffect( () => {
		setTime( currentTime );
	}, [ currentTime ] );

    return (
        <TimePicker
            currentTime={ time }
            onChange={ ( newTime ) => {
				setTime( newTime );
				onChange?.( newTime );
			} } />
    );
};
Time Input story ok
The time input can be used in isolation as `<TimePicker.TimeInput />`. In this case, the `value` will be passed as an object in 24-hour format (`{ hours: number, minutes: number }`).
const TimeInput = () => {
    return <TimePicker.TimeInput label="Time" />;
};

Tip

components-tip · ../packages/components/src/tip/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 1 prop type
Component: ../packages/components/src/tip/index.tsx::Tip
Props:
/**
 * Children to render in the tip.
 */
children: ReactNode
Imports
import { Tip } from "@wordpress/components";
Default story ok
const Default = () => {
    return <Tip>An example tip</Tip>;
};

ToggleControl

components-togglecontrol · ../packages/components/src/toggle-control/stories/index.story.tsx
ToggleControl is used to generate a toggle user interface. ```jsx import { ToggleControl } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyToggleControl = () => { const [ value, setValue ] = useState( false ); return ( <ToggleControl label="Fixed Background" checked={ value } onChange={ () => setValue( ( state ) => ! state ) } /> ); }; ```
Imports
import { ToggleControl } from "@wordpress/components";
Default story ok
const Default = ( {
	onChange,
	...props
} ) => {
	const [ checked, setChecked ] = useState( true );
	return (
		<ToggleControl
			{ ...props }
			checked={ checked }
			onChange={ ( ...changeArgs ) => {
				setChecked( ...changeArgs );
				onChange( ...changeArgs );
			} }
		/>
	);
};
With Help Text story ok
const WithHelpText = ( {
	onChange,
	...props
} ) => {
	const [ checked, setChecked ] = useState( true );
	return (
		<ToggleControl
			{ ...props }
			checked={ checked }
			onChange={ ( ...changeArgs ) => {
				setChecked( ...changeArgs );
				onChange( ...changeArgs );
			} }
		/>
	);
};

ToggleGroupControl

components-togglegroupcontrol · ../packages/components/src/toggle-group-control/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { ToggleGroupControl, ToggleGroupControlOption, ToggleGroupControlOptionIcon } from "@wordpress/components";
Default story ok
const Default = ( {
	onChange,
	...props
} ) => {
	const [ value, setValue ] =
		useState< ToggleGroupControlProps[ 'value' ] >();

	return (
		<ToggleGroupControl
			__next40pxDefaultSize
			{ ...props }
			onChange={ ( ...changeArgs ) => {
				setValue( ...changeArgs );
				onChange?.( ...changeArgs );
			} }
			value={ value }
		/>
	);
};
With Tooltip story ok
A tooltip can be shown for each option by enabling the `showTooltip` prop. The `aria-label` will be used in the tooltip if provided. Otherwise, the `label` will be used.
const WithTooltip = ( {
	onChange,
	...props
} ) => {
	const [ value, setValue ] =
		useState< ToggleGroupControlProps[ 'value' ] >();

	return (
		<ToggleGroupControl
			__next40pxDefaultSize
			{ ...props }
			onChange={ ( ...changeArgs ) => {
				setValue( ...changeArgs );
				onChange?.( ...changeArgs );
			} }
			value={ value }
		/>
	);
};
With Icons story ok
The `ToggleGroupControlOptionIcon` component can be used for icon options. A `label` is required on each option for accessibility, which will be shown in a tooltip.
const WithIcons = ( {
	onChange,
	...props
} ) => {
	const [ value, setValue ] =
		useState< ToggleGroupControlProps[ 'value' ] >();

	return (
		<ToggleGroupControl
			__next40pxDefaultSize
			{ ...props }
			onChange={ ( ...changeArgs ) => {
				setValue( ...changeArgs );
				onChange?.( ...changeArgs );
			} }
			value={ value }
		/>
	);
};
Deselectable story ok
When the `isDeselectable` prop is true, the option can be deselected by clicking on it again.
const Deselectable = ( {
	onChange,
	...props
} ) => {
	const [ value, setValue ] =
		useState< ToggleGroupControlProps[ 'value' ] >();

	return (
		<ToggleGroupControl
			__next40pxDefaultSize
			{ ...props }
			onChange={ ( ...changeArgs ) => {
				setValue( ...changeArgs );
				onChange?.( ...changeArgs );
			} }
			value={ value }
		/>
	);
};

Toolbar

components-toolbar · ../packages/components/src/toolbar/stories/index.story.tsx
Renders a toolbar. To add controls, simply pass `ToolbarButton` components as children. ```jsx import { Toolbar, ToolbarButton } from '@wordpress/components'; import { formatBold, formatItalic, link } from '@wordpress/icons'; function MyToolbar() { return ( <Toolbar label="Options"> <ToolbarButton icon={ formatBold } label="Bold" /> <ToolbarButton icon={ formatItalic } label="Italic" /> <ToolbarButton icon={ link } label="Link" /> </Toolbar> ); } ```
Imports
import {
    DropdownMenu,
    Toolbar,
    ToolbarButton,
    ToolbarDropdownMenu,
    ToolbarGroup,
    ToolbarItem,
} from "@wordpress/components";
import { Path, SVG } from "@wordpress/primitives";
Default story ok
const Default = ( props ) => (
	<div style={ { height: 280 } }>
		<Toolbar { ...props } />
	</div>
);
Without Group story ok
const WithoutGroup = ( props ) => (
	<div style={ { height: 280 } }>
		<Toolbar { ...props } />
	</div>
);
Unstyled story ok
Set the variant to `unstyled` to remove default border styles. Otherwise, leave it as `undefined` for default styles.
const Unstyled = ( props ) => (
	<div style={ { height: 280 } }>
		<Toolbar { ...props } />
	</div>
);

ToolsPanel

components-toolspanel · ../packages/components/src/tools-panel/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import {
    Panel,
    Provider as SlotFillProvider,
    ToggleGroupControl,
    ToggleGroupControlOption,
    ToolsPanel,
    ToolsPanelItem,
    UnitControl,
} from "@wordpress/components";
Default story ok
const Default = ( {
	resetAll: resetAllProp,
	...props
} ) => {
	const [ height, setHeight ] = useState< string | undefined >();
	const [ minHeight, setMinHeight ] = useState< string | undefined >();
	const [ width, setWidth ] = useState< string | undefined >();
	const [ scale, setScale ] = useState< number | string | undefined >();

	const resetAll: typeof resetAllProp = ( filters ) => {
		setHeight( undefined );
		setWidth( undefined );
		setMinHeight( undefined );
		setScale( undefined );
		resetAllProp( filters );
	};

	return (
		<PanelWrapperView>
			<Panel>
				<ToolsPanel { ...props } resetAll={ resetAll }>
					<SingleColumnItem
						hasValue={ () => !! width }
						label="Width"
						onDeselect={ () => setWidth( undefined ) }
						isShownByDefault
					>
						<UnitControl
							__next40pxDefaultSize
							label="Width"
							value={ width }
							onChange={ ( next ) => setWidth( next ) }
						/>
					</SingleColumnItem>
					<SingleColumnItem
						hasValue={ () => !! height }
						label="Height"
						onDeselect={ () => setHeight( undefined ) }
						isShownByDefault
					>
						<UnitControl
							__next40pxDefaultSize
							label="Height"
							value={ height }
							onChange={ ( next ) => setHeight( next ) }
						/>
					</SingleColumnItem>
					<ToolsPanelItem
						hasValue={ () => !! minHeight }
						label="Minimum height"
						onDeselect={ () => setMinHeight( undefined ) }
						isShownByDefault
					>
						<UnitControl
							__next40pxDefaultSize
							label="Minimum height"
							value={ minHeight }
							onChange={ ( next ) => setMinHeight( next ) }
						/>
					</ToolsPanelItem>
					<ToolsPanelItem
						hasValue={ () => !! scale }
						label="Scale"
						onDeselect={ () => setScale( undefined ) }
					>
						<ToggleGroupControl
							__next40pxDefaultSize
							label="Scale"
							value={ scale }
							onChange={ ( next ) => setScale( next ) }
							isBlock
						>
							<ToggleGroupControlOption
								value="cover"
								label="Cover"
							/>
							<ToggleGroupControlOption
								value="contain"
								label="Contain"
							/>
							<ToggleGroupControlOption
								value="fill"
								label="Fill"
							/>
						</ToggleGroupControl>
					</ToolsPanelItem>
				</ToolsPanel>
			</Panel>
		</PanelWrapperView>
	);
};
With Non Tools Panel Items story ok
const WithNonToolsPanelItems = ( {
	resetAll: resetAllProp,
	...props
} ) => {
	const [ height, setHeight ] = useState< string | undefined >();
	const [ width, setWidth ] = useState< string | undefined >();

	const resetAll: typeof resetAllProp = ( filters ) => {
		setHeight( undefined );
		setWidth( undefined );
		resetAllProp( filters );
	};

	return (
		<PanelWrapperView>
			<Panel>
				<ToolsPanel { ...props } resetAll={ resetAll }>
					<IntroText>
						This text illustrates not all items must be wrapped in a
						ToolsPanelItem and represented in the panel menu.
					</IntroText>
					<SingleColumnItem
						hasValue={ () => !! width }
						label="Width"
						onDeselect={ () => setWidth( undefined ) }
						isShownByDefault
					>
						<UnitControl
							__next40pxDefaultSize
							label="Width"
							value={ width }
							onChange={ ( next ) => setWidth( next ) }
						/>
					</SingleColumnItem>
					<SingleColumnItem
						hasValue={ () => !! height }
						label="Height"
						onDeselect={ () => setHeight( undefined ) }
						isShownByDefault
					>
						<UnitControl
							__next40pxDefaultSize
							label="Height"
							value={ height }
							onChange={ ( next ) => setHeight( next ) }
						/>
					</SingleColumnItem>
				</ToolsPanel>
			</Panel>
		</PanelWrapperView>
	);
};
With Optional Items Plus Icon story ok
const WithOptionalItemsPlusIcon = ( {
	resetAll: resetAllProp,
	...props
} ) => {
	const [
		isFirstToolsPanelItemShownByDefault,
		setIsFirstToolsPanelItemShownByDefault,
	] = useState( false );
	const [ height, setHeight ] = useState< string | undefined >();
	const [ width, setWidth ] = useState< string | undefined >();
	const [ minWidth, setMinWidth ] = useState< string | undefined >();

	const resetAll: typeof resetAllProp = ( filters ) => {
		setHeight( undefined );
		setWidth( undefined );
		setMinWidth( undefined );
		resetAllProp( filters );
	};

	return (
		<>
			<PanelWrapperView>
				<Panel>
					<ToolsPanel
						{ ...props }
						resetAll={ resetAll }
						// `key` property here is used as a hack to force `ToolsPanel` to re-render
						// See https://github.com/WordPress/gutenberg/pull/38262/files#r793422991
						key={
							isFirstToolsPanelItemShownByDefault
								? 'true'
								: 'false'
						}
					>
						<SingleColumnItem
							hasValue={ () => !! minWidth }
							label="Minimum width"
							onDeselect={ () => setMinWidth( undefined ) }
							isShownByDefault={
								isFirstToolsPanelItemShownByDefault
							}
						>
							<UnitControl
								__next40pxDefaultSize
								label="Minimum width"
								value={ minWidth }
								onChange={ ( next ) => setMinWidth( next ) }
							/>
						</SingleColumnItem>
						<SingleColumnItem
							hasValue={ () => !! width }
							label="Width"
							onDeselect={ () => setWidth( undefined ) }
							isShownByDefault={ false }
						>
							<UnitControl
								__next40pxDefaultSize
								label="Width"
								value={ width }
								onChange={ ( next ) => setWidth( next ) }
							/>
						</SingleColumnItem>
						<SingleColumnItem
							hasValue={ () => !! height }
							label="Height"
							onDeselect={ () => setHeight( undefined ) }
							isShownByDefault={ false }
						>
							<UnitControl
								__next40pxDefaultSize
								label="Height"
								value={ height }
								onChange={ ( next ) => setHeight( next ) }
							/>
						</SingleColumnItem>
					</ToolsPanel>
				</Panel>
			</PanelWrapperView>

			<button
				onClick={ () =>
					setIsFirstToolsPanelItemShownByDefault(
						! isFirstToolsPanelItemShownByDefault
					)
				}
				aria-pressed={
					isFirstToolsPanelItemShownByDefault ? 'true' : 'false'
				}
				style={ {
					marginTop: '2rem',
				} }
			>
				{ isFirstToolsPanelItemShownByDefault
					? 'Make first PanelItem hidden by default'
					: 'Make first PanelItem shown by default' }
			</button>
		</>
	);
};
With Slot Fill Items story ok
const WithSlotFillItems = ( {
	resetAll: resetAllProp,
	panelId,
	...props
} ) => {
	const [ attributes, setAttributes ] = useState< {
		width?: string;
		height?: string;
	} >( {} );
	const { width, height } = attributes;

	const resetAll: typeof resetAllProp = ( resetFilters = [] ) => {
		let newAttributes: typeof attributes = {};

		resetFilters.forEach( ( resetFilter ) => {
			newAttributes = {
				...newAttributes,
				...resetFilter( newAttributes ),
			};
		} );

		setAttributes( newAttributes );
		resetAllProp( resetFilters );
	};

	const updateAttribute = ( name: string, value?: any ) => {
		setAttributes( {
			...attributes,
			[ name ]: value,
		} );
	};

	return (
		<SlotFillProvider>
			<ToolsPanelItems>
				<SingleColumnItem
					hasValue={ () => !! width }
					label="Injected Width"
					onDeselect={ () => updateAttribute( 'width', undefined ) }
					resetAllFilter={ () => ( { width: undefined } ) }
					panelId={ panelId }
				>
					<UnitControl
						__next40pxDefaultSize
						label="Injected Width"
						value={ width }
						onChange={ ( next ) =>
							updateAttribute( 'width', next )
						}
					/>
				</SingleColumnItem>
				<SingleColumnItem
					hasValue={ () => !! height }
					label="Injected Height"
					onDeselect={ () => updateAttribute( 'height', undefined ) }
					resetAllFilter={ () => ( { height: undefined } ) }
					panelId={ panelId }
				>
					<UnitControl
						__next40pxDefaultSize
						label="Injected Height"
						value={ height }
						onChange={ ( next ) =>
							updateAttribute( 'height', next )
						}
					/>
				</SingleColumnItem>
				<ToolsPanelItem
					hasValue={ () => true }
					label="Item for alternate panel"
					onDeselect={ () => undefined }
					resetAllFilter={ () => undefined }
					panelId="intended-for-another-panel-via-shared-slot"
				>
					<p>
						This panel item will not be displayed in the demo as its
						panelId does not match the panel being rendered.
					</p>
				</ToolsPanelItem>
			</ToolsPanelItems>
			<PanelWrapperView>
				<Panel>
					<ToolsPanel
						{ ...props }
						resetAll={ resetAll }
						panelId={ panelId }
					>
						<Slot />
					</ToolsPanel>
				</Panel>
			</PanelWrapperView>
		</SlotFillProvider>
	);
};
With Conditional Default Control story ok
const WithConditionalDefaultControl = ( {
	resetAll: resetAllProp,
	panelId,
	...props
} ) => {
	const [ attributes, setAttributes ] = useState< {
		height?: string;
		scale?: number | string;
	} >( {} );
	const { height, scale } = attributes;

	const resetAll: typeof resetAllProp = ( resetFilters = [] ) => {
		let newAttributes: typeof attributes = {};

		resetFilters.forEach( ( resetFilter ) => {
			newAttributes = {
				...newAttributes,
				...resetFilter( newAttributes ),
			};
		} );

		setAttributes( newAttributes );

		resetAllProp( resetFilters );
	};

	const updateAttribute = ( name: string, value?: any ) => {
		setAttributes( {
			...attributes,
			[ name ]: value,
		} );
	};

	return (
		<SlotFillProvider>
			<ToolsPanelItems>
				<SingleColumnItem
					hasValue={ () => !! height }
					label="Injected Height"
					onDeselect={ () => updateAttribute( 'height', undefined ) }
					resetAllFilter={ () => ( { height: undefined } ) }
					panelId={ panelId }
					isShownByDefault
				>
					<UnitControl
						__next40pxDefaultSize
						label="Injected Height"
						value={ height }
						onChange={ ( next ) =>
							updateAttribute( 'height', next )
						}
					/>
				</SingleColumnItem>
				<ToolsPanelItem
					hasValue={ () => !! scale }
					label="Scale"
					onDeselect={ () => updateAttribute( 'scale', undefined ) }
					resetAllFilter={ () => ( { scale: undefined } ) }
					panelId={ panelId }
					isShownByDefault={ !! height }
				>
					<ToggleGroupControl
						__next40pxDefaultSize
						label="Scale"
						value={ scale }
						onChange={ ( next ) =>
							updateAttribute( 'scale', next )
						}
						isBlock
					>
						<ToggleGroupControlOption value="cover" label="Cover" />
						<ToggleGroupControlOption
							value="contain"
							label="Contain"
						/>
						<ToggleGroupControlOption value="fill" label="Fill" />
					</ToggleGroupControl>
				</ToolsPanelItem>
			</ToolsPanelItems>
			<PanelWrapperView>
				<Panel>
					<ToolsPanel
						{ ...props }
						resetAll={ resetAll }
						panelId={ panelId }
					>
						<Slot />
					</ToolsPanel>
				</Panel>
			</PanelWrapperView>
		</SlotFillProvider>
	);
};
With Conditionally Rendered Control story ok
const WithConditionallyRenderedControl = ( { resetAll: resetAllProp, panelId, ...props } ) => {
	const [ attributes, setAttributes ] = useState< {
		height?: string;
		scale?: number | string;
	} >( {} );
	const { height, scale } = attributes;

	const resetAll: typeof resetAllProp = ( resetFilters = [] ) => {
		let newAttributes: typeof attributes = {};

		resetFilters.forEach( ( resetFilter ) => {
			newAttributes = {
				...newAttributes,
				...resetFilter( newAttributes ),
			};
		} );

		setAttributes( newAttributes );

		resetAllProp( resetFilters );
	};

	const updateAttribute = ( name: string, value?: any ) => {
		setAttributes( {
			...attributes,
			[ name ]: value,
		} );
	};

	return (
		<SlotFillProvider>
			<ToolsPanelItems>
				<SingleColumnItem
					hasValue={ () => !! height }
					label="Injected Height"
					onDeselect={ () => {
						updateAttribute( 'scale', undefined );
						updateAttribute( 'height', undefined );
					} }
					resetAllFilter={ () => ( { height: undefined } ) }
					panelId={ panelId }
					isShownByDefault
				>
					<UnitControl
						__next40pxDefaultSize
						label="Injected Height"
						value={ height }
						onChange={ ( next ) =>
							updateAttribute( 'height', next )
						}
					/>
				</SingleColumnItem>
				{ !! height && (
					<ToolsPanelItem
						hasValue={ () => !! scale }
						label="Scale"
						onDeselect={ () =>
							updateAttribute( 'scale', undefined )
						}
						resetAllFilter={ () => ( { scale: undefined } ) }
						panelId={ panelId }
						isShownByDefault
					>
						<ToggleGroupControl
							__next40pxDefaultSize
							label="Scale"
							value={ scale }
							onChange={ ( next ) =>
								updateAttribute( 'scale', next )
							}
							isBlock
						>
							<ToggleGroupControlOption
								value="cover"
								label="Cover"
							/>
							<ToggleGroupControlOption
								value="contain"
								label="Contain"
							/>
							<ToggleGroupControlOption
								value="fill"
								label="Fill"
							/>
						</ToggleGroupControl>
					</ToolsPanelItem>
				) }
			</ToolsPanelItems>
			<PanelWrapperView>
				<Panel>
					<ToolsPanel
						{ ...props }
						resetAll={ resetAll }
						panelId={ panelId }
					>
						<Slot />
					</ToolsPanel>
				</Panel>
			</PanelWrapperView>
		</SlotFillProvider>
	);
};

Tooltip

components-tooltip · ../packages/components/src/tooltip/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 8 prop types
Component: ../packages/components/src/tooltip/index.tsx::Tooltip
Props:
/**
 * The anchor for the tooltip.
 * 
 * **Note**: Accepts only one child element.
 */
children: React.ReactElement

/**
 * Custom class name for the tooltip.
 */
className?: string

/**
 * The amount of time in milliseconds to wait before showing the tooltip.
 * 
 * @default 700
 */
delay?: number

/**
 * Option to hide the tooltip when the anchor is clicked.
 * 
 * @default true
 */
hideOnClick?: boolean

/**
 * Where the tooltip should be positioned relative to its parent.
 * 
 * @default top
 */
placement?: Placement

/**
 * _Note: this prop is deprecated. Please use the `placement` prop instead._
 * 
 * Legacy way of specifying the tooltip's position relative to its parent.
 * 
 * Specify y- and x-axis as a space-separated string. Supports `"top"`,
 * `"bottom"` y axis, and `"left"`, `"center"`, `"right"` x axis.
 * 
 * @deprecated
 * @default top
 */
position?: PopoverProps[ 'position' ]

/**
 * An option for adding accessible keyboard shortcuts.
 * 
 * If shortcut is a string, it is expecting the display text. If shortcut is an
 * object, it will accept the properties of `display` (string) and `ariaLabel`
 * (string).
 */
shortcut?: ShortcutProps[ 'shortcut' ]

/**
 * The text shown in the tooltip when anchor element is focused or hovered.
 */
text?: string
Imports
import { Button, Tooltip } from "@wordpress/components";
Default story ok
const Default = ( props ) => (
	<Tooltip { ...props } />
);
Keyboard Shortcut story ok
const KeyboardShortcut = ( props ) => (
	<Tooltip { ...props } />
);
Nested story ok
In case one or more `Tooltip` components are rendered inside another `Tooltip` component, only the tooltip associated to the outermost `Tooltip` component will be rendered in the browser and shown to the user appropriately. The rest of the nested `Tooltip` components will simply no-op and pass-through their anchor.
const Nested = ( props ) => (
	<Tooltip { ...props } />
);

Tooltip.Root

design-system-components-tooltip · ../packages/ui/src/tooltip/stories/index.story.tsx
A badge component for displaying labels with semantic intent.
Prop types 4 prop types
Component: ../packages/ui/src/badge/badge.tsx::Badge
Props:
/**
 * The text to display in the badge.
 */
children: string

/**
 * CSS class name to apply to the component.
 */
className?: string

/**
 * The semantic intent of the badge, communicating its meaning through color.
 * 
 * @default "none"
 */
intent?: | 'high'
| 'medium'
| 'low'
| 'stable'
| 'informational'
| 'draft'
| 'none' = 'none'

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: | ComponentRenderFn< HTMLAttributesWithRef >
| React.ReactElement< Record< string, unknown > >
Imports
import { Icon, Tooltip } from "@wordpress/ui";
Default story ok
const Default = () => <Tooltip.Root>(<>
        <Tooltip.Trigger aria-label="Save">💾</Tooltip.Trigger>
        <Tooltip.Popup>Save</Tooltip.Popup>
    </>)</Tooltip.Root>;
Disabled story ok
The `disabled` prop prevents the tooltip from showing, and can be used to show the tooltip conditionally without rendering the underlying react component conditionally (which could cause reconciliation issues).
const Disabled = () => <Tooltip.Root disabled />;
Positioning story ok
Use the `side` prop to control where the tooltip appears relative to the trigger element.
const Positioning = () => (
    <div
        style={ {
            display: 'flex',
            gap: '2rem',
            padding: '4rem',
            justifyContent: 'center',
        } }
    >
        <Tooltip.Root>
            <Tooltip.Trigger aria-label="Up">⬆️</Tooltip.Trigger>
            <Tooltip.Popup side="top">Up</Tooltip.Popup>
        </Tooltip.Root>

        <Tooltip.Root>
            <Tooltip.Trigger aria-label="Forward">➡️</Tooltip.Trigger>
            <Tooltip.Popup side="right">Forward</Tooltip.Popup>
        </Tooltip.Root>

        <Tooltip.Root>
            <Tooltip.Trigger aria-label="Down">⬇️</Tooltip.Trigger>
            <Tooltip.Popup side="bottom">Down</Tooltip.Popup>
        </Tooltip.Root>

        <Tooltip.Root>
            <Tooltip.Trigger aria-label="Back">⬅️</Tooltip.Trigger>
            <Tooltip.Popup side="left">Back</Tooltip.Popup>
        </Tooltip.Root>
    </div>
);
With Provider story ok
Use `Tooltip.Provider` to control the delay before tooltips appear. This is useful when you have multiple tooltips and want them to share the same delay configuration.
const WithProvider = () => (
    <Tooltip.Provider delay={ 0 }>
        <div style={ { display: 'flex', gap: '1rem' } }>
            <Tooltip.Root>
                <Tooltip.Trigger aria-label="Bold">
                    <Icon icon={ formatBold } />
                </Tooltip.Trigger>
                <Tooltip.Popup>Bold</Tooltip.Popup>
            </Tooltip.Root>

            <Tooltip.Root>
                <Tooltip.Trigger aria-label="Italic">
                    <Icon icon={ formatItalic } />
                </Tooltip.Trigger>
                <Tooltip.Popup>Italic</Tooltip.Popup>
            </Tooltip.Root>
        </div>
    </Tooltip.Provider>
);

TreeGrid

components-treegrid · ../packages/components/src/tree-grid/stories/index.story.tsx
`TreeGrid` is used to create a tree hierarchy. It is not a visually styled component, but instead helps with adding keyboard navigation and roving tab index behaviors to tree grid structures. A tree grid is a hierarchical 2 dimensional UI component, for example it could be used to implement a file system browser. A tree grid allows the user to navigate using arrow keys. Up/down to navigate vertically across rows, and left/right to navigate horizontally between focusables in a row. The `TreeGrid` renders both a `table` and `tbody` element, and is intended to be used with `TreeGridRow` (`tr`) and `TreeGridCell` (`td`) to build out a grid. ```jsx function TreeMenu() { return ( <TreeGrid> <TreeGridRow level={ 1 } positionInSet={ 1 } setSize={ 2 }> <TreeGridCell> { ( props ) => ( <Button onClick={ onSelect } { ...props }>Select</Button> ) } </TreeGridCell> <TreeGridCell> { ( props ) => ( <Button onClick={ onMove } { ...props }>Move</Button> ) } </TreeGridCell> </TreeGridRow> <TreeGridRow level={ 1 } positionInSet={ 2 } setSize={ 2 }> <TreeGridCell> { ( props ) => ( <Button onClick={ onSelect } { ...props }>Select</Button> ) } </TreeGridCell> <TreeGridCell> { ( props ) => ( <Button onClick={ onMove } { ...props }>Move</Button> ) } </TreeGridCell> </TreeGridRow> <TreeGridRow level={ 2 } positionInSet={ 1 } setSize={ 1 }> <TreeGridCell> { ( props ) => ( <Button onClick={ onSelect } { ...props }>Select</Button> ) } </TreeGridCell> <TreeGridCell> { ( props ) => ( <Button onClick={ onMove } { ...props }>Move</Button> ) } </TreeGridCell> </TreeGridRow> </TreeGrid> ); } ```
see: {@link https://www.w3.org/TR/wai-aria-practices/examples/treegrid/treegrid-1.html}
Prop types 3 prop types
Component: ../packages/components/src/tree-grid/index.tsx::TreeGrid
Props:
onCollapseRow?: any = () => {}

onExpandRow?: any = () => {}

onFocusRow?: any = () => {}
Imports
import { Button, InputControl, TreeGrid, TreeGridCell, TreeGridRow } from "@wordpress/components";
import { Fragment } from "@wordpress/element";
Default story ok
const Default = () => <TreeGrid onExpandRow={fn()} onCollapseRow={fn()} onFocusRow={fn()}><Rows items={ groceries } /></TreeGrid>;

TreeSelect

components-treeselect · ../packages/components/src/tree-select/stories/index.story.tsx
Generates a hierarchical select input. ```jsx import { useState } from 'react'; import { TreeSelect } from '@wordpress/components'; const MyTreeSelect = () => { const [ page, setPage ] = useState( 'p21' ); return ( <TreeSelect __next40pxDefaultSize label="Parent page" noOptionLabel="No parent page" onChange={ ( newPage ) => setPage( newPage ) } selectedId={ page } tree={ [ { name: 'Page 1', id: 'p1', children: [ { name: 'Descend 1 of page 1', id: 'p11' }, { name: 'Descend 2 of page 1', id: 'p12' }, ], }, { name: 'Page 2', id: 'p2', children: [ { name: 'Descend 1 of page 2', id: 'p21', children: [ { name: 'Descend 1 of Descend 1 of page 2', id: 'p211', }, ], }, ], }, ] } /> ); } ```
Prop types 4 prop types
Component: ../packages/components/src/tree-select/index.tsx::TreeSelect
Props:
/**
 * If this property is added, an option will be added with this label to represent empty selection.
 */
noOptionLabel?: string

/**
 * A function that receives the value of the new option that is being selected as input.
 */
onChange?: SelectControlSingleSelectionProps[ 'onChange' ]

/**
 * The id of the currently selected node.
 */
selectedId?: SelectControlSingleSelectionProps[ 'value' ]

/**
 * An array containing the tree objects with the possible nodes the user can select.
 */
tree?: Tree[]
Imports
import { TreeSelect } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	const [ selection, setSelection ] =
		useState< ComponentProps< typeof TreeSelect >[ 'selectedId' ] >();

	return (
		<TreeSelect
			__next40pxDefaultSize
			{ ...props }
			onChange={ setSelection }
			selectedId={ selection }
		/>
	);
};

Truncate

components-truncate · ../packages/components/src/truncate/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Truncate } from "@wordpress/components";
Default story ok
const Default = () => {
    return <Truncate numberOfLines={2}>{defaultText}</Truncate>;
};
Truncate by character count story ok
const CharacterCount = () => {
    return <Truncate limit={23} ellipsizeMode="tail" ellipsis="[---]">{defaultText}</Truncate>;
};

UnitControl

blockeditor-unitcontrol · ../packages/block-editor/src/components/unit-control/stories/index.story.jsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { UnitControl } from "@wordpress/block-editor";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState();

    return (
        <UnitControl
            label="Label"
            value={ value }
            onChange={ ( ...changeArgs ) => {
                onChange( ...changeArgs );
                setValue( ...changeArgs );
            } } />
    );
};

UnitControl

components-unitcontrol · ../packages/components/src/unit-control/stories/index.story.tsx
`UnitControl` allows the user to set a numeric quantity as well as a unit (e.g. `px`). ```jsx import { __experimentalUnitControl as UnitControl } from '@wordpress/components'; import { useState } from '@wordpress/element'; const Example = () => { const [ value, setValue ] = useState( '10px' ); return <UnitControl __next40pxDefaultSize onChange={ setValue } value={ value } />; }; ```
Imports
import { UnitControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState< string | undefined >( '10px' );

    return (
        <UnitControl
            __next40pxDefaultSize
            onUnitChange={fn()}
            onFocus={fn()}
            onBlur={fn()}
            label="Label"
            value={ value }
            onChange={ ( v, extra ) => {
				setValue( v );
				onChange?.( v, extra );
			} } />
    );
};
Press Enter To Change story ok
If the `isPressEnterToChange` prop is set to `true`, the `onChange` callback will not fire while a new value is typed in the input field (you can verify this behavior by inspecting the console's output).
const PressEnterToChange = () => {
    const [ value, setValue ] = useState< string | undefined >( '10px' );

    return (
        <UnitControl
            __next40pxDefaultSize
            onUnitChange={fn()}
            onFocus={fn()}
            onBlur={fn()}
            isPressEnterToChange
            value={ value }
            onChange={ ( v, extra ) => {
				setValue( v );
				onChange?.( v, extra );
			} } />
    );
};
Tweaking The Number Input story ok
Most of `NumberControl`'s props can be passed to `UnitControl`, and they will affect its numeric input field.
const TweakingTheNumberInput = () => {
    const [ value, setValue ] = useState< string | undefined >( '10px' );

    return (
        <UnitControl
            __next40pxDefaultSize
            onUnitChange={fn()}
            onFocus={fn()}
            onBlur={fn()}
            min={0}
            max={100}
            step="any"
            label="Custom label"
            value={ value }
            onChange={ ( v, extra ) => {
				setValue( v );
				onChange?.( v, extra );
			} } />
    );
};
With Single Unit story ok
When only one unit is available, the unit selection dropdown becomes static text.
const WithSingleUnit = () => {
    const [ value, setValue ] = useState< string | undefined >( '10px' );

    return (
        <UnitControl
            __next40pxDefaultSize
            onUnitChange={fn()}
            onFocus={fn()}
            onBlur={fn()}
            units={CSS_UNITS.slice( 0, 1 )}
            value={ value }
            onChange={ ( v, extra ) => {
				setValue( v );
				onChange?.( v, extra );
			} } />
    );
};
With Custom Units story ok
It is possible to pass a custom list of units. Every time the unit changes, if the `isResetValueOnUnitChange` is set to `true`, the input's quantity is reset to the new unit's default value.
const WithCustomUnits = () => {
    const [ value, setValue ] = useState< string | undefined >( '80km' );

    return (
        <UnitControl
            __next40pxDefaultSize
            onUnitChange={fn()}
            onFocus={fn()}
            onBlur={fn()}
            isResetValueOnUnitChange
            min={0}
            units={[
                {
                    value: 'km',
                    label: 'km',
                    default: 1,
                },
                {
                    value: 'mi',
                    label: 'mi',
                    default: 1,
                },
                {
                    value: 'm',
                    label: 'm',
                    default: 1000,
                },
                {
                    value: 'yd',
                    label: 'yd',
                    default: 1760,
                },
            ]}
            value={ value }
            onChange={ ( v, extra ) => {
				setValue( v );
				onChange?.( v, extra );
			} } />
    );
};

URLPopover

blockeditor-urlpopover · ../packages/block-editor/src/components/url-popover/stories/index.story.jsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 1 prop type
Component: ../packages/block-editor/src/components/url-popover/index.js::default
Props:
focusOnMount?: any = 'firstElement'
Imports
import { Button, ToggleControl } from "@wordpress/components";
import { URLPopover } from "@wordpress/block-editor";
Default story ok
const _default = () => {
	return <TestURLPopover />;
};

UseCompositeStatePlaceholder

components-composite-unstable · ../packages/components/src/composite/legacy/stories/index.story.tsx
Renders a composite widget. This unstable component is deprecated. Use `Composite` instead. ```jsx import { __unstableUseCompositeState as useCompositeState, __unstableComposite as Composite, __unstableCompositeItem as CompositeItem, } from '@wordpress/components'; const state = useCompositeState(); <Composite state={ state }> <CompositeItem>Item 1</CompositeItem> <CompositeItem>Item 2</CompositeItem> </Composite>; ```
Prop types 8 prop types
Component: ../packages/components/src/composite/legacy/stories/utils.tsx::UseCompositeStatePlaceholder
Props:
/**
 * ID that will serve as a base for all the items IDs.
 */
baseId?: string

/**
 * The current focused item `id`.
 */
currentId?: string

/**
 * Determines how focus moves from the start and end of rows and columns.
 * 
 * @default false
 */
loop?: boolean | Orientation

/**
 * Defines the orientation of the composite widget. If the composite has a
 * single row or column (one-dimensional), the orientation value determines
 * which arrow keys can be used to move focus.
 */
orientation?: 'horizontal' | 'vertical'

/**
 * Determines how next and previous functions will behave. If `rtl` is set
 * to `true`, they will be inverted. This only affects the composite widget
 * behavior. You still need to set `dir="rtl"` on HTML/CSS.
 * 
 * @default false
 */
rtl?: boolean

/**
 * If enabled, moving up or down when there's no next item or the next item
 * is disabled will shift to the item right before it.
 * 
 * ** Has effect only on two-dimensional composites. **
 * 
 * @default false
 */
shift?: boolean

unstable_virtual?: boolean

/**
 * If enabled, moving to the next item from the last one in a row or column
 * will focus the first item in the next row or column and vice-versa.
 * 
 * ** Has effect only on two-dimensional composites. **
 * 
 * @default false
 */
wrap?: boolean | Orientation
Imports
import { Composite, CompositeGroup, CompositeItem, UseCompositeStatePlaceholder } from "@wordpress/components";
Two Dimensions With State Prop story ok
const TwoDimensionsWithStateProp = ( initialState ) => {
	const state = useCompositeState( initialState );

	return (
		<Composite
			role="grid"
			state={ state }
			aria-label="Legacy Composite with state prop (two dimensions)"
		>
			<CompositeGroup state={ state } role="row">
				<CompositeItem state={ state } role="gridcell">
					Item A1
				</CompositeItem>
				<CompositeItem state={ state } role="gridcell">
					Item A2
				</CompositeItem>
				<CompositeItem state={ state } role="gridcell">
					Item A3
				</CompositeItem>
			</CompositeGroup>
			<CompositeGroup state={ state } role="row">
				<CompositeItem state={ state } role="gridcell">
					Item B1
				</CompositeItem>
				<CompositeItem state={ state } role="gridcell">
					Item B2
				</CompositeItem>
				<CompositeItem state={ state } role="gridcell">
					Item B3
				</CompositeItem>
			</CompositeGroup>
			<CompositeGroup state={ state } role="row">
				<CompositeItem state={ state } role="gridcell">
					Item C1
				</CompositeItem>
				<CompositeItem state={ state } role="gridcell">
					Item C2
				</CompositeItem>
				<CompositeItem state={ state } role="gridcell">
					Item C3
				</CompositeItem>
			</CompositeGroup>
		</Composite>
	);
};
Two Dimensions With Spread Props story ok
const TwoDimensionsWithSpreadProps = ( initialState ) => {
	const state = useCompositeState( initialState );

	return (
		<Composite
			role="grid"
			{ ...state }
			aria-label="Legacy Composite with spread props (two dimensions)"
		>
			<CompositeGroup { ...state } role="row">
				<CompositeItem { ...state } role="gridcell">
					Item A1
				</CompositeItem>
				<CompositeItem { ...state } role="gridcell">
					Item A2
				</CompositeItem>
				<CompositeItem { ...state } role="gridcell">
					Item A3
				</CompositeItem>
			</CompositeGroup>
			<CompositeGroup { ...state } role="row">
				<CompositeItem { ...state } role="gridcell">
					Item B1
				</CompositeItem>
				<CompositeItem { ...state } role="gridcell">
					Item B2
				</CompositeItem>
				<CompositeItem { ...state } role="gridcell">
					Item B3
				</CompositeItem>
			</CompositeGroup>
			<CompositeGroup { ...state } role="row">
				<CompositeItem { ...state } role="gridcell">
					Item C1
				</CompositeItem>
				<CompositeItem { ...state } role="gridcell">
					Item C2
				</CompositeItem>
				<CompositeItem { ...state } role="gridcell">
					Item C3
				</CompositeItem>
			</CompositeGroup>
		</Composite>
	);
};
One Dimension With State Prop story ok
const OneDimensionWithStateProp = ( initialState ) => {
	const state = useCompositeState( initialState );

	return (
		<Composite
			role="list"
			state={ state }
			aria-label="Legacy Composite with state prop (one dimension)"
		>
			<CompositeItem state={ state } role="listitem">
				Item 1
			</CompositeItem>
			<CompositeItem state={ state } role="listitem">
				Item 2
			</CompositeItem>
			<CompositeItem state={ state } role="listitem">
				Item 3
			</CompositeItem>
			<CompositeItem state={ state } role="listitem">
				Item 4
			</CompositeItem>
			<CompositeItem state={ state } role="listitem">
				Item 5
			</CompositeItem>
		</Composite>
	);
};
One Dimension With Spread Props story ok
const OneDimensionWithSpreadProps = ( initialState ) => {
	const state = useCompositeState( initialState );

	return (
		<Composite
			role="list"
			{ ...state }
			aria-label="Legacy Composite with spread props (one dimension)"
		>
			<CompositeItem { ...state } role="listitem">
				Item 1
			</CompositeItem>
			<CompositeItem { ...state } role="listitem">
				Item 2
			</CompositeItem>
			<CompositeItem { ...state } role="listitem">
				Item 3
			</CompositeItem>
			<CompositeItem { ...state } role="listitem">
				Item 4
			</CompositeItem>
			<CompositeItem { ...state } role="listitem">
				Item 5
			</CompositeItem>
		</Composite>
	);
};

ValidatedCheckboxControl

components-validatedcheckboxcontrol · ../packages/components/src/validated-form-controls/components/stories/checkbox-control.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 3 prop types
Component: ../packages/components/src/validated-form-controls/components/checkbox-control.tsx::ValidatedCheckboxControl
Props:
/**
 * Show a custom message based on the validation status.
 * 
 * - When `type` is `invalid`, the message will be applied to the underlying element using the
 * native [`setCustomValidity()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity).
 * This means the custom message will be prioritized over any existing validity messages
 * triggered by HTML attribute-based validation.
 * - When `type` is `validating` or `valid`, the custom validity message of the underlying element
 * will be cleared. If there are no remaining validity messages triggered by HTML attribute-based validation,
 * the message will be presented as a status indicator rather than an error. These indicators are intended
 * for asynchronous validation calls that may take more than 1 second to complete.
 * Otherwise, custom errors can simply be cleared by setting the `customValidity` prop to `undefined`.
 */
customValidity?: {
	type: 'validating' | 'valid' | 'invalid';
	message: string;
}

/**
 * Label the control as "optional" when _not_ `required`, instead of the inverse.
 * @default false
 */
markWhenOptional?: boolean

/**
 * Whether the control is required.
 * @default false
 */
required?: boolean
Imports
import { ValidatedCheckboxControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ checked, setChecked ] = useState( false );

    return (
        <ValidatedCheckboxControl
            required
            label="Checkbox"
            help="This checkbox may neither be checked nor unchecked."
            checked={ checked }
            onChange={ ( newValue ) => {
                setChecked( newValue );
                onChange?.( newValue );
            } }
            customValidity={
                checked
                    ? {
                            type: 'invalid',
                            message: 'This checkbox may not be checked.',
                      }
                    : undefined
            } />
    );
};

ValidatedComboboxControl

components-validatedcomboboxcontrol · ../packages/components/src/validated-form-controls/components/stories/combobox-control.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 3 prop types
Component: ../packages/components/src/validated-form-controls/components/combobox-control.tsx::ValidatedComboboxControl
Props:
/**
 * Show a custom message based on the validation status.
 * 
 * - When `type` is `invalid`, the message will be applied to the underlying element using the
 * native [`setCustomValidity()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity).
 * This means the custom message will be prioritized over any existing validity messages
 * triggered by HTML attribute-based validation.
 * - When `type` is `validating` or `valid`, the custom validity message of the underlying element
 * will be cleared. If there are no remaining validity messages triggered by HTML attribute-based validation,
 * the message will be presented as a status indicator rather than an error. These indicators are intended
 * for asynchronous validation calls that may take more than 1 second to complete.
 * Otherwise, custom errors can simply be cleared by setting the `customValidity` prop to `undefined`.
 */
customValidity?: {
	type: 'validating' | 'valid' | 'invalid';
	message: string;
}

/**
 * Label the control as "optional" when _not_ `required`, instead of the inverse.
 * @default false
 */
markWhenOptional?: boolean

/**
 * Whether the control is required.
 * @default false
 */
required?: boolean
Imports
import { ValidatedComboboxControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ value, setValue ] =
        useState<
            React.ComponentProps<
                typeof ValidatedComboboxControl
            >[ 'value' ]
        >();

    return (
        <ValidatedComboboxControl
            required
            label="Combobox"
            help="Option A is not allowed."
            options={[
                { value: 'a', label: 'Option A (not allowed)' },
                { value: 'b', label: 'Option B' },
            ]}
            value={ value }
            onChange={ ( newValue ) => {
                setValue( newValue );
                onChange?.( newValue );
            } }
            customValidity={
                value === 'a'
                    ? {
                            type: 'invalid',
                            message: 'Option A is not allowed.',
                      }
                    : undefined
            } />
    );
};

ValidatedCustomSelectControl

components-validatedcustomselectcontrol · ../packages/components/src/validated-form-controls/components/stories/custom-select-control.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 3 prop types
Component: ../packages/components/src/validated-form-controls/components/custom-select-control.tsx::ValidatedCustomSelectControl
Props:
/**
 * Show a custom message based on the validation status.
 * 
 * - When `type` is `invalid`, the message will be applied to the underlying element using the
 * native [`setCustomValidity()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity).
 * This means the custom message will be prioritized over any existing validity messages
 * triggered by HTML attribute-based validation.
 * - When `type` is `validating` or `valid`, the custom validity message of the underlying element
 * will be cleared. If there are no remaining validity messages triggered by HTML attribute-based validation,
 * the message will be presented as a status indicator rather than an error. These indicators are intended
 * for asynchronous validation calls that may take more than 1 second to complete.
 * Otherwise, custom errors can simply be cleared by setting the `customValidity` prop to `undefined`.
 */
customValidity?: {
	type: 'validating' | 'valid' | 'invalid';
	message: string;
}

/**
 * Label the control as "optional" when _not_ `required`, instead of the inverse.
 * @default false
 */
markWhenOptional?: boolean

/**
 * Whether the control is required.
 * @default false
 */
required?: boolean
Imports
import { ValidatedCustomSelectControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ value, setValue ] =
        useState<
            React.ComponentProps<
                typeof ValidatedCustomSelectControl
            >[ 'value' ]
        >();

    return (
        <ValidatedCustomSelectControl
            required
            label="Custom Select"
            options={[
                { key: '', name: 'Select an option' },
                { key: 'a', name: 'Option A (not allowed)' },
                { key: 'b', name: 'Option B' },
            ]}
            value={ value }
            onChange={ ( newValue ) => {
                setValue( newValue.selectedItem );
                onChange?.( newValue );
            } }
            customValidity={
                value?.key === 'a'
                    ? {
                            type: 'invalid',
                            message: 'Option A is not allowed.',
                      }
                    : undefined
            } />
    );
};

ValidatedFormTokenField

components-validatedformtokenfield · ../packages/components/src/validated-form-controls/components/stories/form-token-field.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 3 prop types
Component: ../packages/components/src/validated-form-controls/components/form-token-field.tsx::ValidatedFormTokenField
Props:
/**
 * Show a custom message based on the validation status.
 * 
 * - When `type` is `invalid`, the message will be applied to the underlying element using the
 * native [`setCustomValidity()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity).
 * This means the custom message will be prioritized over any existing validity messages
 * triggered by HTML attribute-based validation.
 * - When `type` is `validating` or `valid`, the custom validity message of the underlying element
 * will be cleared. If there are no remaining validity messages triggered by HTML attribute-based validation,
 * the message will be presented as a status indicator rather than an error. These indicators are intended
 * for asynchronous validation calls that may take more than 1 second to complete.
 * Otherwise, custom errors can simply be cleared by setting the `customValidity` prop to `undefined`.
 */
customValidity?: {
	type: 'validating' | 'valid' | 'invalid';
	message: string;
}

/**
 * Label the control as "optional" when _not_ `required`, instead of the inverse.
 * @default false
 */
markWhenOptional?: boolean

/**
 * Whether the control is required.
 * @default false
 */
required?: boolean
Imports
import { ValidatedFormTokenField } from "@wordpress/components";
Default story ok
This demonstrates how array validation would work with the ValidatedFormTokenField component.
const Default = () => {
    const [ value, setValue ] = useState< ( string | TokenItem )[] >( [] );

    return (
        <ValidatedFormTokenField
            required
            label="Tags"
            placeholder="Add tags..."
            suggestions={[ 'Posts', 'Pages', 'Media', 'Error' ]}
            __experimentalExpandOnFocus
            value={ value }
            onChange={ ( newValue ) => {
                setValue( newValue );
                onChange?.( newValue );
            } }
            customValidity={
                value?.some( ( token ) => {
                    const tokenValue =
                        typeof token === 'string' ? token : token.value;
                    return tokenValue.toLowerCase() === 'error';
                } )
                    ? {
                            type: 'invalid',
                            message: 'The tag "error" is not allowed.',
                      }
                    : undefined
            } />
    );
};

ValidatedInputControl

components-validatedinputcontrol · ../packages/components/src/validated-form-controls/components/stories/input-control.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 3 prop types
Component: ../packages/components/src/validated-form-controls/components/input-control.tsx::ValidatedInputControl
Props:
/**
 * Show a custom message based on the validation status.
 * 
 * - When `type` is `invalid`, the message will be applied to the underlying element using the
 * native [`setCustomValidity()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity).
 * This means the custom message will be prioritized over any existing validity messages
 * triggered by HTML attribute-based validation.
 * - When `type` is `validating` or `valid`, the custom validity message of the underlying element
 * will be cleared. If there are no remaining validity messages triggered by HTML attribute-based validation,
 * the message will be presented as a status indicator rather than an error. These indicators are intended
 * for asynchronous validation calls that may take more than 1 second to complete.
 * Otherwise, custom errors can simply be cleared by setting the `customValidity` prop to `undefined`.
 */
customValidity?: {
	type: 'validating' | 'valid' | 'invalid';
	message: string;
}

/**
 * Label the control as "optional" when _not_ `required`, instead of the inverse.
 * @default false
 */
markWhenOptional?: boolean

/**
 * Whether the control is required.
 * @default false
 */
required?: boolean
Imports
import { Button, InputControlSuffixWrapper, ValidatedInputControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState< string | undefined >( '' );

    return (
        <ValidatedInputControl
            required
            label="Input"
            help="The word \"error\" will trigger an error."
            value={ value }
            onChange={ ( newValue, ...rest ) => {
                setValue( newValue );
                onChange?.( newValue, ...rest );
            } }
            customValidity={
                value?.toLowerCase() === 'error'
                    ? {
                            type: 'invalid',
                            message: 'The word "error" is not allowed.',
                      }
                    : undefined
            } />
    );
};
Password story ok
This demonstrates how password validation would work with the standard implementation. We are planning to move to a custom implementation more tailored to the password use case.
const Password = () => {
    const [ value, setValue ] = useState< string | undefined >( '' );
    const [ visible, setVisible ] = useState( false );

    return (
        <ValidatedInputControl
            required
            label="Password"
            help="Minimum 8 characters, include a number, capital letter, and symbol (!@£$%^&*#)."
            minLength={8}
            type={ visible ? 'text' : 'password' }
            suffix={
                <InputControlSuffixWrapper variant="control">
                    <Button
                        size="small"
                        icon={ visible ? unseen : seen }
                        onClick={ () => setVisible( ( v ) => ! v ) }
                        label={
                            visible ? 'Hide password' : 'Show password'
                        }
                    />
                </InputControlSuffixWrapper>
            }
            value={ value }
            onChange={ ( newValue, ...rest ) => {
                setValue( newValue );
                onChange?.( newValue, ...rest );
            } }
            customValidity={ ( () => {
                if ( ! /\d/.test( value ?? '' ) ) {
                    return {
                        type: 'invalid' as const,
                        message:
                            'Password must include at least one number.',
                    };
                }
                if ( ! /[A-Z]/.test( value ?? '' ) ) {
                    return {
                        type: 'invalid' as const,
                        message:
                            'Password must include at least one capital letter.',
                    };
                }
                if ( ! /[!@£$%^&*#]/.test( value ?? '' ) ) {
                    return {
                        type: 'invalid' as const,
                        message:
                            'Password must include at least one symbol.',
                    };
                }
                return undefined;
            } )() } />
    );
};

ValidatedNumberControl

components-validatednumbercontrol · ../packages/components/src/validated-form-controls/components/stories/number-control.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 3 prop types
Component: ../packages/components/src/validated-form-controls/components/number-control.tsx::ValidatedNumberControl
Props:
/**
 * Show a custom message based on the validation status.
 * 
 * - When `type` is `invalid`, the message will be applied to the underlying element using the
 * native [`setCustomValidity()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity).
 * This means the custom message will be prioritized over any existing validity messages
 * triggered by HTML attribute-based validation.
 * - When `type` is `validating` or `valid`, the custom validity message of the underlying element
 * will be cleared. If there are no remaining validity messages triggered by HTML attribute-based validation,
 * the message will be presented as a status indicator rather than an error. These indicators are intended
 * for asynchronous validation calls that may take more than 1 second to complete.
 * Otherwise, custom errors can simply be cleared by setting the `customValidity` prop to `undefined`.
 */
customValidity?: {
	type: 'validating' | 'valid' | 'invalid';
	message: string;
}

/**
 * Label the control as "optional" when _not_ `required`, instead of the inverse.
 * @default false
 */
markWhenOptional?: boolean

/**
 * Whether the control is required.
 * @default false
 */
required?: boolean
Imports
import { ValidatedNumberControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ value, setValue ] =
        useState<
            React.ComponentProps< typeof ValidatedNumberControl >[ 'value' ]
        >();

    return (
        <ValidatedNumberControl
            required
            label="Number"
            help="Odd numbers are not allowed."
            value={ value }
            onChange={ ( newValue, extra ) => {
                setValue( newValue );
                onChange?.( newValue, extra );
            } }
            customValidity={
                value && parseInt( value.toString(), 10 ) % 2 !== 0
                    ? {
                            type: 'invalid',
                            message: 'Choose an even number.',
                      }
                    : undefined
            } />
    );
};

ValidatedRadioControl

components-validatedradiocontrol · ../packages/components/src/validated-form-controls/components/stories/radio-control.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 3 prop types
Component: ../packages/components/src/validated-form-controls/components/radio-control.tsx::ValidatedRadioControl
Props:
/**
 * Show a custom message based on the validation status.
 * 
 * - When `type` is `invalid`, the message will be applied to the underlying element using the
 * native [`setCustomValidity()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity).
 * This means the custom message will be prioritized over any existing validity messages
 * triggered by HTML attribute-based validation.
 * - When `type` is `validating` or `valid`, the custom validity message of the underlying element
 * will be cleared. If there are no remaining validity messages triggered by HTML attribute-based validation,
 * the message will be presented as a status indicator rather than an error. These indicators are intended
 * for asynchronous validation calls that may take more than 1 second to complete.
 * Otherwise, custom errors can simply be cleared by setting the `customValidity` prop to `undefined`.
 */
customValidity?: {
	type: 'validating' | 'valid' | 'invalid';
	message: string;
}

/**
 * Label the control as "optional" when _not_ `required`, instead of the inverse.
 * @default false
 */
markWhenOptional?: boolean

/**
 * Whether the control is required.
 * @default false
 */
required?: boolean
Imports
import { ValidatedRadioControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ selected, setSelected ] =
        useState<
            React.ComponentProps<
                typeof ValidatedRadioControl
            >[ 'selected' ]
        >();

    return (
        <ValidatedRadioControl
            required
            label="Radio"
            help="Option B is not allowed."
            options={[
                { label: 'Option A', value: 'a' },
                { label: 'Option B (not allowed)', value: 'b' },
            ]}
            selected={ selected }
            onChange={ ( newValue ) => {
                setSelected( newValue );
                onChange?.( newValue );
            } }
            customValidity={
                selected === 'b'
                    ? {
                            type: 'invalid',
                            message: 'Option B is not allowed.',
                      }
                    : undefined
            } />
    );
};

ValidatedRangeControl

components-validatedrangecontrol · ../packages/components/src/validated-form-controls/components/stories/range-control.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 3 prop types
Component: ../packages/components/src/validated-form-controls/components/range-control.tsx::ValidatedRangeControl
Props:
/**
 * Show a custom message based on the validation status.
 * 
 * - When `type` is `invalid`, the message will be applied to the underlying element using the
 * native [`setCustomValidity()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity).
 * This means the custom message will be prioritized over any existing validity messages
 * triggered by HTML attribute-based validation.
 * - When `type` is `validating` or `valid`, the custom validity message of the underlying element
 * will be cleared. If there are no remaining validity messages triggered by HTML attribute-based validation,
 * the message will be presented as a status indicator rather than an error. These indicators are intended
 * for asynchronous validation calls that may take more than 1 second to complete.
 * Otherwise, custom errors can simply be cleared by setting the `customValidity` prop to `undefined`.
 */
customValidity?: {
	type: 'validating' | 'valid' | 'invalid';
	message: string;
}

/**
 * Label the control as "optional" when _not_ `required`, instead of the inverse.
 * @default false
 */
markWhenOptional?: boolean

/**
 * Whether the control is required.
 * @default false
 */
required?: boolean
Imports
import { ValidatedRangeControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ value, setValue ] =
        useState<
            React.ComponentProps< typeof ValidatedRangeControl >[ 'value' ]
        >();

    return (
        <ValidatedRangeControl
            required
            label="Range"
            help="Odd numbers are not allowed."
            min={0}
            max={20}
            value={ value }
            onChange={ ( newValue ) => {
                setValue( newValue );
                onChange?.( newValue );
            } }
            customValidity={
                value && value % 2 !== 0
                    ? {
                            type: 'invalid',
                            message: 'Choose an even number.',
                      }
                    : undefined
            } />
    );
};

ValidatedSelectControl

components-validatedselectcontrol · ../packages/components/src/validated-form-controls/components/stories/select-control.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 5 prop types
Component: ../packages/components/src/validated-form-controls/components/select-control.tsx::ValidatedSelectControl
Props:
/**
 * Show a custom message based on the validation status.
 * 
 * - When `type` is `invalid`, the message will be applied to the underlying element using the
 * native [`setCustomValidity()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity).
 * This means the custom message will be prioritized over any existing validity messages
 * triggered by HTML attribute-based validation.
 * - When `type` is `validating` or `valid`, the custom validity message of the underlying element
 * will be cleared. If there are no remaining validity messages triggered by HTML attribute-based validation,
 * the message will be presented as a status indicator rather than an error. These indicators are intended
 * for asynchronous validation calls that may take more than 1 second to complete.
 * Otherwise, custom errors can simply be cleared by setting the `customValidity` prop to `undefined`.
 */
customValidity?: {
	type: 'validating' | 'valid' | 'invalid';
	message: string;
}

/**
 * Label the control as "optional" when _not_ `required`, instead of the inverse.
 * @default false
 */
markWhenOptional?: boolean

onChange: ( value: string ) => void

/**
 * Whether the control is required.
 * @default false
 */
required?: boolean

value?: string
Imports
import { ValidatedSelectControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState< string | undefined >( '' );

    return (
        <ValidatedSelectControl
            required
            label="Select"
            help="Selecting option 1 will trigger an error."
            options={[
                { value: '', label: 'Select an option' },
                { value: '1', label: 'Option 1 (not allowed)' },
                { value: '2', label: 'Option 2' },
            ]}
            value={ value }
            onChange={ ( newValue ) => {
                setValue( newValue );
                onChange?.( newValue );
            } }
            customValidity={
                value === '1'
                    ? {
                            type: 'invalid',
                            message: 'Option 1 is not allowed.',
                      }
                    : undefined
            } />
    );
};

ValidatedTextareaControl

components-validatedtextareacontrol · ../packages/components/src/validated-form-controls/components/stories/textarea-control.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 3 prop types
Component: ../packages/components/src/validated-form-controls/components/textarea-control.tsx::ValidatedTextareaControl
Props:
/**
 * Show a custom message based on the validation status.
 * 
 * - When `type` is `invalid`, the message will be applied to the underlying element using the
 * native [`setCustomValidity()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity).
 * This means the custom message will be prioritized over any existing validity messages
 * triggered by HTML attribute-based validation.
 * - When `type` is `validating` or `valid`, the custom validity message of the underlying element
 * will be cleared. If there are no remaining validity messages triggered by HTML attribute-based validation,
 * the message will be presented as a status indicator rather than an error. These indicators are intended
 * for asynchronous validation calls that may take more than 1 second to complete.
 * Otherwise, custom errors can simply be cleared by setting the `customValidity` prop to `undefined`.
 */
customValidity?: {
	type: 'validating' | 'valid' | 'invalid';
	message: string;
}

/**
 * Label the control as "optional" when _not_ `required`, instead of the inverse.
 * @default false
 */
markWhenOptional?: boolean

/**
 * Whether the control is required.
 * @default false
 */
required?: boolean
Imports
import { ValidatedTextareaControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ value, setValue ] =
        useState<
            React.ComponentProps<
                typeof ValidatedTextareaControl
            >[ 'value' ]
        >( '' );

    return (
        <ValidatedTextareaControl
            required
            label="Textarea"
            help="The word \"error\" will trigger an error."
            value={ value }
            onChange={ ( newValue ) => {
                setValue( newValue );
                onChange?.( newValue );
            } }
            customValidity={
                value?.toLowerCase() === 'error'
                    ? {
                            type: 'invalid',
                            message: 'The word "error" is not allowed.',
                      }
                    : undefined
            } />
    );
};

ValidatedTextControl

components-validatedtextcontrol · ../packages/components/src/validated-form-controls/components/stories/text-control.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 3 prop types
Component: ../packages/components/src/validated-form-controls/components/text-control.tsx::ValidatedTextControl
Props:
/**
 * Show a custom message based on the validation status.
 * 
 * - When `type` is `invalid`, the message will be applied to the underlying element using the
 * native [`setCustomValidity()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity).
 * This means the custom message will be prioritized over any existing validity messages
 * triggered by HTML attribute-based validation.
 * - When `type` is `validating` or `valid`, the custom validity message of the underlying element
 * will be cleared. If there are no remaining validity messages triggered by HTML attribute-based validation,
 * the message will be presented as a status indicator rather than an error. These indicators are intended
 * for asynchronous validation calls that may take more than 1 second to complete.
 * Otherwise, custom errors can simply be cleared by setting the `customValidity` prop to `undefined`.
 */
customValidity?: {
	type: 'validating' | 'valid' | 'invalid';
	message: string;
}

/**
 * Label the control as "optional" when _not_ `required`, instead of the inverse.
 * @default false
 */
markWhenOptional?: boolean

/**
 * Whether the control is required.
 * @default false
 */
required?: boolean
Imports
import { ValidatedTextControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ value, setValue ] =
        useState<
            React.ComponentProps< typeof ValidatedTextControl >[ 'value' ]
        >( '' );

    return (
        <ValidatedTextControl
            required
            label="Text"
            help="The word 'error' will trigger an error."
            value={ value }
            onChange={ ( newValue ) => {
                setValue( newValue );
                onChange?.( newValue );
            } }
            customValidity={
                value === 'error'
                    ? {
                            type: 'invalid',
                            message: 'The word "error" is not allowed.',
                      }
                    : undefined
            } />
    );
};

ValidatedToggleControl

components-validatedtogglecontrol · ../packages/components/src/validated-form-controls/components/stories/toggle-control.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 3 prop types
Component: ../packages/components/src/validated-form-controls/components/toggle-control.tsx::ValidatedToggleControl
Props:
/**
 * Show a custom message based on the validation status.
 * 
 * - When `type` is `invalid`, the message will be applied to the underlying element using the
 * native [`setCustomValidity()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity).
 * This means the custom message will be prioritized over any existing validity messages
 * triggered by HTML attribute-based validation.
 * - When `type` is `validating` or `valid`, the custom validity message of the underlying element
 * will be cleared. If there are no remaining validity messages triggered by HTML attribute-based validation,
 * the message will be presented as a status indicator rather than an error. These indicators are intended
 * for asynchronous validation calls that may take more than 1 second to complete.
 * Otherwise, custom errors can simply be cleared by setting the `customValidity` prop to `undefined`.
 */
customValidity?: {
	type: 'validating' | 'valid' | 'invalid';
	message: string;
}

/**
 * Label the control as "optional" when _not_ `required`, instead of the inverse.
 * @default false
 */
markWhenOptional?: boolean

/**
 * Whether the control is required.
 * @default false
 */
required?: boolean
Imports
import { ValidatedToggleControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ checked, setChecked ] = useState( false );

    return (
        <ValidatedToggleControl
            required
            label="Toggle"
            help="This toggle may neither be enabled nor disabled."
            checked={ checked }
            onChange={ ( newValue ) => {
                setChecked( newValue );
                onChange?.( newValue );
            } }
            customValidity={
                checked
                    ? {
                            type: 'invalid',
                            message: 'This toggle may not be enabled.',
                      }
                    : undefined
            } />
    );
};

ValidatedToggleGroupControl

components-validatedtogglegroupcontrol · ../packages/components/src/validated-form-controls/components/stories/toggle-group-control.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Prop types 3 prop types
Component: ../packages/components/src/validated-form-controls/components/toggle-group-control.tsx::ValidatedToggleGroupControl
Props:
/**
 * Show a custom message based on the validation status.
 * 
 * - When `type` is `invalid`, the message will be applied to the underlying element using the
 * native [`setCustomValidity()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity).
 * This means the custom message will be prioritized over any existing validity messages
 * triggered by HTML attribute-based validation.
 * - When `type` is `validating` or `valid`, the custom validity message of the underlying element
 * will be cleared. If there are no remaining validity messages triggered by HTML attribute-based validation,
 * the message will be presented as a status indicator rather than an error. These indicators are intended
 * for asynchronous validation calls that may take more than 1 second to complete.
 * Otherwise, custom errors can simply be cleared by setting the `customValidity` prop to `undefined`.
 */
customValidity?: {
	type: 'validating' | 'valid' | 'invalid';
	message: string;
}

/**
 * Label the control as "optional" when _not_ `required`, instead of the inverse.
 * @default false
 */
markWhenOptional?: boolean

/**
 * Whether the control is required.
 * @default false
 */
required?: boolean
Imports
import { ToggleGroupControlOption, ValidatedToggleGroupControl } from "@wordpress/components";
Default story ok
const Default = () => {
    const [ value, setValue ] =
        useState<
            React.ComponentProps<
                typeof ValidatedToggleGroupControl
            >[ 'value' ]
        >( '1' );

    return (
        <ValidatedToggleGroupControl
            required
            label="Toggle Group"
            isBlock
            help="Selecting option 2 will trigger an error."
            value={ value }
            onChange={ ( newValue ) => {
                setValue( newValue );
                onChange?.( newValue );
            } }
            customValidity={
                value === '2'
                    ? {
                            type: 'invalid',
                            message: 'Option 2 is not allowed.',
                      }
                    : undefined
            }>{[
                <ToggleGroupControlOption value="1" key="1" label="Option 1" />,
                <ToggleGroupControlOption value="2" key="2" label="Option 2" />,
            ]}</ValidatedToggleGroupControl>
    );
};

Verifier

design-system-theme-theme-provider-brand-color-fallbacks · ../packages/theme/src/color-ramps/stories/brand-fallbacks.story.tsx
Prop type error
No component file found for the "Verifier" component.
  44 |  * schemes and observe how closely the fallbacks track the real values.
  45 |  */
> 46 | const meta: Meta< typeof Verifier > = {
     | ^
  47 | 	title: 'Design System/Theme/Theme Provider/Brand Color Fallbacks',
  48 | 	component: Verifier,
  49 | 	argTypes: {

../packages/theme/src/color-ramps/stories/brand-fallbacks.story.tsx:
import type { Meta, StoryObj } from '@storybook/react-vite';
import colorTokens from '../../prebuilt/ts/color-tokens';
import _tokenFallbacks from '../../prebuilt/js/design-token-fallbacks.mjs';
import { ThemeProvider } from '../../theme-provider';

const tokenFallbacks: Record< string, string > = _tokenFallbacks;

type BrandToken = {
	cssVarName: string;
	fallbackExpr: string;
};

function getBrandTokens(): BrandToken[] {
	const tokens: BrandToken[] = [];

	for ( const [ rampKey, tokenNames ] of Object.entries( colorTokens ) ) {
		if ( ! rampKey.startsWith( 'primary-' ) ) {
			continue;
		}

		for ( const tokenName of tokenNames ) {
			const cssVarName = `--wpds-color-${ tokenName }`;
			tokens.push( {
				cssVarName,
				fallbackExpr: tokenFallbacks[ cssVarName ] ?? '',
			} );
		}
	}

	return tokens.sort( ( a, b ) =>
		a.cssVarName.localeCompare( b.cssVarName )
	);
}

const brandTokens = getBrandTokens();

type VerifierProps = { adminThemeColor: string };
const Verifier: React.FC< VerifierProps > = () => null;

/**
 * Compares actual brand token values (computed by ThemeProvider using the full
 * ramp algorithm) against their `color-mix()` fallback approximations driven
 * by `--wp-admin-theme-color`. Use the color picker to switch admin color
 * schemes and observe how closely the fallbacks track the real values.
 */
const meta: Meta< typeof Verifier > = {
	title: 'Design System/Theme/Theme Provider/Brand Color Fallbacks',
	component: Verifier,
	argTypes: {
		adminThemeColor: {
			control: {
				type: 'color',
				presetColors: [
					'#3858e9', // modern
					'#0085ba', // light
					'#096484', // blue
					'#46403c', // coffee
					'#523f6d', // ectoplasm
					'#e14d43', // midnight
					'#627c83', // ocean
					'#dd823b', // sunrise
				],
			},
		},
	},
	parameters: {
		controls: { expanded: true },
	},
};
export default meta;

export const Default: StoryObj< typeof Verifier > = {
	render: ( { adminThemeColor } ) => (
		<div
			style={
				{
					'--wp-admin-theme-color': adminThemeColor,
					fontSize: 13,
				} as React.CSSProperties
			}
		>
			<p
				style={ {
					margin: '0 0 16px',
					color: '#757575',
					fontSize: 12,
				} }
			>
				<strong>Actual:</strong> real token value from ThemeProvider
				(ramp algorithm). <strong>Fallback:</strong> approximation via{ ' ' }
				<code>color-mix()</code> and <code>--wp-admin-theme-color</code>
				.
			</p>
			<ThemeProvider color={ { primary: adminThemeColor } }>
				<div
					style={ {
						display: 'grid',
						gridTemplateColumns: '40px 40px 1fr 1fr',
						gap: '4px 12px',
						alignItems: 'center',
					} }
				>
					<div style={ headerStyle }>Actual</div>
					<div style={ headerStyle }>Fallback</div>
					<div style={ headerStyle }>Token</div>
					<div style={ headerStyle }>Fallback expression</div>
					{ brandTokens.map( ( { cssVarName, fallbackExpr } ) => (
						<Row
							key={ cssVarName }
							cssVarName={ cssVarName }
							fallbackExpr={ fallbackExpr }
						/>
					) ) }
				</div>
			</ThemeProvider>
		</div>
	),
	args: {
		adminThemeColor: '#3858e9',
	},
};

const headerStyle: React.CSSProperties = {
	fontSize: 11,
	fontWeight: 600,
	color: '#757575',
	paddingBottom: 4,
	borderBottom: '1px solid #e0e0e0',
};

function Row( { cssVarName, fallbackExpr }: BrandToken ) {
	return (
		<>
			<Swatch
				color={ `var(${ cssVarName })` }
				title={ `${ cssVarName } (actual)` }
			/>
			<Swatch color={ fallbackExpr } title="Fallback (rendered)" />
			<code style={ { fontSize: 12 } }>{ cssVarName }</code>
			<code
				style={ {
					fontSize: 11,
					color: '#555',
					wordBreak: 'break-all',
				} }
			>
				{ fallbackExpr }
			</code>
		</>
	);
}

function Swatch( { color, title }: { color: string; title: string } ) {
	return (
		<div
			title={ title }
			style={ {
				backgroundColor: color,
				width: 40,
				height: 28,
				border: '1px solid rgba(0, 0, 0, 0.1)',
			} }
		/>
	);
}
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { ThemeProvider } from "@wordpress/theme";
Default story ok
const Default = ( { adminThemeColor } ) => (
    <div
        style={
            {
                '--wp-admin-theme-color': adminThemeColor,
                fontSize: 13,
            } as React.CSSProperties
        }
    >
        <p
            style={ {
                margin: '0 0 16px',
                color: '#757575',
                fontSize: 12,
            } }
        >
            <strong>Actual:</strong> real token value from ThemeProvider
            (ramp algorithm). <strong>Fallback:</strong> approximation via{ ' ' }
            <code>color-mix()</code> and <code>--wp-admin-theme-color</code>
            .
        </p>
        <ThemeProvider color={ { primary: adminThemeColor } }>
            <div
                style={ {
                    display: 'grid',
                    gridTemplateColumns: '40px 40px 1fr 1fr',
                    gap: '4px 12px',
                    alignItems: 'center',
                } }
            >
                <div style={ headerStyle }>Actual</div>
                <div style={ headerStyle }>Fallback</div>
                <div style={ headerStyle }>Token</div>
                <div style={ headerStyle }>Fallback expression</div>
                { brandTokens.map( ( { cssVarName, fallbackExpr } ) => (
                    <Row
                        key={ cssVarName }
                        cssVarName={ cssVarName }
                        fallbackExpr={ fallbackExpr }
                    />
                ) ) }
            </div>
        </ThemeProvider>
    </div>
);

View

components-view · ../packages/components/src/view/stories/index.story.tsx
`View` is a core component that renders everything in the library. It is the principle component in the entire library. ```jsx import { View } from `@wordpress/components`; function Example() { return ( <View> Code is Poetry </View> ); } ```
Imports
import { View } from "@wordpress/components";
Default story ok
const Default = () => {
    return <View>An example tip</View>;
};

VisuallyHidden

components-visuallyhidden · ../packages/components/src/visually-hidden/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { VisuallyHidden } from "@wordpress/components";
Default story ok
const Default = () => <>
    <VisuallyHidden as="span">This should not show.
                </VisuallyHidden>
    <div>This text will{ ' ' }
        <VisuallyHidden as="span">but not inline{ ' ' }
        </VisuallyHidden>{ ' ' }always show.
                </div>
</>;
With Forwarded Props story ok
const WithForwardedProps = () => <>Additional props can be passed to VisuallyHidden and are forwarded to
            the rendered element.{ ' ' }
    <VisuallyHidden as="span" data-id="test">Check out my data attribute!{ ' ' }
    </VisuallyHidden>Inspect the HTML to see!
        </>;
With Additional Class Names story ok
const WithAdditionalClassNames = () => <>Additional class names passed to VisuallyHidden extend the component
            class name.{ ' ' }
    <VisuallyHidden as="label" className="test-input">Check out my class!{ ' ' }
    </VisuallyHidden>Inspect the HTML to see!
        </>;

VisuallyHidden

design-system-components-visuallyhidden · ../packages/ui/src/visually-hidden/stories/index.story.tsx
Visually hides content while keeping it accessible to screen readers. Useful when providing context that's only meaningful to assistive technology.
Prop types 3 prop types
Component: ../packages/ui/src/visually-hidden/visually-hidden.tsx::VisuallyHidden
Props:
/**
 * The content to be rendered inside the component.
 */
children?: React.ReactNode

/**
 * CSS class name to apply to the component.
 */
className?: string

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: | ComponentRenderFn< HTMLAttributesWithRef >
| React.ReactElement< Record< string, unknown > >
Imports
import { VisuallyHidden } from "@wordpress/ui";
Default story ok
const Default = () => (
    <>
        <VisuallyHidden>This should not show.</VisuallyHidden>
        <div>
            This text will <VisuallyHidden>but not inline </VisuallyHidden>
            always show.
        </div>
    </>
);

VStack

components-vstack · ../packages/components/src/v-stack/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { View, VStack } from "@wordpress/components";
Default story ok
const Default = ( props ) => {
	return (
		<VStack
			{ ...props }
			style={ { background: '#eee', minHeight: '200px' } }
		>
			{ [ 'One', 'Two', 'Three', 'Four', 'Five' ].map( ( text ) => (
				<View key={ text } style={ { background: '#b9f9ff' } }>
					{ text }
				</View>
			) ) }
		</VStack>
	);
};

Warning

blockeditor-warning · ../packages/block-editor/src/components/warning/stories/index.story.jsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Button } from "@wordpress/components";
import { Warning } from "@wordpress/block-editor";
Default story ok
const Default = () => <Warning>{__( 'This block ran into an issue.' )}</Warning>;
With Actions story ok
const WithActions = () => <Warning
    actions={[
        <Button key="fix-issue" __next40pxDefaultSize variant="primary">
            { __( 'Fix issue' ) }
        </Button>,
    ]} />;
With Secondary Actions story ok
const WithSecondaryActions = () => <Warning
    secondaryActions={[
        { title: __( 'Get help' ) },
        { title: __( 'Remove block' ) },
    ]} />;

WidthHeightTool

blockeditor-dimensionstool-widthheighttool · ../packages/block-editor/src/components/dimensions-tool/stories/width-height-tool.story.jsx
Component that renders controls to edit the dimensions of an image or container.
param: {WidthHeightToolProps} props The component props.return: {React.ReactElement} The width and height tool.
Prop types 3 prop types
Component: ../packages/block-editor/src/components/dimensions-tool/width-height-tool.js::default
Props:
isShownByDefault?: any = true

onChange?: any = () => {}

value?: any = {}
Imports
import { Panel, __experimentalToolsPanel as ToolsPanel } from "@wordpress/components";
import { WidthHeightTool } from "@wordpress/block-editor";
Default story ok
const Default = ( { panelId, onChange: onChangeProp, ...props } ) => {
	const [ value, setValue ] = useState( EMPTY_OBJECT );
	const resetAll = () => {
		setValue( EMPTY_OBJECT );
		onChangeProp( EMPTY_OBJECT );
	};
	return (
		<Panel>
			<ToolsPanel
				label="Width & Height"
				panelId={ panelId }
				resetAll={ resetAll }
			>
				<WidthHeightTool
					panelId={ panelId }
					onChange={ ( nextValue ) => {
						setValue( nextValue );
						onChangeProp( nextValue );
					} }
					value={ value }
					{ ...props }
				/>
			</ToolsPanel>
		</Panel>
	);
};

WritingModeControl

blockeditor-writingmodecontrol · ../packages/block-editor/src/components/writing-mode-control/stories/index.story.jsx
Control to facilitate writing mode selections.
param: {Object} props Component props.param: {string} props.className Class name to add to the control.param: {string} props.value Currently selected writing mode.param: {Function} props.onChange Handles change in the writing mode selection.return: {Element} Writing Mode control.
Imports
import { WritingModeControl } from "@wordpress/block-editor";
Default story ok
const Default = () => {
    const [ value, setValue ] = useState();

    return (
        <WritingModeControl
            onChange={ ( ...changeArgs ) => {
                onChange( ...changeArgs );
                setValue( ...changeArgs );
            } }
            value={ value } />
    );
};

ZStack

components-zstack · ../packages/components/src/z-stack/stories/index.story.tsx
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Elevation, View, ZStack } from "@wordpress/components";
Default story ok
const Default = () => {
    return (
        <ZStack offset={20}>
            <Avatar backgroundColor="#444" />
            <Avatar backgroundColor="#777" />
            <Avatar backgroundColor="#aaa" />
            <Avatar backgroundColor="#fff" />
        </ZStack>
    );
};

ColorGen

design-system-theme-theme-provider-color-scales · ../packages/theme/src/color-ramps/stories/index.story.tsx
Prop type error
No component file found for the "ColorGen" component.
  19 | };
  20 |
> 21 | const meta: Meta< typeof ColorGen > = {
     | ^
  22 | 	title: 'Design System/Theme/Theme Provider/Color Scales',
  23 | 	component: ColorGen,
  24 | 	argTypes: {

../packages/theme/src/color-ramps/stories/index.story.tsx:
/**
 * External dependencies
 */
import type { Meta, StoryObj } from '@storybook/react-vite';

/**
 * Internal dependencies
 */
import { RampTable } from './ramp-table';
import { buildBgRamp, buildAccentRamp, checkAccessibleCombinations } from '..';
import { DEFAULT_SEED_COLORS } from '../lib/constants';

const ColorGen = ( props: {
	background: string;
	primary: string;
	children: React.ReactNode;
} ) => {
	return <div>{ props.children }</div>;
};

const meta: Meta< typeof ColorGen > = {
	title: 'Design System/Theme/Theme Provider/Color Scales',
	component: ColorGen,
	argTypes: {
		background: {
			control: { type: 'color', presetColors: [ '#1e1e1e', '#f8f8f8' ] },
		},
		primary: {
			control: {
				type: 'color',
				presetColors: [ '#3858e9', '#069e08', '#873eff' ],
			},
		},
	},
	parameters: {
		controls: { expanded: true },
		docs: { canvas: { sourceState: 'shown' } },
	},
};
export default meta;

export const Default: StoryObj< typeof ColorGen > = {
	render: ( args ) => {
		const bgSeed = args.background ?? DEFAULT_SEED_COLORS.bg;
		const primarySeed = args.primary ?? DEFAULT_SEED_COLORS.primary;
		const bgRamp = buildBgRamp( bgSeed );

		const bgRampObj = {
			seed: {
				name: 'surface2' as const,
				value: bgSeed,
			},
			ramp: bgRamp.ramp,
		};

		const primaryRampObj = {
			seed: {
				name: 'bgFill1' as const,
				value: primarySeed,
			},
			ramp: buildAccentRamp( primarySeed, bgRamp ).ramp,
		};
		const infoRampObj = {
			seed: {
				name: 'bgFill1' as const,
				value: DEFAULT_SEED_COLORS.info,
			},
			ramp: buildAccentRamp( DEFAULT_SEED_COLORS.info, bgRamp ).ramp,
		};
		const successRampObj = {
			seed: {
				name: 'bgFill1' as const,
				value: DEFAULT_SEED_COLORS.success,
			},
			ramp: buildAccentRamp( DEFAULT_SEED_COLORS.success, bgRamp ).ramp,
		};
		const warningRampObj = {
			seed: {
				name: 'bgFill1' as const,
				value: DEFAULT_SEED_COLORS.warning,
			},
			ramp: buildAccentRamp( DEFAULT_SEED_COLORS.warning, bgRamp ).ramp,
		};
		const cautionRampObj = {
			seed: {
				name: 'bgFill1' as const,
				value: DEFAULT_SEED_COLORS.caution,
			},
			ramp: buildAccentRamp( DEFAULT_SEED_COLORS.caution, bgRamp ).ramp,
		};
		const errorRampObj = {
			seed: {
				name: 'bgFill1' as const,
				value: DEFAULT_SEED_COLORS.error,
			},
			ramp: buildAccentRamp( DEFAULT_SEED_COLORS.error, bgRamp ).ramp,
		};

		const unmetTargets = checkAccessibleCombinations( {
			bgRamp,
		} );

		return (
			<div
				style={ {
					display: 'flex',
					flexDirection: 'column',
					gap: '32px',
				} }
			>
				<RampTable
					ramps={ [
						bgRampObj,
						primaryRampObj,
						infoRampObj,
						successRampObj,
						warningRampObj,
						cautionRampObj,
						errorRampObj,
					] }
				/>

				{ unmetTargets.length === 0 ? (
					<p>All accessibility targets met</p>
				) : (
					<ul>
						{ unmetTargets.map(
							(
								{
									bgName,
									bgColor,
									fgName,
									fgColor,
									unmetContrast,
									achievedContrast,
								},
								i
							) => (
								<li key={ i }>
									{ fgName } (
									<span
										style={ {
											width: 20,
											height: 20,
											backgroundColor: fgColor,
											display: 'inline-block',
										} }
									/>
									{ fgColor }) over { bgName } (
									<span
										style={ {
											width: 20,
											height: 20,
											backgroundColor: bgColor,
											display: 'inline-block',
										} }
									/>
									{ bgColor }) did not meet { unmetContrast },
									achieved just { achievedContrast }
								</li>
							)
						) }
					</ul>
				) }
			</div>
		);
	},
	args: {},
};

export const SampleCombinations: StoryObj< typeof ColorGen > = {
	render: () => {
		const combinations = [
			// WordPress (light / dark)
			{
				background: '#f8f8f8',
				primary: '#3858e9',
			},
			{
				background: '#1e1e1e',
				primary: '#3858e9',
			},
			// WP Classic
			{
				background: '#1d2327',
				primary: '#2271b1',
			},
			// WP Light
			{
				background: '#e5e5e5',
				primary: '#d64e07',
			},
			// WP Blue
			{
				background: '#096484',
				primary: '#52accc',
			},
			// WP Coffee
			{
				background: '#46403c',
				primary: '#c7a589',
			},
			// WP Ectoplasm
			{
				background: '#413256',
				primary: '#a3b745',
			},
			// WP Ocean
			{
				background: '#627c83',
				primary: '#9ebaa0',
			},
			// Sunrise
			{
				background: '#b43c38',
				primary: '#dd823b',
			},
		];

		const ramps = combinations.map( ( { background, primary } ) => {
			const bgRamp = buildBgRamp( background );

			const bgRampObj = {
				seed: {
					name: 'surface2' as const,
					value: background,
				},
				ramp: bgRamp.ramp,
				warnings: bgRamp.warnings,
			};

			const primaryRamp = buildAccentRamp( primary, bgRamp );
			const primaryRampObj = {
				seed: {
					name: 'bgFill1' as const,
					value: primary,
				},
				ramp: primaryRamp.ramp,
				warnings: primaryRamp.warnings,
			};

			return [ bgRampObj, primaryRampObj ];
		} );

		return (
			<div
				style={ { display: 'flex', flexDirection: 'column', gap: 16 } }
			>
				{ ramps.map( ( r, i ) => (
					<RampTable key={ i } ramps={ r } />
				) ) }
			</div>
		);
	},
	argTypes: {
		background: {
			control: false,
		},
		primary: {
			control: false,
		},
	},
};
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { RampTable } from "@wordpress/theme";
Default story ok
const Default = ( args ) => {
    const bgSeed = args.background ?? DEFAULT_SEED_COLORS.bg;
    const primarySeed = args.primary ?? DEFAULT_SEED_COLORS.primary;
    const bgRamp = buildBgRamp( bgSeed );

    const bgRampObj = {
        seed: {
            name: 'surface2' as const,
            value: bgSeed,
        },
        ramp: bgRamp.ramp,
    };

    const primaryRampObj = {
        seed: {
            name: 'bgFill1' as const,
            value: primarySeed,
        },
        ramp: buildAccentRamp( primarySeed, bgRamp ).ramp,
    };
    const infoRampObj = {
        seed: {
            name: 'bgFill1' as const,
            value: DEFAULT_SEED_COLORS.info,
        },
        ramp: buildAccentRamp( DEFAULT_SEED_COLORS.info, bgRamp ).ramp,
    };
    const successRampObj = {
        seed: {
            name: 'bgFill1' as const,
            value: DEFAULT_SEED_COLORS.success,
        },
        ramp: buildAccentRamp( DEFAULT_SEED_COLORS.success, bgRamp ).ramp,
    };
    const warningRampObj = {
        seed: {
            name: 'bgFill1' as const,
            value: DEFAULT_SEED_COLORS.warning,
        },
        ramp: buildAccentRamp( DEFAULT_SEED_COLORS.warning, bgRamp ).ramp,
    };
    const cautionRampObj = {
        seed: {
            name: 'bgFill1' as const,
            value: DEFAULT_SEED_COLORS.caution,
        },
        ramp: buildAccentRamp( DEFAULT_SEED_COLORS.caution, bgRamp ).ramp,
    };
    const errorRampObj = {
        seed: {
            name: 'bgFill1' as const,
            value: DEFAULT_SEED_COLORS.error,
        },
        ramp: buildAccentRamp( DEFAULT_SEED_COLORS.error, bgRamp ).ramp,
    };

    const unmetTargets = checkAccessibleCombinations( {
        bgRamp,
    } );

    return (
        <div
            style={ {
                display: 'flex',
                flexDirection: 'column',
                gap: '32px',
            } }
        >
            <RampTable
                ramps={ [
                    bgRampObj,
                    primaryRampObj,
                    infoRampObj,
                    successRampObj,
                    warningRampObj,
                    cautionRampObj,
                    errorRampObj,
                ] }
            />

            { unmetTargets.length === 0 ? (
                <p>All accessibility targets met</p>
            ) : (
                <ul>
                    { unmetTargets.map(
                        (
                            {
                                bgName,
                                bgColor,
                                fgName,
                                fgColor,
                                unmetContrast,
                                achievedContrast,
                            },
                            i
                        ) => (
                            <li key={ i }>
                                { fgName } (
                                <span
                                    style={ {
                                        width: 20,
                                        height: 20,
                                        backgroundColor: fgColor,
                                        display: 'inline-block',
                                    } }
                                />
                                { fgColor }) over { bgName } (
                                <span
                                    style={ {
                                        width: 20,
                                        height: 20,
                                        backgroundColor: bgColor,
                                        display: 'inline-block',
                                    } }
                                />
                                { bgColor }) did not meet { unmetContrast },
                                achieved just { achievedContrast }
                            </li>
                        )
                    ) }
                </ul>
            ) }
        </div>
    );
};
Sample Combinations story ok
const SampleCombinations = () => {
    const combinations = [
        // WordPress (light / dark)
        {
            background: '#f8f8f8',
            primary: '#3858e9',
        },
        {
            background: '#1e1e1e',
            primary: '#3858e9',
        },
        // WP Classic
        {
            background: '#1d2327',
            primary: '#2271b1',
        },
        // WP Light
        {
            background: '#e5e5e5',
            primary: '#d64e07',
        },
        // WP Blue
        {
            background: '#096484',
            primary: '#52accc',
        },
        // WP Coffee
        {
            background: '#46403c',
            primary: '#c7a589',
        },
        // WP Ectoplasm
        {
            background: '#413256',
            primary: '#a3b745',
        },
        // WP Ocean
        {
            background: '#627c83',
            primary: '#9ebaa0',
        },
        // Sunrise
        {
            background: '#b43c38',
            primary: '#dd823b',
        },
    ];

    const ramps = combinations.map( ( { background, primary } ) => {
        const bgRamp = buildBgRamp( background );

        const bgRampObj = {
            seed: {
                name: 'surface2' as const,
                value: background,
            },
            ramp: bgRamp.ramp,
            warnings: bgRamp.warnings,
        };

        const primaryRamp = buildAccentRamp( primary, bgRamp );
        const primaryRampObj = {
            seed: {
                name: 'bgFill1' as const,
                value: primary,
            },
            ramp: primaryRamp.ramp,
            warnings: primaryRamp.warnings,
        };

        return [ bgRampObj, primaryRampObj ];
    } );

    return (
        <div
            style={ { display: 'flex', flexDirection: 'column', gap: 16 } }
        >
            { ramps.map( ( r, i ) => (
                <RampTable key={ i } ramps={ r } />
            ) ) }
        </div>
    );
};

LayoutCardSaveExample

design-system-patterns-save-submit · ./stories/design-system/patterns/save-and-submit.story.tsx
Prop type error
No component file found for the "LayoutCardSaveExample" component.
  51 | };
  52 |
> 53 | const meta: Meta< typeof LayoutCardSaveExample > = {
     | ^
  54 | 	title: 'Design System/Patterns/Save & Submit',
  55 | 	component: LayoutCardSaveExample,
  56 | 	parameters: {

./stories/design-system/patterns/save-and-submit.mdx:
import type { Meta, StoryObj } from '@storybook/react-vite';
import { Button, Card, CardBody } from '@wordpress/components';
import { DataForm } from '@wordpress/dataviews';
import { useState } from '@wordpress/element';

const LayoutCardSaveExample = () => {
	const [ data, setData ] = useState( { title: '' } );

	return (
		<div style={ { maxWidth: '480px' } }>
			<Card
				size={ {
					blockStart: 'medium',
					blockEnd: 'medium',
					inlineStart: 'medium',
					inlineEnd: 'medium',
				} }
			>
				<CardBody>
					<DataForm
						data={ data }
						fields={ [
							{
								id: 'title',
								label: 'Title',
								type: 'text',
							},
						] }
						form={ {
							layout: { type: 'regular' },
							fields: [ 'title' ],
						} }
						onChange={ ( edits ) =>
							setData( ( previous ) => ( {
								...previous,
								...edits,
							} ) )
						}
					/>
					<Button
						variant="primary"
						isBusy
						style={ { marginTop: '16px' } }
					>
						Save
					</Button>
				</CardBody>
			</Card>
		</div>
	);
};

const meta: Meta< typeof LayoutCardSaveExample > = {
	title: 'Design System/Patterns/Save & Submit',
	component: LayoutCardSaveExample,
	parameters: {
		controls: { disable: true },
	},
	tags: [ '!dev' /* Hide individual story pages from sidebar */ ],
};

export default meta;

type Story = StoryObj< typeof LayoutCardSaveExample >;

export const SaveFormLayoutCard: Story = {
	name: 'Save form layout card',
	render: () => <LayoutCardSaveExample />,
};
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Button, Card, CardBody } from "@wordpress/components";
import { DataForm } from "@wordpress/dataviews";
Save form layout card story ok
const SaveFormLayoutCard = () => <LayoutCardSaveExample />;

ThemeProvider

design-system-theme-theme-provider-example-application · ./stories/design-system/theme-example-application.story.tsx
Prop type error
No component file found for the "ThemeProvider" component.
  30 | ];
  31 |
> 32 | const meta: Meta< typeof ThemeProvider > = {
     | ^
  33 | 	title: 'Design System/Theme/Theme Provider/Example Application',
  34 | 	component: ThemeProvider,
  35 | 	parameters: {

./stories/design-system/theme-example-application.story.tsx:
import type { Meta, StoryObj } from '@storybook/react-vite';
import { useState } from '@wordpress/element';
import { privateApis as themeApis } from '@wordpress/theme';
import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis';
import {
	Badge,
	Button,
	Card,
	Link,
	Notice,
	Stack,
	Tabs,
	Text,
} from '@wordpress/ui';

const { unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules(
	'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.',
	'@wordpress/theme'
);

const { ThemeProvider } = unlock( themeApis );

const sidebarNavItems = [
	'Dashboard',
	'Posts',
	'Pages',
	'Comments',
	'Appearance',
	'Settings',
];

const meta: Meta< typeof ThemeProvider > = {
	title: 'Design System/Theme/Theme Provider/Example Application',
	component: ThemeProvider,
	parameters: {
		controls: { expanded: true },
		docs: { canvas: { sourceState: 'hidden' } },
	},
};
export default meta;

/**
 * A mock application page demonstrating how `ThemeProvider` affects multiple
 * `@wordpress/ui` components in concert. Use the inline controls to adjust
 * the `primary` seed color, `bg` seed color, and `density`, and observe how
 * every surface, text element, and interactive control adapts accordingly.
 */
export const ExampleApplication: StoryObj< typeof ThemeProvider > = {
	render: () => {
		const [ primary, setPrimary ] = useState< string | undefined >();
		const [ bg, setBg ] = useState< string | undefined >();
		const [ density, setDensity ] = useState<
			'default' | 'compact' | 'comfortable' | undefined
		>();

		return (
			<div>
				<div
					style={ {
						display: 'flex',
						alignItems: 'center',
						gap: '16px',
						padding: '12px 16px',
						marginBlockEnd: '16px',
						borderRadius: '8px',
						background: '#f0f0f0',
						fontSize: '13px',
						flexWrap: 'wrap',
					} }
				>
					{ /* eslint-disable jsx-a11y/label-has-associated-control */ }
					<label
						style={ {
							display: 'inline-flex',
							alignItems: 'center',
							gap: '6px',
						} }
					>
						Primary
						<input
							type="color"
							value={ primary ?? '#3858e9' }
							onChange={ ( e ) => setPrimary( e.target.value ) }
						/>
					</label>
					<label
						style={ {
							display: 'inline-flex',
							alignItems: 'center',
							gap: '6px',
						} }
					>
						Background
						<input
							type="color"
							value={ bg ?? '#ffffff' }
							onChange={ ( e ) => setBg( e.target.value ) }
						/>
					</label>
					<label
						style={ {
							display: 'inline-flex',
							alignItems: 'center',
							gap: '6px',
						} }
					>
						Density
						<select
							value={ density ?? '' }
							onChange={ ( e ) =>
								setDensity(
									( e.target.value || undefined ) as
										| 'default'
										| 'compact'
										| 'comfortable'
										| undefined
								)
							}
						>
							<option value="">Default</option>
							<option value="compact">Compact</option>
							<option value="comfortable">Comfortable</option>
						</select>
					</label>
					{ /* eslint-enable jsx-a11y/label-has-associated-control */ }
				</div>
				<ThemeProvider
					color={ { primary, bg } }
					density={ density }
					isRoot
				>
					<div
						style={ {
							display: 'grid',
							gridTemplateColumns: '200px 1fr',
							minHeight: '500px',
							color: 'var(--wpds-color-fg-content-neutral)',
						} }
					>
						{ /* Sidebar */ }
						<div
							style={ {
								backgroundColor:
									'var(--wpds-color-bg-surface-neutral-weak)',
								padding:
									'var(--wpds-dimension-padding-xl) var(--wpds-dimension-padding-lg)',
							} }
						>
							<Text
								variant="heading-sm"
								render={ <h2 /> }
								style={ {
									marginBlockEnd:
										'var(--wpds-dimension-gap-xl)',
								} }
							>
								My App
							</Text>
							<nav>
								<Stack
									direction="column"
									gap="xs"
									render={ <ul /> }
									style={ {
										listStyle: 'none',
										margin: 0,
										padding: 0,
									} }
								>
									{ sidebarNavItems.map( ( item ) => (
										<li key={ item }>
											<Text variant="body-md">
												{ item }
											</Text>
										</li>
									) ) }
								</Stack>
							</nav>
						</div>

						{ /* Page content (header + content area) */ }
						<div
							style={ {
								backgroundColor:
									'var(--wpds-color-bg-surface-neutral-weak)',
								padding: 'var(--wpds-dimension-padding-lg)',
							} }
						>
							<div
								style={ {
									display: 'flex',
									flexDirection: 'column',
									borderRadius:
										'var(--wpds-border-radius-lg)',
									border: '1px solid var(--wpds-color-stroke-surface-neutral-weak)',
									overflow: 'hidden',
									height: '100%',
								} }
							>
								{ /* Header */ }
								<div
									style={ {
										backgroundColor:
											'var(--wpds-color-bg-surface-neutral-strong)',
										padding:
											'var(--wpds-dimension-padding-xl)',
										display: 'flex',
										alignItems: 'center',
										justifyContent: 'space-between',
										gap: 'var(--wpds-dimension-gap-lg)',
										borderBlockEnd:
											'1px solid var(--wpds-color-stroke-surface-neutral-weak)',
									} }
								>
									<div
										style={ {
											display: 'flex',
											alignItems: 'center',
											gap: 'var(--wpds-dimension-gap-md)',
										} }
									>
										<Text
											variant="heading-lg"
											render={ <h1 /> }
											style={ {
												margin: 0,
											} }
										>
											Settings
										</Text>
										<Badge intent="informational">
											Beta
										</Badge>
									</div>
									<Button
										variant="solid"
										tone="brand"
										size="compact"
									>
										Save changes
									</Button>
								</div>

								{ /* Content area */ }
								<div
									style={ {
										backgroundColor:
											'var(--wpds-color-bg-surface-neutral)',
										padding:
											'var(--wpds-dimension-padding-xl)',
										flexGrow: 1,
									} }
								>
									<Stack
										direction="column"
										gap="xl"
										style={ {
											maxWidth: '640px',
											marginInline: 'auto',
										} }
									>
										<Notice.Root intent="info">
											<Notice.Title>
												Welcome to your new site
											</Notice.Title>
											<Notice.Description>
												Complete the steps below to
												finish setting up.
											</Notice.Description>
										</Notice.Root>

										{ /* Card 1: General */ }
										<Card.Root>
											<Card.Header>
												<Card.Title>General</Card.Title>
											</Card.Header>
											<Card.Content>
												<Stack
													direction="column"
													gap="md"
												>
													<Text>
														Configure the basic
														settings for your site.
														You can update your{ ' ' }
														<Link href="#">
															site title
														</Link>
														, tagline, and{ ' ' }
														<Link href="#">
															admin email address
														</Link>{ ' ' }
														at any time.
													</Text>
													<Text>
														For more advanced
														options, visit the{ ' ' }
														<Link href="#">
															developer
															documentation
														</Link>
														.
													</Text>
												</Stack>
											</Card.Content>
										</Card.Root>

										{ /* Card 2: Display */ }
										<Card.Root>
											<Card.Header>
												<Card.Title>Display</Card.Title>
											</Card.Header>
											<Card.Content>
												<Tabs.Root defaultValue="appearance">
													<Tabs.List variant="minimal">
														<Tabs.Tab value="appearance">
															Appearance
														</Tabs.Tab>
														<Tabs.Tab value="layout">
															Layout
														</Tabs.Tab>
														<Tabs.Tab value="accessibility">
															Accessibility
														</Tabs.Tab>
													</Tabs.List>
													<Tabs.Panel value="appearance">
														<Text
															style={ {
																paddingBlockStart:
																	'var(--wpds-dimension-padding-lg)',
															} }
														>
															Control how your
															site looks to
															visitors. Adjust{ ' ' }
															<Link href="#">
																typography
															</Link>
															,{ ' ' }
															<Link href="#">
																colors
															</Link>
															, and spacing to
															match your brand.
														</Text>
													</Tabs.Panel>
													<Tabs.Panel value="layout">
														<Text
															style={ {
																paddingBlockStart:
																	'var(--wpds-dimension-padding-lg)',
															} }
														>
															Choose a layout
															structure for your
															pages. Options
															include full-width,
															boxed, and{ ' ' }
															<Link href="#">
																custom layouts
															</Link>
															.
														</Text>
													</Tabs.Panel>
													<Tabs.Panel value="accessibility">
														<Text
															style={ {
																paddingBlockStart:
																	'var(--wpds-dimension-padding-lg)',
															} }
														>
															Review your
															site&apos;s{ ' ' }
															<Link href="#">
																accessibility
																settings
															</Link>{ ' ' }
															to ensure it meets
															WCAG guidelines.
														</Text>
													</Tabs.Panel>
												</Tabs.Root>
											</Card.Content>
										</Card.Root>
									</Stack>
								</div>
							</div>
						</div>
					</div>
				</ThemeProvider>
			</div>
		);
	},
	parameters: {
		controls: { disable: true },
	},
};
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Badge, Button, Card, Link, Notice, Stack, Tabs, Text } from "@wordpress/ui";
Example Application story ok
A mock application page demonstrating how `ThemeProvider` affects multiple `@wordpress/ui` components in concert. Use the inline controls to adjust the `primary` seed color, `bg` seed color, and `density`, and observe how every surface, text element, and interactive control adapts accordingly.
const ExampleApplication = () => {
    const [ primary, setPrimary ] = useState< string | undefined >();
    const [ bg, setBg ] = useState< string | undefined >();
    const [ density, setDensity ] = useState<
        'default' | 'compact' | 'comfortable' | undefined
    >();

    return (
        <div>
            <div
                style={ {
                    display: 'flex',
                    alignItems: 'center',
                    gap: '16px',
                    padding: '12px 16px',
                    marginBlockEnd: '16px',
                    borderRadius: '8px',
                    background: '#f0f0f0',
                    fontSize: '13px',
                    flexWrap: 'wrap',
                } }
            >
                { /* eslint-disable jsx-a11y/label-has-associated-control */ }
                <label
                    style={ {
                        display: 'inline-flex',
                        alignItems: 'center',
                        gap: '6px',
                    } }
                >
                    Primary
                    <input
                        type="color"
                        value={ primary ?? '#3858e9' }
                        onChange={ ( e ) => setPrimary( e.target.value ) }
                    />
                </label>
                <label
                    style={ {
                        display: 'inline-flex',
                        alignItems: 'center',
                        gap: '6px',
                    } }
                >
                    Background
                    <input
                        type="color"
                        value={ bg ?? '#ffffff' }
                        onChange={ ( e ) => setBg( e.target.value ) }
                    />
                </label>
                <label
                    style={ {
                        display: 'inline-flex',
                        alignItems: 'center',
                        gap: '6px',
                    } }
                >
                    Density
                    <select
                        value={ density ?? '' }
                        onChange={ ( e ) =>
                            setDensity(
                                ( e.target.value || undefined ) as
                                    | 'default'
                                    | 'compact'
                                    | 'comfortable'
                                    | undefined
                            )
                        }
                    >
                        <option value="">Default</option>
                        <option value="compact">Compact</option>
                        <option value="comfortable">Comfortable</option>
                    </select>
                </label>
                { /* eslint-enable jsx-a11y/label-has-associated-control */ }
            </div>
            <ThemeProvider
                color={ { primary, bg } }
                density={ density }
                isRoot
            >
                <div
                    style={ {
                        display: 'grid',
                        gridTemplateColumns: '200px 1fr',
                        minHeight: '500px',
                        color: 'var(--wpds-color-fg-content-neutral)',
                    } }
                >
                    { /* Sidebar */ }
                    <div
                        style={ {
                            backgroundColor:
                                'var(--wpds-color-bg-surface-neutral-weak)',
                            padding:
                                'var(--wpds-dimension-padding-xl) var(--wpds-dimension-padding-lg)',
                        } }
                    >
                        <Text
                            variant="heading-sm"
                            render={ <h2 /> }
                            style={ {
                                marginBlockEnd:
                                    'var(--wpds-dimension-gap-xl)',
                            } }
                        >
                            My App
                        </Text>
                        <nav>
                            <Stack
                                direction="column"
                                gap="xs"
                                render={ <ul /> }
                                style={ {
                                    listStyle: 'none',
                                    margin: 0,
                                    padding: 0,
                                } }
                            >
                                { sidebarNavItems.map( ( item ) => (
                                    <li key={ item }>
                                        <Text variant="body-md">
                                            { item }
                                        </Text>
                                    </li>
                                ) ) }
                            </Stack>
                        </nav>
                    </div>

                    { /* Page content (header + content area) */ }
                    <div
                        style={ {
                            backgroundColor:
                                'var(--wpds-color-bg-surface-neutral-weak)',
                            padding: 'var(--wpds-dimension-padding-lg)',
                        } }
                    >
                        <div
                            style={ {
                                display: 'flex',
                                flexDirection: 'column',
                                borderRadius:
                                    'var(--wpds-border-radius-lg)',
                                border: '1px solid var(--wpds-color-stroke-surface-neutral-weak)',
                                overflow: 'hidden',
                                height: '100%',
                            } }
                        >
                            { /* Header */ }
                            <div
                                style={ {
                                    backgroundColor:
                                        'var(--wpds-color-bg-surface-neutral-strong)',
                                    padding:
                                        'var(--wpds-dimension-padding-xl)',
                                    display: 'flex',
                                    alignItems: 'center',
                                    justifyContent: 'space-between',
                                    gap: 'var(--wpds-dimension-gap-lg)',
                                    borderBlockEnd:
                                        '1px solid var(--wpds-color-stroke-surface-neutral-weak)',
                                } }
                            >
                                <div
                                    style={ {
                                        display: 'flex',
                                        alignItems: 'center',
                                        gap: 'var(--wpds-dimension-gap-md)',
                                    } }
                                >
                                    <Text
                                        variant="heading-lg"
                                        render={ <h1 /> }
                                        style={ {
                                            margin: 0,
                                        } }
                                    >
                                        Settings
                                    </Text>
                                    <Badge intent="informational">
                                        Beta
                                    </Badge>
                                </div>
                                <Button
                                    variant="solid"
                                    tone="brand"
                                    size="compact"
                                >
                                    Save changes
                                </Button>
                            </div>

                            { /* Content area */ }
                            <div
                                style={ {
                                    backgroundColor:
                                        'var(--wpds-color-bg-surface-neutral)',
                                    padding:
                                        'var(--wpds-dimension-padding-xl)',
                                    flexGrow: 1,
                                } }
                            >
                                <Stack
                                    direction="column"
                                    gap="xl"
                                    style={ {
                                        maxWidth: '640px',
                                        marginInline: 'auto',
                                    } }
                                >
                                    <Notice.Root intent="info">
                                        <Notice.Title>
                                            Welcome to your new site
                                        </Notice.Title>
                                        <Notice.Description>
                                            Complete the steps below to
                                            finish setting up.
                                        </Notice.Description>
                                    </Notice.Root>

                                    { /* Card 1: General */ }
                                    <Card.Root>
                                        <Card.Header>
                                            <Card.Title>General</Card.Title>
                                        </Card.Header>
                                        <Card.Content>
                                            <Stack
                                                direction="column"
                                                gap="md"
                                            >
                                                <Text>
                                                    Configure the basic
                                                    settings for your site.
                                                    You can update your{ ' ' }
                                                    <Link href="#">
                                                        site title
                                                    </Link>
                                                    , tagline, and{ ' ' }
                                                    <Link href="#">
                                                        admin email address
                                                    </Link>{ ' ' }
                                                    at any time.
                                                </Text>
                                                <Text>
                                                    For more advanced
                                                    options, visit the{ ' ' }
                                                    <Link href="#">
                                                        developer
                                                        documentation
                                                    </Link>
                                                    .
                                                </Text>
                                            </Stack>
                                        </Card.Content>
                                    </Card.Root>

                                    { /* Card 2: Display */ }
                                    <Card.Root>
                                        <Card.Header>
                                            <Card.Title>Display</Card.Title>
                                        </Card.Header>
                                        <Card.Content>
                                            <Tabs.Root defaultValue="appearance">
                                                <Tabs.List variant="minimal">
                                                    <Tabs.Tab value="appearance">
                                                        Appearance
                                                    </Tabs.Tab>
                                                    <Tabs.Tab value="layout">
                                                        Layout
                                                    </Tabs.Tab>
                                                    <Tabs.Tab value="accessibility">
                                                        Accessibility
                                                    </Tabs.Tab>
                                                </Tabs.List>
                                                <Tabs.Panel value="appearance">
                                                    <Text
                                                        style={ {
                                                            paddingBlockStart:
                                                                'var(--wpds-dimension-padding-lg)',
                                                        } }
                                                    >
                                                        Control how your
                                                        site looks to
                                                        visitors. Adjust{ ' ' }
                                                        <Link href="#">
                                                            typography
                                                        </Link>
                                                        ,{ ' ' }
                                                        <Link href="#">
                                                            colors
                                                        </Link>
                                                        , and spacing to
                                                        match your brand.
                                                    </Text>
                                                </Tabs.Panel>
                                                <Tabs.Panel value="layout">
                                                    <Text
                                                        style={ {
                                                            paddingBlockStart:
                                                                'var(--wpds-dimension-padding-lg)',
                                                        } }
                                                    >
                                                        Choose a layout
                                                        structure for your
                                                        pages. Options
                                                        include full-width,
                                                        boxed, and{ ' ' }
                                                        <Link href="#">
                                                            custom layouts
                                                        </Link>
                                                        .
                                                    </Text>
                                                </Tabs.Panel>
                                                <Tabs.Panel value="accessibility">
                                                    <Text
                                                        style={ {
                                                            paddingBlockStart:
                                                                'var(--wpds-dimension-padding-lg)',
                                                        } }
                                                    >
                                                        Review your
                                                        site&apos;s{ ' ' }
                                                        <Link href="#">
                                                            accessibility
                                                            settings
                                                        </Link>{ ' ' }
                                                        to ensure it meets
                                                        WCAG guidelines.
                                                    </Text>
                                                </Tabs.Panel>
                                            </Tabs.Root>
                                        </Card.Content>
                                    </Card.Root>
                                </Stack>
                            </div>
                        </div>
                    </div>
                </div>
            </ThemeProvider>
        </div>
    );
};

Verifier

design-system-theme-theme-provider-brand-color-fallbacks · ../packages/theme/src/color-ramps/stories/brand-fallbacks.story.tsx
Prop type error
No component file found for the "Verifier" component.
  44 |  * schemes and observe how closely the fallbacks track the real values.
  45 |  */
> 46 | const meta: Meta< typeof Verifier > = {
     | ^
  47 | 	title: 'Design System/Theme/Theme Provider/Brand Color Fallbacks',
  48 | 	component: Verifier,
  49 | 	argTypes: {

../packages/theme/src/color-ramps/stories/brand-fallbacks.story.tsx:
import type { Meta, StoryObj } from '@storybook/react-vite';
import colorTokens from '../../prebuilt/ts/color-tokens';
import _tokenFallbacks from '../../prebuilt/js/design-token-fallbacks.mjs';
import { ThemeProvider } from '../../theme-provider';

const tokenFallbacks: Record< string, string > = _tokenFallbacks;

type BrandToken = {
	cssVarName: string;
	fallbackExpr: string;
};

function getBrandTokens(): BrandToken[] {
	const tokens: BrandToken[] = [];

	for ( const [ rampKey, tokenNames ] of Object.entries( colorTokens ) ) {
		if ( ! rampKey.startsWith( 'primary-' ) ) {
			continue;
		}

		for ( const tokenName of tokenNames ) {
			const cssVarName = `--wpds-color-${ tokenName }`;
			tokens.push( {
				cssVarName,
				fallbackExpr: tokenFallbacks[ cssVarName ] ?? '',
			} );
		}
	}

	return tokens.sort( ( a, b ) =>
		a.cssVarName.localeCompare( b.cssVarName )
	);
}

const brandTokens = getBrandTokens();

type VerifierProps = { adminThemeColor: string };
const Verifier: React.FC< VerifierProps > = () => null;

/**
 * Compares actual brand token values (computed by ThemeProvider using the full
 * ramp algorithm) against their `color-mix()` fallback approximations driven
 * by `--wp-admin-theme-color`. Use the color picker to switch admin color
 * schemes and observe how closely the fallbacks track the real values.
 */
const meta: Meta< typeof Verifier > = {
	title: 'Design System/Theme/Theme Provider/Brand Color Fallbacks',
	component: Verifier,
	argTypes: {
		adminThemeColor: {
			control: {
				type: 'color',
				presetColors: [
					'#3858e9', // modern
					'#0085ba', // light
					'#096484', // blue
					'#46403c', // coffee
					'#523f6d', // ectoplasm
					'#e14d43', // midnight
					'#627c83', // ocean
					'#dd823b', // sunrise
				],
			},
		},
	},
	parameters: {
		controls: { expanded: true },
	},
};
export default meta;

export const Default: StoryObj< typeof Verifier > = {
	render: ( { adminThemeColor } ) => (
		<div
			style={
				{
					'--wp-admin-theme-color': adminThemeColor,
					fontSize: 13,
				} as React.CSSProperties
			}
		>
			<p
				style={ {
					margin: '0 0 16px',
					color: '#757575',
					fontSize: 12,
				} }
			>
				<strong>Actual:</strong> real token value from ThemeProvider
				(ramp algorithm). <strong>Fallback:</strong> approximation via{ ' ' }
				<code>color-mix()</code> and <code>--wp-admin-theme-color</code>
				.
			</p>
			<ThemeProvider color={ { primary: adminThemeColor } }>
				<div
					style={ {
						display: 'grid',
						gridTemplateColumns: '40px 40px 1fr 1fr',
						gap: '4px 12px',
						alignItems: 'center',
					} }
				>
					<div style={ headerStyle }>Actual</div>
					<div style={ headerStyle }>Fallback</div>
					<div style={ headerStyle }>Token</div>
					<div style={ headerStyle }>Fallback expression</div>
					{ brandTokens.map( ( { cssVarName, fallbackExpr } ) => (
						<Row
							key={ cssVarName }
							cssVarName={ cssVarName }
							fallbackExpr={ fallbackExpr }
						/>
					) ) }
				</div>
			</ThemeProvider>
		</div>
	),
	args: {
		adminThemeColor: '#3858e9',
	},
};

const headerStyle: React.CSSProperties = {
	fontSize: 11,
	fontWeight: 600,
	color: '#757575',
	paddingBottom: 4,
	borderBottom: '1px solid #e0e0e0',
};

function Row( { cssVarName, fallbackExpr }: BrandToken ) {
	return (
		<>
			<Swatch
				color={ `var(${ cssVarName })` }
				title={ `${ cssVarName } (actual)` }
			/>
			<Swatch color={ fallbackExpr } title="Fallback (rendered)" />
			<code style={ { fontSize: 12 } }>{ cssVarName }</code>
			<code
				style={ {
					fontSize: 11,
					color: '#555',
					wordBreak: 'break-all',
				} }
			>
				{ fallbackExpr }
			</code>
		</>
	);
}

function Swatch( { color, title }: { color: string; title: string } ) {
	return (
		<div
			title={ title }
			style={ {
				backgroundColor: color,
				width: 40,
				height: 28,
				border: '1px solid rgba(0, 0, 0, 0.1)',
			} }
		/>
	);
}
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { ThemeProvider } from "@wordpress/theme";
Default story ok
const Default = ( { adminThemeColor } ) => (
    <div
        style={
            {
                '--wp-admin-theme-color': adminThemeColor,
                fontSize: 13,
            } as React.CSSProperties
        }
    >
        <p
            style={ {
                margin: '0 0 16px',
                color: '#757575',
                fontSize: 12,
            } }
        >
            <strong>Actual:</strong> real token value from ThemeProvider
            (ramp algorithm). <strong>Fallback:</strong> approximation via{ ' ' }
            <code>color-mix()</code> and <code>--wp-admin-theme-color</code>
            .
        </p>
        <ThemeProvider color={ { primary: adminThemeColor } }>
            <div
                style={ {
                    display: 'grid',
                    gridTemplateColumns: '40px 40px 1fr 1fr',
                    gap: '4px 12px',
                    alignItems: 'center',
                } }
            >
                <div style={ headerStyle }>Actual</div>
                <div style={ headerStyle }>Fallback</div>
                <div style={ headerStyle }>Token</div>
                <div style={ headerStyle }>Fallback expression</div>
                { brandTokens.map( ( { cssVarName, fallbackExpr } ) => (
                    <Row
                        key={ cssVarName }
                        cssVarName={ cssVarName }
                        fallbackExpr={ fallbackExpr }
                    />
                ) ) }
            </div>
        </ThemeProvider>
    </div>
);

Animate

components-animate · ../packages/components/src/animate/stories/index.story.tsx
Prop type error
File: /home/runner/work/gutenberg/gutenberg/packages/components/src/animate/index.tsx
Error:
No suitable component definition found.
You can debug your component file in this playground: https://react-docgen.dev/playground
Code:
/**
 * External dependencies
 */
import clsx from 'clsx';

/**
 * Internal dependencies
 */
import type { AnimateProps, GetAnimateOptions } from './types';

/**
 * @param type The animation type
 * @return Default origin
 */
function getDefaultOrigin( type?: GetAnimateOptions[ 'type' ] ) {
	return type === 'appear' ? 'top' : 'left';
}

/**
 * @param options
 *
 * @return ClassName that applies the animations
 */
export function getAnimateClassName( options: GetAnimateOptions ) {
	if ( options.type === 'loading' ) {
		return 'components-animate__loading';
	}

	const { type, origin = getDefaultOrigin( type ) } = options;

	if ( type === 'appear' ) {
		const [ yAxis, xAxis = 'center' ] = origin.split( ' ' );
		return clsx( 'components-animate__appear', {
			[ 'is-from-' + xAxis ]: xAxis !== 'center',
			[ 'is-from-' + yAxis ]: yAxis !== 'middle',
		} );
	}

	if ( type === 'slide-in' ) {
		return clsx( 'components-animate__slide-in', 'is-from-' + origin );
	}

	return undefined;
}

/**
 * Simple interface to introduce animations to components.
 *
 * ```jsx
 * import { Animate, Notice } from '@wordpress/components';
 *
 * const MyAnimatedNotice = () => (
 * 	<Animate type="slide-in" options={ { origin: 'top' } }>
 * 		{ ( { className } ) => (
 * 			<Notice className={ className } status="success">
 * 				<p>Animation finished.</p>
 * 			</Notice>
 * 		) }
 * 	</Animate>
 * );
 * ```
 */
export function Animate( { type, options = {}, children }: AnimateProps ) {
	return children( {
		className: getAnimateClassName( {
			type,
			...options,
		} as GetAnimateOptions ),
	} );
}

export default Animate;
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Animate, Notice } from "@wordpress/components";
Default story ok
const Default = ( props ) => (
	<Animate { ...props } />
);
Appear Top Left story ok
const AppearTopLeft = ( props ) => (
	<Animate { ...props } />
);
Appear Top Right story ok
const AppearTopRight = ( props ) => (
	<Animate { ...props } />
);
Appear Bottom Left story ok
const AppearBottomLeft = ( props ) => (
	<Animate { ...props } />
);
Appear Bottom Right story ok
const AppearBottomRight = ( props ) => (
	<Animate { ...props } />
);
Loading story ok
const Loading = ( props ) => (
	<Animate { ...props } />
);
Slide In story ok
const SlideIn = ( props ) => (
	<Animate { ...props } />
);

BlockTitle

blockeditor-blocktitle · ../packages/block-editor/src/components/block-title/stories/index.story.jsx
Prop type error
File: /home/runner/work/gutenberg/gutenberg/packages/block-editor/src/components/block-title/index.js
Error:
No suitable component definition found.
You can debug your component file in this playground: https://react-docgen.dev/playground
Code:
/**
 * Internal dependencies
 */

import useBlockDisplayTitle from './use-block-display-title';

/**
 * Renders the block's configured title as a string, or empty if the title
 * cannot be determined.
 *
 * @example
 *
 * ```jsx
 * <BlockTitle clientId="afd1cb17-2c08-4e7a-91be-007ba7ddc3a1" maximumLength={ 17 }/>
 * ```
 *
 * @param {Object}           props
 * @param {string}           props.clientId      Client ID of block.
 * @param {number|undefined} props.maximumLength The maximum length that the block title string may be before truncated.
 * @param {string|undefined} props.context       The context to pass to `getBlockLabel`.
 *
 * @return {React.JSX.Element} Block title.
 */
export default function BlockTitle( { clientId, maximumLength, context } ) {
	return useBlockDisplayTitle( { clientId, maximumLength, context } );
}
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { BlockTitle, ExperimentalBlockEditorProvider } from "@wordpress/block-editor";
Default story ok
const Default = () => <BlockTitle clientId={blocks[ 0 ].clientId} />;

ScrollLock

components-scrolllock · ../packages/components/src/scroll-lock/stories/index.story.tsx
Prop type error
File: /home/runner/work/gutenberg/gutenberg/packages/components/src/scroll-lock/index.tsx
Error:
No suitable component definition found.
You can debug your component file in this playground: https://react-docgen.dev/playground
Code:
/**
 * WordPress dependencies
 */
import { useEffect } from '@wordpress/element';

/*
 * Setting `overflow: hidden` on html and body elements resets body scroll in iOS.
 * Save scroll top so we can restore it after locking scroll.
 *
 * NOTE: It would be cleaner and possibly safer to find a localized solution such
 * as preventing default on certain touchmove events.
 */
let previousScrollTop = 0;

function setLocked( locked: boolean ) {
	const scrollingElement = document.scrollingElement || document.body;

	if ( locked ) {
		previousScrollTop = scrollingElement.scrollTop;
	}

	const methodName = locked ? 'add' : 'remove';
	scrollingElement.classList[ methodName ]( 'lockscroll' );

	// Adding the class to the document element seems to be necessary in iOS.
	document.documentElement.classList[ methodName ]( 'lockscroll' );

	if ( ! locked ) {
		scrollingElement.scrollTop = previousScrollTop;
	}
}

let lockCounter = 0;

/**
 * ScrollLock is a content-free React component for declaratively preventing
 * scroll bleed from modal UI to the page body. This component applies a
 * `lockscroll` class to the `document.documentElement` and
 * `document.scrollingElement` elements to stop the body from scrolling. When it
 * is present, the lock is applied.
 *
 * ```jsx
 * import { ScrollLock, Button } from '@wordpress/components';
 * import { useState } from '@wordpress/element';
 *
 * const MyScrollLock = () => {
 *   const [ isScrollLocked, setIsScrollLocked ] = useState( false );
 *
 *   const toggleLock = () => {
 *     setIsScrollLocked( ( locked ) => ! locked ) );
 *   };
 *
 *   return (
 *     <div>
 *       <Button variant="secondary" onClick={ toggleLock }>
 *         Toggle scroll lock
 *       </Button>
 *       { isScrollLocked && <ScrollLock /> }
 *       <p>
 *         Scroll locked:
 *         <strong>{ isScrollLocked ? 'Yes' : 'No' }</strong>
 *       </p>
 *     </div>
 *   );
 * };
 * ```
 */
export function ScrollLock(): null {
	useEffect( () => {
		if ( lockCounter === 0 ) {
			setLocked( true );
		}

		++lockCounter;

		return () => {
			if ( lockCounter === 1 ) {
				setLocked( false );
			}

			--lockCounter;
		};
	}, [] );

	return null;
}

export default ScrollLock;
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Button, ScrollLock } from "@wordpress/components";
Default story ok
const Default = () => {
	const [ isScrollLocked, setScrollLocked ] = useState( false );
	const toggleLock = () => setScrollLocked( ! isScrollLocked );

	return (
		<div style={ { height: 1000 } }>
			<div
				style={ {
					overflow: 'auto',
					height: 240,
					border: '1px solid lightgray',
				} }
			>
				<StripedBackground>
					<div>
						Start scrolling down. Once you scroll to the end of this
						container with the stripes, the rest of the page will
						continue scrolling. <code>ScrollLock</code> prevents
						this &quot;scroll bleed&quot; from happening.
					</div>
					<ToggleContainer>
						<Button
							__next40pxDefaultSize
							variant="primary"
							onClick={ toggleLock }
						>
							Toggle Scroll Lock
						</Button>
						{ isScrollLocked && <ScrollLock /> }
						<p>
							Scroll locked:{ ' ' }
							<strong>{ isScrollLocked ? 'Yes' : 'No' }</strong>
						</p>
					</ToggleContainer>
				</StripedBackground>
			</div>
		</div>
	);
};

BlockDraggable

blockeditor-blockdraggable · ../packages/block-editor/src/components/block-draggable/stories/index.story.jsx
Prop type error
We could not detect the component from your story file. Specify meta.component.
  4 | import BlockDraggableChip from '../draggable-chip';
  5 |
> 6 | export default { title: 'BlockEditor/BlockDraggable' };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  7 |
  8 | export const _default = () => {
  9 | 	// Create a wrapper box for the absolutely-positioned child component.

../packages/block-editor/src/components/block-draggable/stories/index.story.jsx:
/**
 * Internal dependencies
 */
import BlockDraggableChip from '../draggable-chip';

export default { title: 'BlockEditor/BlockDraggable' };

export const _default = () => {
	// Create a wrapper box for the absolutely-positioned child component.
	const wrapperStyle = { margin: '24px 0', position: 'relative' };
	return (
		<div style={ wrapperStyle }>
			<BlockDraggableChip count={ 2 } />
		</div>
	);
};
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { BlockDraggableChip } from "@wordpress/block-editor";
Default story ok
const _default = () => {
	// Create a wrapper box for the absolutely-positioned child component.
	const wrapperStyle = { margin: '24px 0', position: 'relative' };
	return (
		<div style={ wrapperStyle }>
			<BlockDraggableChip count={ 2 } />
		</div>
	);
};

BlockEditor

playground-block-editor · ./stories/playground/index.story.jsx
Prop type error
We could not detect the component from your story file. Specify meta.component.
   7 | import EditorZoomOut from './zoom-out';
   8 |
>  9 | export default {
     | ^
  10 | 	title: 'Playground/Block Editor',
  11 | 	parameters: {
  12 | 		sourceLink: 'storybook/stories/playground',

./stories/playground/index.story.jsx:
/**
 * Internal dependencies
 */
import EditorFullPage from './fullpage';
import EditorBox from './box';
import EditorWithUndoRedo from './with-undo-redo';
import EditorZoomOut from './zoom-out';

export default {
	title: 'Playground/Block Editor',
	parameters: {
		sourceLink: 'storybook/stories/playground',
	},
};

export const _default = () => {
	return <EditorFullPage />;
};

_default.parameters = {
	sourceLink: 'storybook/stories/playground/fullpage/index.jsx',
};

export const Box = () => {
	return <EditorBox />;
};

Box.parameters = {
	sourceLink: 'storybook/stories/playground/box/index.jsx',
};

export const UndoRedo = () => {
	return <EditorWithUndoRedo />;
};

UndoRedo.parameters = {
	sourceLink: 'storybook/stories/playground/with-undo-redo/index.jsx',
};

export const ZoomOut = ( props ) => {
	return <EditorZoomOut { ...props } />;
};

ZoomOut.parameters = {
	sourceLink: 'storybook/stories/playground/zoom-out/index.jsx',
};
ZoomOut.argTypes = {
	zoomLevel: { control: { type: 'range', min: 10, max: 100, step: 5 } },
};
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { EditorBox, EditorFullPage, EditorWithUndoRedo, EditorZoomOut } from "@wordpress/storybook";
Default story ok
const _default = () => {
	return <EditorFullPage />;
};
Box story ok
const Box = () => {
	return <EditorBox />;
};
Undo Redo story ok
const UndoRedo = () => {
	return <EditorWithUndoRedo />;
};
Zoom Out story ok
const ZoomOut = ( props ) => {
	return <EditorZoomOut { ...props } />;
};

Overview

components-validated-form-controls-overview · ../packages/components/src/validated-form-controls/components/stories/overview.story.tsx
Prop type error
We could not detect the component from your story file. Specify meta.component.
  24 | import { VStack } from '../../../v-stack';
  25 |
> 26 | const meta: Meta< typeof ControlWithError > = {
     | ^
  27 | 	title: 'Components/Selection & Input/Validated Form Controls/Overview',
  28 | 	id: 'components-validated-form-controls-overview',
  29 | 	parameters: {

../packages/components/src/validated-form-controls/components/stories/overview.mdx:
/**
 * External dependencies
 */
import type { Meta, StoryObj } from '@storybook/react-vite';
import { expect, userEvent, waitFor, within } from 'storybook/test';
import clsx from 'clsx';

/**
 * WordPress dependencies
 */
import { useRef, useCallback, useState } from '@wordpress/element';
import { debounce } from '@wordpress/compose';

/**
 * Internal dependencies
 */
import { ValidatedInputControl } from '..';
import { formDecorator } from './story-utils';
import type { ControlWithError } from '../../control-with-error';
import Dropdown from '../../../dropdown';
import { Button } from '../../../button';
import Modal from '../../../modal';
import { HStack } from '../../../h-stack';
import { VStack } from '../../../v-stack';

const meta: Meta< typeof ControlWithError > = {
	title: 'Components/Selection & Input/Validated Form Controls/Overview',
	id: 'components-validated-form-controls-overview',
	parameters: {
		controls: { disable: true },
	},
};
export default meta;

type Story = StoryObj< typeof ControlWithError >;

/**
 * When there are multiple controls with errors, attempting to submit will
 * move focus to the first control with an error.
 */
export const WithMultipleControls: Story = {
	decorators: formDecorator,
	render: function Template() {
		const [ text, setText ] = useState< string | undefined >( '' );
		const [ text2, setText2 ] = useState< string | undefined >( '' );

		return (
			<>
				<ValidatedInputControl
					label="Text"
					required
					value={ text }
					help="The word 'error' will trigger an error."
					onChange={ setText }
					customValidity={
						text?.toLowerCase() === 'error'
							? {
									type: 'invalid',
									message: 'The word "error" is not allowed.',
							  }
							: undefined
					}
				/>
				<ValidatedInputControl
					label="Text"
					required
					value={ text2 }
					help="The word 'error' will trigger an error."
					onChange={ setText2 }
					customValidity={
						text2?.toLowerCase() === 'error'
							? {
									type: 'invalid',
									message: 'The word "error" is not allowed.',
							  }
							: undefined
					}
				/>
			</>
		);
	},
};

/**
 * Help text can be configured to be hidden when a custom error is reported. Whether to opt for this approach
 * will depend on context.
 */
export const WithHelpTextReplacement: Story = {
	decorators: formDecorator,
	render: function Template() {
		const [ text, setText ] = useState< string | undefined >( '' );
		const isInvalid = text?.toLowerCase() === 'error';

		return (
			<>
				<style>
					{ `
				.my-control:has(:invalid[data-validity-visible]) .my-control__help:not(.is-visible) {
					display: none;
				}
				` }
				</style>
				<ValidatedInputControl
					className="my-control"
					label="Text"
					required
					value={ text }
					help={
						<span
							className={ clsx(
								'my-control__help',
								! isInvalid && 'is-visible'
							) }
						>
							The word &quot;error&quot; is not allowed.
						</span>
					}
					onChange={ setText }
					customValidity={
						isInvalid
							? {
									type: 'invalid',
									message: 'The word "error" is not allowed.',
							  }
							: undefined
					}
				/>
			</>
		);
	},
};

/**
 * To provide feedback from server-side validation, the `customValidity` prop can be used
 * to show additional status indicators while waiting for the server response,
 * and after the response is received.
 *
 * These indicators are intended for asynchronous validation calls that may take more than 1 second to complete.
 * They may be unnecessary when responses are generally quick.
 */
export const AsyncValidation: StoryObj< typeof ValidatedInputControl > = {
	decorators: formDecorator,
	render: function Template( { ...args } ) {
		const [ text, setText ] = useState( '' );
		const [ customValidity, setCustomValidity ] =
			useState<
				React.ComponentProps<
					typeof ValidatedInputControl
				>[ 'customValidity' ]
			>( undefined );

		const timeoutRef =
			useRef< ReturnType< typeof setTimeout > >( undefined );

		// eslint-disable-next-line react-hooks/exhaustive-deps
		const debouncedValidate = useCallback(
			debounce( ( v ) => {
				if ( v === '' ) {
					return;
				}

				setCustomValidity( {
					type: 'validating',
					message: 'Validating...',
				} );

				timeoutRef.current = setTimeout( () => {
					if ( v?.toString().toLowerCase() === 'error' ) {
						setCustomValidity( {
							type: 'invalid',
							message: 'The word "error" is not allowed.',
						} );
					} else {
						setCustomValidity( {
							type: 'valid',
							message: 'Validated',
						} );
					}
				}, 1500 );
			}, 500 ),
			[]
		);

		return (
			<ValidatedInputControl
				{ ...args }
				value={ text }
				onChange={ ( newValue ) => {
					setText( newValue ?? '' );
					setCustomValidity( undefined );
					clearTimeout( timeoutRef.current );
					debouncedValidate( newValue );
				} }
				customValidity={ customValidity }
			/>
		);
	},
	args: {
		label: 'Text',
		help: 'The word "error" will trigger an error asynchronously.',
		required: true,
	},
};

// Not exported - Only for testing purposes.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const AsyncValidationWithTest: StoryObj< typeof ValidatedInputControl > = {
	...AsyncValidation,
	decorators: formDecorator,
	play: async ( { canvasElement } ) => {
		const canvas = within( canvasElement );
		await userEvent.click( canvas.getByRole( 'textbox' ) );
		await userEvent.type( canvas.getByRole( 'textbox' ), 'valid text', {
			delay: 10,
		} );
		await userEvent.tab();

		await waitFor(
			() => {
				expect( canvas.getByText( 'Validated' ) ).toBeVisible();
			},
			{ timeout: 2500 }
		);

		await new Promise( ( resolve ) => setTimeout( resolve, 500 ) );
		await userEvent.clear( canvas.getByRole( 'textbox' ) );

		await waitFor(
			() => {
				expect(
					canvas.getByText( 'Please fill out this field.' )
				).toBeVisible();
			},
			{ timeout: 2500 }
		);

		// Should not show validating state if there were no changes
		// after a valid/invalid state was already shown.
		await new Promise( ( resolve ) => setTimeout( resolve, 1500 ) );
		await expect(
			canvas.queryByText( 'Validating...' )
		).not.toBeInTheDocument();

		await userEvent.type( canvas.getByRole( 'textbox' ), 'e', {
			delay: 10,
		} );

		// Should not show valid state if server has not yet responded.
		await expect(
			canvas.queryByText( 'Validated' )
		).not.toBeInTheDocument();

		// Should show validating state when transitioning from invalid to valid.
		await waitFor(
			() => {
				expect( canvas.getByText( 'Validating...' ) ).toBeVisible();
			},
			{ timeout: 2500 }
		);

		await waitFor(
			() => {
				expect( canvas.getByText( 'Validated' ) ).toBeVisible();
			},
			{ timeout: 2500 }
		);

		await new Promise( ( resolve ) => setTimeout( resolve, 1000 ) );
		await userEvent.type( canvas.getByRole( 'textbox' ), 'rror', {
			delay: 10,
		} );

		await waitFor(
			() => {
				expect(
					canvas.getByText( 'The word "error" is not allowed.' )
				).toBeVisible();
			},
			{ timeout: 2500 }
		);
	},
};

/**
 * Custom validity errors are effective immediately, even when they are not yet visible
 * to the user. For example, in this form where the initial value is already invalid,
 * the error message will be shown to the user once the submit button is clicked,
 * even if the input has never been interacted with.
 */
export const CustomErrorsOnSubmit: StoryObj< typeof ValidatedInputControl > = {
	decorators: formDecorator,
	args: {
		label: 'Text',
		required: true,
		help: 'The word "error" will trigger an error.',
	},
	render: function Template( { ...args } ) {
		const [ text, setText ] = useState< string | undefined >( 'error' );

		return (
			<>
				<ValidatedInputControl
					{ ...args }
					value={ text }
					onChange={ setText }
					customValidity={
						text === 'error'
							? {
									type: 'invalid',
									message: 'The word "error" is not allowed.',
							  }
							: undefined
					}
				/>
			</>
		);
	},
};

/**
 * While it is recommended to rely on the built-in behavior for showing errors by
 * using a `form` element and `type="submit"` button around validated fields,
 * it is also possible to show errors at arbitrary times.
 * This can be done by calling the [`reportValidity()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reportValidity)
 * on a ref of the field itself, or the wrapping `form` element.
 */
export const ShowingErrorsAtArbitraryTimes: StoryObj<
	typeof ValidatedInputControl
> = {
	args: {
		label: 'Text',
		required: true,
		help: 'The word "error" will trigger an error.',
	},
	decorators: [],
	render: function Template( { ...args } ) {
		const [ text, setText ] = useState< string | undefined >( 'error' );
		const ref = useRef< HTMLInputElement >( null );

		return (
			<VStack spacing={ 4 } alignment="left">
				<ValidatedInputControl
					ref={ ref }
					{ ...args }
					value={ text }
					onChange={ setText }
					customValidity={
						text === 'error'
							? {
									type: 'invalid',
									message: 'The word "error" is not allowed.',
							  }
							: undefined
					}
				/>
				<Button
					__next40pxDefaultSize
					variant="secondary"
					onClick={ () => ref.current?.reportValidity() }
				>
					Report validity
				</Button>
			</VStack>
		);
	},
};

/**
 * A `form` wrapper and `type="submit"` button can be used to force validation when
 * the user tries to commit their changes, while still allowing the modal to be closed by canceling.
 * Optionally, the `shouldCloseOnClickOutside`, `isDismissible`, and `shouldCloseOnEsc` props
 * on `Modal` can be disabled to force users to more explicitly signal whether they are trying to
 * "submit close" or "cancel close" the dialog, as well as preventing data loss on accidental closures.
 */
export const ValidateInModal: StoryObj< typeof ValidatedInputControl > = {
	render: function Template( { ...args } ) {
		const [ isOpen, setIsOpen ] = useState( false );
		const [ text, setText ] = useState< string | undefined >( '' );

		return (
			<>
				<Button
					variant="secondary"
					__next40pxDefaultSize
					onClick={ () => setIsOpen( true ) }
				>
					Open in modal
				</Button>
				{ isOpen && (
					<Modal
						title="Dialog title"
						onRequestClose={ () => setIsOpen( false ) }
						shouldCloseOnClickOutside={ false }
						shouldCloseOnEsc={ false }
						isDismissible={ false }
					>
						<form
							onSubmit={ ( event ) => {
								event.preventDefault();
								setIsOpen( false );
							} }
						>
							<VStack spacing={ 2 }>
								<ValidatedInputControl
									{ ...args }
									value={ text }
									onChange={ setText }
									customValidity={
										text === 'error'
											? {
													type: 'invalid',
													message:
														'The word "error" is not allowed.',
											  }
											: undefined
									}
								/>

								<HStack justify="flex-end" spacing={ 2 }>
									<Button
										variant="tertiary"
										__next40pxDefaultSize
										onClick={ () => setIsOpen( false ) }
									>
										Cancel
									</Button>
									<Button
										variant="primary"
										__next40pxDefaultSize
										type="submit"
									>
										Save
									</Button>
								</HStack>
							</VStack>
						</form>
					</Modal>
				) }
			</>
		);
	},
	args: {
		label: 'Text',
		required: true,
		help: 'The word "error" will trigger an error.',
	},
};

/**
 * [Form methods](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement#instance_methods) like
 * `reportValidity()` can be used to validate the fields when a popover is about to be closed,
 * and prevent the closing of the popover when invalid.
 */
export const ValidateOnPopoverClose: StoryObj< typeof ValidatedInputControl > =
	{
		render: function Template( { ...args } ) {
			const [ isOpen, setIsOpen ] = useState( false );
			const formRef = useRef< HTMLFormElement >( null );
			const [ text, setText ] = useState< string | undefined >( '' );

			return (
				<Dropdown
					popoverProps={ { placement: 'bottom-start' } }
					open={ isOpen }
					onToggle={ ( willOpen ) => {
						if ( ! willOpen ) {
							const isValid = formRef.current?.reportValidity();
							setIsOpen( ! isValid );
						} else {
							setIsOpen( true );
						}
					} }
					renderContent={ () => (
						<form
							ref={ formRef }
							onSubmit={ ( event ) => {
								event.preventDefault();
								setIsOpen( false );
							} }
						>
							<ValidatedInputControl
								{ ...args }
								value={ text }
								onChange={ setText }
								customValidity={
									text === 'error'
										? {
												type: 'invalid',
												message:
													'The word "error" is not allowed.',
										  }
										: undefined
								}
							/>
						</form>
					) }
					renderToggle={ () => {
						return (
							<Button
								__next40pxDefaultSize
								variant="secondary"
								onClick={ () => setIsOpen( ! isOpen ) }
								aria-expanded={ isOpen }
							>
								Open in popover
							</Button>
						);
					} }
				/>
			);
		},
		args: {
			label: 'Text',
			help: 'The word "error" will trigger an error.',
			required: true,
			style: {
				width: '200px',
			},
		},
	};
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { Button, Dropdown, HStack, Modal, ValidatedInputControl, VStack } from "@wordpress/components";
With Multiple Controls story ok
When there are multiple controls with errors, attempting to submit will move focus to the first control with an error.
const WithMultipleControls = function Template() {
    const [ text, setText ] = useState< string | undefined >( '' );
    const [ text2, setText2 ] = useState< string | undefined >( '' );

    return (
        <>
            <ValidatedInputControl
                label="Text"
                required
                value={ text }
                help="The word 'error' will trigger an error."
                onChange={ setText }
                customValidity={
                    text?.toLowerCase() === 'error'
                        ? {
                                type: 'invalid',
                                message: 'The word "error" is not allowed.',
                          }
                        : undefined
                }
            />
            <ValidatedInputControl
                label="Text"
                required
                value={ text2 }
                help="The word 'error' will trigger an error."
                onChange={ setText2 }
                customValidity={
                    text2?.toLowerCase() === 'error'
                        ? {
                                type: 'invalid',
                                message: 'The word "error" is not allowed.',
                          }
                        : undefined
                }
            />
        </>
    );
};
With Help Text Replacement story ok
Help text can be configured to be hidden when a custom error is reported. Whether to opt for this approach will depend on context.
const WithHelpTextReplacement = function Template() {
    const [ text, setText ] = useState< string | undefined >( '' );
    const isInvalid = text?.toLowerCase() === 'error';

    return (
        <>
            <style>
                { `
            .my-control:has(:invalid[data-validity-visible]) .my-control__help:not(.is-visible) {
                display: none;
            }
            ` }
            </style>
            <ValidatedInputControl
                className="my-control"
                label="Text"
                required
                value={ text }
                help={
                    <span
                        className={ clsx(
                            'my-control__help',
                            ! isInvalid && 'is-visible'
                        ) }
                    >
                        The word &quot;error&quot; is not allowed.
                    </span>
                }
                onChange={ setText }
                customValidity={
                    isInvalid
                        ? {
                                type: 'invalid',
                                message: 'The word "error" is not allowed.',
                          }
                        : undefined
                }
            />
        </>
    );
};
Async Validation story ok
To provide feedback from server-side validation, the `customValidity` prop can be used to show additional status indicators while waiting for the server response, and after the response is received. These indicators are intended for asynchronous validation calls that may take more than 1 second to complete. They may be unnecessary when responses are generally quick.
const AsyncValidation = () => {
    const [ text, setText ] = useState( '' );
    const [ customValidity, setCustomValidity ] =
        useState<
            React.ComponentProps<
                typeof ValidatedInputControl
            >[ 'customValidity' ]
        >( undefined );

    const timeoutRef =
        useRef< ReturnType< typeof setTimeout > >( undefined );

    // eslint-disable-next-line react-hooks/exhaustive-deps
    const debouncedValidate = useCallback(
        debounce( ( v ) => {
            if ( v === '' ) {
                return;
            }

            setCustomValidity( {
                type: 'validating',
                message: 'Validating...',
            } );

            timeoutRef.current = setTimeout( () => {
                if ( v?.toString().toLowerCase() === 'error' ) {
                    setCustomValidity( {
                        type: 'invalid',
                        message: 'The word "error" is not allowed.',
                    } );
                } else {
                    setCustomValidity( {
                        type: 'valid',
                        message: 'Validated',
                    } );
                }
            }, 1500 );
        }, 500 ),
        []
    );

    return (
        <ValidatedInputControl
            label="Text"
            help="The word \"error\" will trigger an error asynchronously."
            required
            value={ text }
            onChange={ ( newValue ) => {
                setText( newValue ?? '' );
                setCustomValidity( undefined );
                clearTimeout( timeoutRef.current );
                debouncedValidate( newValue );
            } }
            customValidity={ customValidity } />
    );
};
Custom Errors On Submit story ok
Custom validity errors are effective immediately, even when they are not yet visible to the user. For example, in this form where the initial value is already invalid, the error message will be shown to the user once the submit button is clicked, even if the input has never been interacted with.
const CustomErrorsOnSubmit = () => {
    const [ text, setText ] = useState< string | undefined >( 'error' );

    return (
        <>
            <ValidatedInputControl
                label="Text"
                required
                help="The word \"error\" will trigger an error."
                value={ text }
                onChange={ setText }
                customValidity={
                    text === 'error'
                        ? {
                                type: 'invalid',
                                message: 'The word "error" is not allowed.',
                          }
                        : undefined
                } />
        </>
    );
};
Showing Errors At Arbitrary Times story ok
While it is recommended to rely on the built-in behavior for showing errors by using a `form` element and `type="submit"` button around validated fields, it is also possible to show errors at arbitrary times. This can be done by calling the [`reportValidity()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reportValidity) on a ref of the field itself, or the wrapping `form` element.
const ShowingErrorsAtArbitraryTimes = () => {
    const [ text, setText ] = useState< string | undefined >( 'error' );
    const ref = useRef< HTMLInputElement >( null );

    return (
        <VStack spacing={ 4 } alignment="left">
            <ValidatedInputControl
                ref={ ref }
                label="Text"
                required
                help="The word \"error\" will trigger an error."
                value={ text }
                onChange={ setText }
                customValidity={
                    text === 'error'
                        ? {
                                type: 'invalid',
                                message: 'The word "error" is not allowed.',
                          }
                        : undefined
                } />
            <Button
                __next40pxDefaultSize
                variant="secondary"
                onClick={ () => ref.current?.reportValidity() }>Report validity
                                </Button>
        </VStack>
    );
};
Validate In Modal story ok
A `form` wrapper and `type="submit"` button can be used to force validation when the user tries to commit their changes, while still allowing the modal to be closed by canceling. Optionally, the `shouldCloseOnClickOutside`, `isDismissible`, and `shouldCloseOnEsc` props on `Modal` can be disabled to force users to more explicitly signal whether they are trying to "submit close" or "cancel close" the dialog, as well as preventing data loss on accidental closures.
const ValidateInModal = function Template( { ...args } ) {
    const [ isOpen, setIsOpen ] = useState( false );
    const [ text, setText ] = useState< string | undefined >( '' );

    return (
        <>
            <Button
                variant="secondary"
                __next40pxDefaultSize
                onClick={ () => setIsOpen( true ) }
            >
                Open in modal
            </Button>
            { isOpen && (
                <Modal
                    title="Dialog title"
                    onRequestClose={ () => setIsOpen( false ) }
                    shouldCloseOnClickOutside={ false }
                    shouldCloseOnEsc={ false }
                    isDismissible={ false }
                >
                    <form
                        onSubmit={ ( event ) => {
                            event.preventDefault();
                            setIsOpen( false );
                        } }
                    >
                        <VStack spacing={ 2 }>
                            <ValidatedInputControl
                                { ...args }
                                value={ text }
                                onChange={ setText }
                                customValidity={
                                    text === 'error'
                                        ? {
                                                type: 'invalid',
                                                message:
                                                    'The word "error" is not allowed.',
                                          }
                                        : undefined
                                }
                            />

                            <HStack justify="flex-end" spacing={ 2 }>
                                <Button
                                    variant="tertiary"
                                    __next40pxDefaultSize
                                    onClick={ () => setIsOpen( false ) }
                                >
                                    Cancel
                                </Button>
                                <Button
                                    variant="primary"
                                    __next40pxDefaultSize
                                    type="submit"
                                >
                                    Save
                                </Button>
                            </HStack>
                        </VStack>
                    </form>
                </Modal>
            ) }
        </>
    );
};
Validate On Popover Close story ok
[Form methods](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement#instance_methods) like `reportValidity()` can be used to validate the fields when a popover is about to be closed, and prevent the closing of the popover when invalid.
const ValidateOnPopoverClose = function Template( { ...args } ) {
    const [ isOpen, setIsOpen ] = useState( false );
    const formRef = useRef< HTMLFormElement >( null );
    const [ text, setText ] = useState< string | undefined >( '' );

    return (
        <Dropdown
            popoverProps={ { placement: 'bottom-start' } }
            open={ isOpen }
            onToggle={ ( willOpen ) => {
                if ( ! willOpen ) {
                    const isValid = formRef.current?.reportValidity();
                    setIsOpen( ! isValid );
                } else {
                    setIsOpen( true );
                }
            } }
            renderContent={ () => (
                <form
                    ref={ formRef }
                    onSubmit={ ( event ) => {
                        event.preventDefault();
                        setIsOpen( false );
                    } }
                >
                    <ValidatedInputControl
                        { ...args }
                        value={ text }
                        onChange={ setText }
                        customValidity={
                            text === 'error'
                                ? {
                                        type: 'invalid',
                                        message:
                                            'The word "error" is not allowed.',
                                  }
                                : undefined
                        }
                    />
                </form>
            ) }
            renderToggle={ () => {
                return (
                    <Button
                        __next40pxDefaultSize
                        variant="secondary"
                        onClick={ () => setIsOpen( ! isOpen ) }
                        aria-expanded={ isOpen }
                    >
                        Open in popover
                    </Button>
                );
            } }
        />
    );
};

DataForm

fields-base-fields · ../packages/fields/src/stories/index.story.tsx
Prop type error
File: /home/runner/work/gutenberg/gutenberg/node_modules/@wordpress/dataviews/build-module/index.mjs
Error:
Component files in node_modules are not supported.
The distributed files in node_modules usually don't contain the necessary comments or types needed to analyze component information.
Configure TypeScript path aliases to map your package name to the source file instead.

Example (tsconfig.json):
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@design-system/button": ["src/components/Button.tsx"],
      "@design-system/*": ["src/components/*"]
    }
  }
}

Then import using:
import { Button } from '@design-system/button'

Storybook resolves tsconfig paths automatically.
Code:
/* File in node_modules */
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { DataForm, DataViews } from "@wordpress/dataviews";
Data Forms Preview story ok
const DataFormsPreview = ( { type }: { type: 'regular' | 'panel' } ) => {
	const [ data, setData ] = useState( samplePostWithAuthor );

	const handleChange = ( updates: Partial< BasePostWithEmbeddedAuthor > ) => {
		setData( ( prev ) => ( { ...prev, ...updates } ) );
	};

	// Form configuration for the showcase.
	const showcaseForm: Form = {
		layout: {
			type,
		},
		fields: [
			'title',
			'slug',
			'status',
			'date',
			'author',
			'comment_status',
			'password',
			'menu_order',
		],
	};

	return (
		<div style={ { padding: '20px' } }>
			<h2>Base Fields</h2>
			<p>
				This story demonstrates all the base fields from the
				@wordpress/fields package within a DataForm.
			</p>

			<DataForm
				data={ data }
				fields={ showcaseFields }
				form={ showcaseForm }
				onChange={ handleChange }
			/>
		</div>
	);
};
Data Views Preview story ok
const DataViewsPreview = () => {
	const [ view, setView ] = useState< View >( {
		type: 'table',
		fields: showcaseFields.map( ( f ) => f.id ),
		titleField: 'title',
		descriptionField: undefined,
		mediaField: undefined,
	} );
	const [ data ] = useState( [ samplePostWithAuthor ] );

	const paginationInfo = {
		totalItems: 1,
		totalPages: 1,
	};

	const defaultLayouts = {
		table: {},
		list: {},
		grid: {},
	};

	return (
		<div style={ { padding: '20px' } }>
			<h2>Fields Package DataViews Preview</h2>
			<p>
				This story demonstrates all the base fields from the
				@wordpress/fields package, rendered in a DataViews component,
				allowing preview of view state and layout switching.
			</p>
			<DataViews
				data={ data }
				fields={ showcaseFields }
				view={ view }
				onChangeView={ ( nextView: View ) => setView( nextView ) }
				paginationInfo={ paginationInfo }
				defaultLayouts={ defaultLayouts }
			/>
		</div>
	);
};

DataForm

fields-media-fields · ../packages/media-fields/src/stories/index.story.tsx
Prop type error
File: /home/runner/work/gutenberg/gutenberg/node_modules/@wordpress/dataviews/build-module/index.mjs
Error:
Component files in node_modules are not supported.
The distributed files in node_modules usually don't contain the necessary comments or types needed to analyze component information.
Configure TypeScript path aliases to map your package name to the source file instead.

Example (tsconfig.json):
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@design-system/button": ["src/components/Button.tsx"],
      "@design-system/*": ["src/components/*"]
    }
  }
}

Then import using:
import { Button } from '@design-system/button'

Storybook resolves tsconfig paths automatically.
Code:
/* File in node_modules */
Info
No description found. Write a jsdoc comment such as /** Component description */.
Imports
import { DataForm, DataViews } from "@wordpress/dataviews";
Data Forms Preview story ok
const DataFormsPreview = ( { type }: { type: 'regular' | 'panel' } ) => {
	const [ data, setData ] = useState< MediaItem >( sampleMediaItem );

	const handleChange = ( updates: Partial< MediaItem > ) => {
		setData( ( prev: MediaItem ) => ( { ...prev, ...updates } ) );
	};

	// Form configuration for the media fields showcase.
	const showcaseForm: Form = {
		layout: {
			type,
		},
		fields: [
			'media_thumbnail',
			'alt_text',
			'caption',
			'description',
			'filename',
			'mime_type',
			'media_dimensions',
			'filesize',
			'author',
			'date',
			'modified',
			'attached_to',
		],
	};

	return (
		<div style={ { padding: '20px' } }>
			<h2>Media Fields</h2>
			<p>
				This story demonstrates all the media fields from the
				@wordpress/media-fields package within a DataForm.
			</p>

			<DataForm
				data={ data }
				fields={ showcaseFields }
				form={ showcaseForm }
				onChange={ handleChange }
			/>
		</div>
	);
};
Data Views Preview story ok
const DataViewsPreview = () => {
	const [ view, setView ] = useState< View >( {
		type: 'table',
		fields: showcaseFields
			.map( ( f ) => f.id )
			.filter( ( id ) => id !== 'media_thumbnail' ),
		descriptionField: undefined,
		mediaField: 'media_thumbnail',
		showTitle: false,
	} );
	const [ data ] = useState< MediaItem[] >( [
		sampleMediaItem,
		sampleMediaItemZip,
		sampleMediaItemBrokenImage,
	] );

	const paginationInfo = {
		totalItems: 3,
		totalPages: 1,
	};

	const defaultLayouts = {
		table: {},
		list: {},
		grid: {},
	};

	return (
		<div style={ { padding: '20px' } }>
			<h2>Media Fields DataViews Preview</h2>
			<p>
				This story demonstrates all the media fields from the
				@wordpress/media-fields package, rendered in a DataViews
				component, allowing preview of view state and layout switching.
			</p>
			<DataViews
				data={ data }
				fields={ showcaseFields }
				view={ view }
				onChangeView={ ( nextView: View ) => setView( nextView ) }
				paginationInfo={ paginationInfo }
				defaultLayouts={ defaultLayouts }
			/>
		</div>
	);
};