Status: stable

  • Navigator

    View on Storybook

    View source on GitHub

    Import

    import { Navigator } from '@wordpress/components';
    

    Examples

    Default

    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

    const WithNestedInitialPath = () => <Navigator initialPath="/child/grandchild" />;
    

    Skip Focus

    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>;
    
  • Spinner

    Spinner is a component used to notify users that their action is being processed.

    View on Storybook

    View source on GitHub

    Import

    import { Spinner } from '@wordpress/components';
    

    Examples

    Default

    const Default = () => {
        return <Spinner />;
    };
    

    Custom Size

    const CustomSize = () => {
        return <Spinner style={{ width: space( 20 ), height: space( 20 ) }} />;
    };
    
  • Notice

    Notice is a component used to communicate feedback to the user.

    View on Storybook

    View source on GitHub

    Import

    import { Notice } from '@wordpress/components';
    

    Props

    NameTypeDefaultRequiredDescription
    classNamestring

    A CSS class to give to the wrapper element.

    childrenReactNodeYes

    The displayed message of a notice. Also used as the spoken message for assistive technology, unless spokenMessage is provided as an alternative message.

    spokenMessageReactNodechildren

    Used to provide a custom spoken message in place of the children default.

    @default children

    status'warning' | 'success' | 'error' | 'info''info'

    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’

    onRemove() => void() => {}

    Function called when dismissing the notice

    @default noop

    politeness'polite' | 'assertive'getDefaultPoliteness( status )

    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

    isDismissiblebooleantrue

    Whether the notice should be dismissible or not

    @default true

    onDismiss() => void() => {}

    A deprecated alternative to onRemove. This prop is kept for compatibility reasons but should be avoided.

    @default noop

    actionsArray< NoticeAction >[]

    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 []

    __unstableHTMLboolean

    Determines whether or not the message should be parsed as custom HTML instead of a string.

    Examples

    Default

    const Default = ( props ) => {
    	return <Notice { ...props } />;
    };
    

    With Custom Spoken Message

    const WithCustomSpokenMessage = ( props ) => {
    	return <Notice { ...props } />;
    };
    

    With JSX Children

    const WithJSXChildren = ( props ) => {
    	return <Notice { ...props } />;
    };
    

    With Actions

    const WithActions = ( props ) => {
    	return <Notice { ...props } />;
    };
    

    NoticeList Subcomponent

    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

    Action buttons can be disabled.

    const WithDisabledAction = ( props ) => {
    	return <Notice { ...props } />;
    };
    
  • Stack

    A flexible layout component using CSS Flexbox for consistent spacing and alignment. Built on design tokens for predictable spacing values.

    View on Storybook

    View source on GitHub

    Import

    import { Stack } from '@wordpress/ui';
    

    Props

    NameTypeDefaultRequiredDescription
    classNamestring

    CSS class name to apply to the element.

    styleReact.CSSProperties

    CSS style to apply to the element.

    render| ComponentRenderFn< HTMLAttributesWithRef > | React.ReactElement< Record< string, unknown > >

    Replaces the component’s default HTML element using a given React element, or a function that returns a React element.

    directionExclude< React.CSSProperties[ 'flexDirection' ], 'row-reverse' | 'column-reverse' >

    The direction of the stack.

    gapGapSize

    The amount of space between each child element using design system tokens.

    @default undefined

    alignReact.CSSProperties[ 'alignItems' ]

    The alignment of the stack items along the cross axis.

    @default ‘initial’

    justifyReact.CSSProperties[ 'justifyContent' ]

    The alignment of the stack items along the main axis.

    @default ‘initial’

    wrapExclude< React.CSSProperties[ 'flexWrap' ], 'wrap-reverse' >

    Whether the stack items should wrap to the next line.

    childrenReact.ReactNode

    The content to be rendered inside the component.

    Examples

    Default

    const Default = () => <Stack gap="md">(<>
            <DemoBox />
            <DemoBox variant="lg" />
            <DemoBox />
            <DemoBox />
            <DemoBox variant="lg" />
            <DemoBox />
        </>)</Stack>;
    

    Nested

    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>;
    
  • NumberControl

    View on Storybook

    View source on GitHub

    Import

    import { NumberControl } from '@wordpress/components';
    

    Examples

    Default

    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>
    		</>
    	);
    };
    
  • Text

    A text component for rendering content with predefined typographic variants. Built on design tokens for consistent typography across the UI.

    View on Storybook

    View source on GitHub

    Import

    import { Text } from '@wordpress/ui';
    

    Props

    NameTypeDefaultRequiredDescription
    classNamestring

    CSS class name to apply to the element.

    styleReact.CSSProperties

    CSS style to apply to the element.

    render| ComponentRenderFn< HTMLAttributesWithRef > | React.ReactElement< Record< string, unknown > >

    Replaces the component’s default HTML element using a given React element, or a function that returns a React element.

    variant| 'heading-2xl' | 'heading-xl' | 'heading-lg' | 'heading-md' | 'heading-sm' | 'body-xl' | 'body-lg' | 'body-md' | 'body-sm''body-md'

    The typographic variant to apply, controlling font family, size, line height, and weight.

    @default “body-md”

    childrenReact.ReactNode

    The content to be rendered inside the component.

    Examples

    Default

    const Default = () => <Text variant="body-md">The quick brown fox jumps over the lazy dog.</Text>;
    

    All Variants

    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

    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>
    );
    
  • Panel

    Panel expands and collapses multiple sections of content.

    View on Storybook

    View source on GitHub

    Import

    import { Panel } from '@wordpress/components';
    

    Props

    NameTypeDefaultRequiredDescription
    headerPanelHeaderProps[ 'label' ]

    The text that will be rendered as the title of the panel. Text will be rendered inside an <h2> tag.

    classNamestring

    The CSS class to apply to the wrapper element.

    childrenReact.ReactNodeYes

    The content to display within the panel.

    Examples

    Default

    const Default = ( props ) => <Panel { ...props } />;
    

    Panel Row

    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

    const DisabledSection = ( props ) => <Panel { ...props } />;
    

    With Icon

    const WithIcon = ( props ) => <Panel { ...props } />;
    
  • TextareaControl

    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.

    View on Storybook

    View source on GitHub

    Import

    import { TextareaControl } from '@wordpress/components';
    

    Examples

    Default

    const Default = () => {
        const [ value, setValue ] = useState( '' );
    
        return (
            <TextareaControl
                label="Text"
                help="Enter some text"
                placeholder="Placeholder"
                value={ value }
                onChange={ ( v ) => {
    				setValue( v );
    				onChange( v );
    			} } />
        );
    };
    
  • Popover

    View on Storybook

    View source on GitHub

    Import

    import { Popover } from '@wordpress/components';
    

    Props

    NameTypeDefaultRequiredDescription
    namestring'Popover'

    The name of the Slot in which the popover should be rendered. It should be also passed to the corresponding PopoverSlot component.

    @default ‘Popover’

    Examples

    Default

    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

    const Unstyled = () => <Popover variant="unstyled" />;
    

    All Placements

    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

    const DynamicHeight = () => <Popover>(<div
            style={ {
                height: 'var(--dynamic-height)',
                background: '#eee',
                padding: '20px',
            } }
        >Content with dynamic height
                        </div>)</Popover>;
    

    With Slot Outside Iframe

    const WithSlotOutsideIframe = () => <PopoverInsideIframeRenderedInExternalSlot />;
    

    With Close Handlers

    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>
        );
    };
    
  • TextControl

    TextControl components let users enter and edit text.

    View on Storybook

    View source on GitHub

    Import

    import { TextControl } from '@wordpress/components';
    

    Examples

    Default

    const Default = () => {
        const [ value, setValue ] = useState( '' );
    
        return (
            <TextControl
                __next40pxDefaultSize
                placeholder="Placeholder"
                value={ value }
                onChange={ ( v ) => {
    				setValue( v );
    				onChange( v );
    			} } />
        );
    };
    

    With Label And Help Text

    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 );
    			} } />
        );
    };