Status: stable

  • SearchControl

    SearchControl components let users display a search control.

    View on Storybook

    View source on GitHub

    Import

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

    Props

    NameTypeDefaultRequiredDescription
    labelunknown__( 'Search' )
    placeholderunknown__( 'Search' )
    hideLabelFromVisionunknowntrue
    sizeunknown'default'

    Examples

    Default

    const Default = ( {
    	onChange,
    	...props
    } ) => {
    	const [ value, setValue ] = useState< string >();
    
    	return (
    		<SearchControl
    			{ ...props }
    			value={ value }
    			onChange={ ( ...changeArgs ) => {
    				setValue( ...changeArgs );
    				onChange( ...changeArgs );
    			} }
    		/>
    	);
    };
    
  • Truncate

    View on Storybook

    View source on GitHub

    Import

    import { __experimentalTruncate as Truncate } from '@wordpress/components';
    

    Examples

    Default

    const Default = () => {
        return <Truncate numberOfLines={2}>{defaultText}</Truncate>;
    };
    

    Truncate by character count

    const CharacterCount = () => {
        return <Truncate limit={23} ellipsizeMode="tail" ellipsis="[---]">{defaultText}</Truncate>;
    };
    
  • Composite

    Renders a widget based on the WAI-ARIA composite role, which provides a single tab stop on the page and arrow key navigation through the focusable descendants.

    @example

    View on Storybook

    View source on GitHub

    Import

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

    Props

    NameTypeDefaultRequiredDescription
    focusLoopunknownfalse
    focusWrapunknownfalse
    focusShiftunknownfalse
    virtualFocusunknownfalse
    orientationunknown'both'
    rtlunknownisRTL()
    disabledunknownfalse

    Examples

    Default

    const Default = () => <Composite>(<>
            <Composite.Item>Item one</Composite.Item>
            <Composite.Item>Item two</Composite.Item>
            <Composite.Item>Item three</Composite.Item>
        </>)</Composite>;
    

    Groups

    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

    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

    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

    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

    const WithSlotFill = () => <Composite>(<>
            <Composite.Item>Item one (direct child)</Composite.Item>
            <Slot />
            <Composite.Item>Item four (direct child)</Composite.Item>
        </>)</Composite>;
    

    With Tooltips

    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 </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>;
    
  • MenuGroup

    MenuGroup wraps a series of related MenuItem components into a common section.

    View on Storybook

    View source on GitHub

    Import

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

    Props

    NameTypeDefaultRequiredDescription
    classNamestring

    A CSS class to give to the container element.

    hideSeparatorboolean

    Hide the top border on the container.

    labelstring

    Text to be displayed as the menu group header.

    childrenReactNode

    The children elements.

    Examples

    Default

    const Default = () => {
        return (
            <MenuGroup>
                <MenuItem>Menu Item 1</MenuItem>
                <MenuItem>Menu Item 2</MenuItem>
            </MenuGroup>
        );
    };
    

    With Separator

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

    View on Storybook

    View source on GitHub

    Import

    import { __experimentalConfirmDialog as ConfirmDialog } from '@wordpress/components';
    

    Examples

    Default

    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

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

    MenuItem is a component which renders a button intended to be used in combination with the DropdownMenu component.

    View on Storybook

    View source on GitHub

    Import

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

    Examples

    Default

    const Default = ( props ) => {
    	return (
    		<MenuGroup>
    			<MenuItem { ...props }>Menu Item 1</MenuItem>
    		</MenuGroup>
    	);
    };
    

    Is Selected

    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

    const WithIcon = ( props ) => {
    	return (
    		<MenuGroup>
    			<MenuItem { ...props }>Menu Item 1</MenuItem>
    		</MenuGroup>
    	);
    };
    

    With Info

    const WithInfo = ( props ) => {
    	return (
    		<MenuGroup>
    			<MenuItem { ...props }>Menu Item 1</MenuItem>
    		</MenuGroup>
    	);
    };
    

    With Suffix

    const WithSuffix = ( props ) => {
    	return (
    		<MenuGroup>
    			<MenuItem { ...props }>Menu Item 1</MenuItem>
    		</MenuGroup>
    	);
    };
    
  • CustomSelectControl

    View on Storybook

    View source on GitHub

    Import

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

    Props

    NameTypeDefaultRequiredDescription
    classNamestring

    Optional classname for the component.

    hideLabelFromVisionboolean

    Hide the label visually, while keeping available to assistive technology.

    describedBystring

    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.

    labelstringYes

    Label for the control.

    onChange( newValue: CustomSelectChangeObject< NoInfer< T > > ) => void

    Function called with the control’s internal state changes. The selectedItem property contains the next selected item.

    optionsReadonlyArray< T >Yes

    The list of options that can be chosen from.

    size'default' | 'small' | '__unstable-large'

    The size of the control.

    @default ‘default’

    valueNoInfer< T >

    Can be used to externally control the value of the control.

    showSelectedHintboolean

    Show the hint of the selected item in the trigger button.

    @default false

    __next40pxDefaultSizeboolean

    Start opting into the larger default height that will become the default size in a future version.

    @default false

    Examples

    Default

    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

    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

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

    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

    View on Storybook

    View source on GitHub

    Import

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

    Props

    NameTypeDefaultRequiredDescription
    isDisabledunknowntrue

    Examples

    Default

    const Default = () => {
        return (
            <Disabled isDisabled>
                <Form />
            </Disabled>
        );
    };
    

    Content Editable

    const ContentEditable = () => {
        return (
            <Disabled isDisabled>
                <div contentEditable tabIndex={ 0 } suppressContentEditableWarning>contentEditable
                                </div>
            </Disabled>
        );
    };
    
  • Dropdown

    View on Storybook

    View source on GitHub

    Import

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

    Props

    NameTypeDefaultRequiredDescription
    classNamestring

    The className of the global container.

    contentClassNamestring

    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.

    expandOnMobileboolean

    Opt-in prop to show popovers fullscreen on mobile.

    @default false

    focusOnMountuseFocusOnMount.Mode

    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’

    headerTitlestring

    Set this to customize the text that is shown in the dropdown’s header when it is fullscreen on mobile.

    onClose() => void

    A callback invoked when the popover should be closed.

    onToggle( willOpen: boolean ) => void

    A callback invoked when the state of the dropdown changes from open to closed and vice versa.

    popoverPropsOmit< ComponentPropsWithoutRef< typeof Popover >, 'children' >

    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.

    renderContent( props: CallbackProps ) => ReactNodeYes

    A callback invoked to render the content of the dropdown menu. Its first argument is the same as the renderToggle prop.

    renderToggle( props: CallbackProps ) => ReactNodeYes

    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
    styleCSSProperties

    The style of the global container.

    openboolean

    The controlled open state of the dropdown. Must be used in conjunction with onToggle.

    defaultOpenboolean

    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.

    Examples

    Default

    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

    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

    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

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

    A badge component for displaying labels with semantic intent.

    View on Storybook

    View source on GitHub

    Import

    import { Badge } 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.

    childrenstringYes

    The text to display in the badge.

    intent| 'high' | 'medium' | 'low' | 'stable' | 'informational' | 'draft' | 'none''none'

    The semantic intent of the badge, communicating its meaning through color.

    @default “none”

    Examples

    All Intents

    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

    const High = () => (
        <>
            <Badge intent="high">Payment declined</Badge>
            <Badge intent="high">Security issue</Badge>
        </>
    );
    

    Medium

    const Medium = () => (
        <>
            <Badge intent="medium">Approval required</Badge>
            <Badge intent="medium">Review needed</Badge>
        </>
    );
    

    Low

    const Low = () => (
        <>
            <Badge intent="low">Pending</Badge>
            <Badge intent="low">Queued</Badge>
        </>
    );
    

    Informational

    const Informational = () => (
        <>
            <Badge intent="informational">Scheduled</Badge>
            <Badge intent="informational">Beta</Badge>
        </>
    );
    

    Draft

    const Draft = () => (
        <>
            <Badge intent="draft">Draft</Badge>
            <Badge intent="draft">Unpublished</Badge>
        </>
    );
    

    Stable

    const Stable = () => (
        <>
            <Badge intent="stable">Healthy</Badge>
            <Badge intent="stable">Active</Badge>
        </>
    );
    

    None

    const None = () => (
        <>
            <Badge intent="none">Inactive</Badge>
            <Badge intent="none">Expired</Badge>
        </>
    );
    

    Comment Status

    const CommentStatus = () => (
        <>
            <Badge intent="none">Approved</Badge>
            <Badge intent="medium">Approval required</Badge>
        </>
    );
    

    Page Status

    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

    const PluginStatus = () => (
        <>
            <Badge intent="stable">Active</Badge>
            <Badge intent="none">Inactive</Badge>
        </>
    );
    

    Default

    const Default = () => <Badge>Badge</Badge>;
    

    High

    const High = () => <Badge intent="high" />;
    

    Medium

    const Medium = () => <Badge intent="medium" />;
    

    Low

    const Low = () => <Badge intent="low" />;
    

    Stable

    const Stable = () => <Badge intent="stable" />;
    

    Informational

    const Informational = () => <Badge intent="informational" />;
    

    Draft

    const Draft = () => <Badge intent="draft" />;
    

    None

    const None = () => <Badge intent="none" />;
    

    All Intents

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