Category: Overlays

  • Modal

    Modal

    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.

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

    View on Storybook

    View in Figma

    View source on GitHub

    Props

    NameDefaultDescription
    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; }

    bodyOpenClassName

    string

    Class name added to the body element when the modal is open.

    children Required

    React.ReactNode

    The children elements.

    className

    string

    If this property is added, it will an additional class name to the modal content div.

    closeButtonLabel

    string

    Label on the close button.

    contentLabel

    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.

    focusOnMount

    useFocusOnMount.Mode | 'firstContentElement'

    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.
    headerActions

    React.ReactNode

    Elements that are injected into the modal header to the left of the close button (if rendered). Hidden if __experimentalHideHeader is true.

    icon

    React.JSX.Element

    If this property is added, an icon will be added before the title.

    isDismissible

    boolean

    If this property is set to false, the modal will not display a close icon and cannot be dismissed.

    isFullScreen

    boolean

    This property when set to true will render a full screen modal.

    size

    'small' | 'medium' | 'large' | 'fill'

    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.

    onKeyDown

    React.KeyboardEventHandler< HTMLDivElement >

    Handle the key down on the modal frame div.

    onRequestClose Required

    ( event?: React.KeyboardEvent< HTMLDivElement > | React.SyntheticEvent ) => void

    This function is called to indicate that the modal should be closed.

    overlayClassName

    string

    If this property is added, it will an additional class name to the modal overlay div.

    role

    React.AriaRole

    If this property is added, it will override the default role of the modal.

    shouldCloseOnClickOutside

    boolean

    If this property is added, it will determine whether the modal requests to close when a mouse click occurs outside of the modal content.

    shouldCloseOnEsc

    boolean

    If this property is added, it will determine whether the modal requests to close when the escape key is pressed.

    style

    React.CSSProperties

    If this property is added, it will be added to the modal frame div.

    title

    string

    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.

    __experimentalHideHeader

    boolean

    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.

    Examples

    Default

    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

    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

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

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

    View on Storybook

    View source on GitHub

    Props

    NameDefaultDescription
    name'Popover'

    string

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

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

    Tooltip

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

    View on Storybook

    View in Figma

    View source on GitHub

    Props

    NameDefaultDescription
    children Required

    React.ReactElement

    The anchor for the tooltip.

    Note: Accepts only one child element.

    className

    string

    Custom class name for the tooltip.

    hideOnClick

    boolean

    Option to hide the tooltip when the anchor is clicked.

    delay

    number

    The amount of time in milliseconds to wait before showing the tooltip.

    placement

    Placement

    Where the tooltip should be positioned relative to its parent.

    shortcut

    ShortcutProps[ 'shortcut' ]

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

    text

    string

    The text shown in the tooltip when anchor element is focused or hovered.

    Examples

    Default

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

    Keyboard Shortcut

    const KeyboardShortcut = ( props ) => (
    	<Tooltip { ...props } />
    );
    

    Nested

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

    ConfirmDialog

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

    View on Storybook

    View in Figma

    View source on GitHub

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

    Dropdown

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

    View on Storybook

    View in Figma

    View source on GitHub

    Props

    NameDefaultDescription
    className

    string

    The className of the global container.

    contentClassName

    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.

    expandOnMobile

    boolean

    Opt-in prop to show popovers fullscreen on mobile.

    focusOnMount

    useFocusOnMount.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.
    headerTitle

    string

    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.

    popoverProps

    Omit< 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 Required

    ( props: CallbackProps ) => ReactNode

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

    renderToggle Required

    ( 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
    style

    CSSProperties

    The style of the global container.

    open

    boolean

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

    defaultOpen

    boolean

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