Manifest Debugger

Using react-component-meta. Generation took 14.8s.

Components

Autocomplete.Root

design-system-components-form-primitives-autocomplete · ../packages/ui/src/form/primitives/autocomplete/stories/index.story.tsx
Low-level primitive for an autocomplete input that suggests options as you type. Unlike `Combobox`, the input can contain free-form text and suggestions only optionally autocomplete the text. There are currently no plans for higher-level components of this primitive in this package. Use the primitives directly, and remember to label the input field, usually by using the `Field` component.
Prop types (react-component-meta) 34 prop types
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::Root
Props:
/**
 * A ref to imperative actions.
 * - `unmount`: Ends the closing phase of the autocomplete after an externally controlled closing animation finishes.
 * Call `preventUnmountOnClose()` in `onOpenChange` first, otherwise the autocomplete completes closing on its own.
 * Whether it leaves the DOM is decided by `keepMounted` on the portal.
 * - `close`: Closes the autocomplete imperatively when called.
 */
actionsRef?: RefObject<AutocompleteRootActions | null>

/**
 * Whether the first matching item is highlighted automatically.
 * - `true`: highlight after the user types and keep the highlight while the query changes.
 * - `'always'`: always highlight the first item.
 */
autoHighlight?: boolean | "always" | undefined = false

children?: ReactNode

/**
 * Whether the popup is initially open.
 * 
 * To render a controlled popup, use the `open` prop instead.
 */
defaultOpen?: boolean = false

/**
 * The uncontrolled input value of the autocomplete when it's initially rendered.
 * 
 * To render a controlled autocomplete, use the `value` prop instead.
 */
defaultValue?: string | number | readonly string[] | undefined

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

/**
 * Filter function used to match items against the input query.
 */
filter?: ((item: unknown, query: string, itemToString?: ((item: unknown) => string) | undefined) => boolean) | null | undefined

/**
 * Filtered items to display in the list.
 * When provided, the list uses these items instead of filtering the `items` prop internally.
 * When `items` is also provided, this array must preserve its flat or grouped structure.
 * Nullish entries are not supported, as in `items`.
 * Use when you want to control filtering logic externally with the `useFilter()` hook.
 */
filteredItems?: readonly unknown[] | readonly Group<unknown>[] | undefined

/**
 * Identifies the form that owns the internal input.
 * Useful when the autocomplete is rendered outside the form.
 */
form?: string

/**
 * Whether list items are presented in a grid layout.
 * When enabled, arrow keys navigate across rows and columns inferred from DOM rows.
 */
grid?: boolean = false

/**
 * Whether moving the pointer over items should highlight them.
 * Disabling this prop allows CSS `:hover` to be differentiated from the `:focus` (`data-highlighted`) state.
 */
highlightItemOnHover?: boolean = true

/**
 * The id of the component.
 */
id?: string

/**
 * Whether the list is rendered inline without using the component's own popup.
 * 
 * Specify `open` unconditionally in conjunction with this prop so the list is considered
 * visible: `<Autocomplete.Root inline open>`
 */
inline?: boolean = false

/**
 * A ref to the hidden input element.
 */
inputRef?: Ref<HTMLInputElement> | undefined

/**
 * The items to be displayed in the list.
 * Can be either a flat array of items or an array of groups with items.
 * Nullish entries are not supported: remove them from the data before passing it.
 */
items?: readonly unknown[]

/**
 * When the item values are objects (`<Autocomplete.Item value={object}>`), this function converts the object value to a string representation for both display in the input and form submission.
 * If the shape of the object is `{ value, label }`, the label will be used automatically without needing to specify this prop.
 */
itemToStringValue?: (itemValue: unknown) => string

/**
 * Whether the highlighted item should be preserved when the pointer leaves the list.
 */
keepHighlight?: boolean = false

/**
 * The maximum number of items to display in the list.
 */
limit?: number = -1

/**
 * The locale to use for string comparison.
 * Defaults to the user's runtime locale.
 */
locale?: LocalesArgument

/**
 * Whether to loop keyboard focus back to the input when the end of the list is reached while using the arrow keys. The first item can then be reached by pressing <kbd>ArrowDown</kbd> again from the input, or the last item can be reached by pressing <kbd>ArrowUp</kbd> from the input.
 * The input is always included in the focus loop per [ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/).
 * When disabled, focus does not move when on the last element and the user presses <kbd>ArrowDown</kbd>, or when on the first element and the user presses <kbd>ArrowUp</kbd>.
 */
loopFocus?: boolean = true

/**
 * Determines if the popup enters a modal state when open.
 * - `true`: user interaction is limited to the popup: document page scroll is locked and pointer interactions on outside elements are disabled.
 * - `false`: user interaction with the rest of the document is allowed.
 * 
 * On touch devices, a `true` modal blocks outside taps but leaves the page scrollable unless the popup spans nearly the full viewport width, matching native iOS behavior.
 */
modal?: boolean = false

/**
 * Controls how the autocomplete behaves with respect to list filtering and inline autocompletion.
 * - `list` (default): items are dynamically filtered based on the input value. The input value does not change based on the active item.
 * - `both`: items are dynamically filtered based on the input value, which will temporarily change based on the active item (inline autocompletion).
 * - `inline`: items are static (not filtered), and the input value will temporarily change based on the active item (inline autocompletion).
 * - `none`: items are static (not filtered), and the input value will not change based on the active item.
 */
mode?: "list" | "none" | "inline" | "both" = 'list'

/**
 * Identifies the field when a form is submitted.
 */
name?: string

/**
 * Callback fired when an item is highlighted or unhighlighted.
 * Receives the highlighted item value (or `undefined` if no item is highlighted) and event details with a `reason` property describing why the highlight changed.
 * The `reason` can be:
 * - `'keyboard'`: the highlight changed due to keyboard navigation.
 * - `'pointer'`: the highlight changed due to pointer hovering. The event may be a `MouseEvent`
 *   rather than a `PointerEvent`.
 * - `'none'`: the highlight changed for another reason, such as typing, `autoHighlight`, the
 *   item list changing, or the popup opening or closing.
 */
onItemHighlighted?: (highlightedValue: unknown, eventDetails: HighlightEventDetails) => void

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

/**
 * Event handler called after any animations complete when the popup is opened or closed.
 */
onOpenChangeComplete?: (open: boolean) => void

/**
 * Event handler called when the input value of the autocomplete changes.
 */
onValueChange?: (value: string, eventDetails: AutocompleteRootChangeEventDetails) => void

/**
 * Whether the popup is currently open. Use when controlled.
 */
open?: boolean

/**
 * Whether the popup opens when clicking the input.
 */
openOnInputClick?: boolean = false

/**
 * Whether the user should be unable to choose a different option from the popup.
 */
readOnly?: boolean = false

/**
 * Whether the user must choose a value before submitting a form.
 */
required?: boolean = false

/**
 * Whether clicking an item should submit the autocomplete's owning form.
 * By default, clicking an item via a pointer or <kbd>Enter</kbd> key does not submit the owning form.
 * Useful when the autocomplete is used as a single-field form search input.
 */
submitOnItemClick?: boolean = false

/**
 * The input value of the autocomplete. Use when controlled.
 */
value?: string | number | readonly string[] | undefined

/**
 * Whether the items are being externally virtualized.
 */
virtualized?: boolean = false
Imports
import {
  Clear,
  Collection,
  Empty,
  Group,
  GroupLabel,
  Input,
  InputGroup,
  Item,
  ItemDescription,
  ItemLabel,
  List,
  ListBody,
  Popup,
  Portal,
  Positioner,
  Root,
  Row,
  Separator,
  Status,
  Value,
  Icon,
  InputLayout,
  Spinner,
  Stack,
  VisuallyHidden,
} from '@wordpress/ui';
import { Fragment } from '@wordpress/element';
import { URLS, COMMANDS, GROUPED_COMMANDS, EMOJI_GROUPS } from './fixtures';
import * as Autocomplete from '../index';
import { Input } from '../../input';
import { InputLayout } from '../../input-layout';
import { Icon } from '../../../../icon';
import { search } from '@wordpress/icons';
import { longLabelPopupItems } from '../../../stories/shared';
Default incomplete example
The input accepts free-form text while suggesting matching items.
const Default = () => <Autocomplete.Root items={URLS}>{[
        <Autocomplete.Input
            aria-label="URL"
            placeholder="Enter a URL"
            key="input"
        />,
        <Autocomplete.Popup key="popup">
            <Autocomplete.Empty>No matching items.</Autocomplete.Empty>
            <Autocomplete.List>
                <Autocomplete.ListBody>
                    <Autocomplete.Collection>
                        { ( item: FixtureItem ) => (
                            <Autocomplete.Item
                                key={ item.id }
                                value={ item }
                            >
                                <Autocomplete.ItemLabel>
                                    { item.value }
                                </Autocomplete.ItemLabel>
                            </Autocomplete.Item>
                        ) }
                    </Autocomplete.Collection>
                </Autocomplete.ListBody>
            </Autocomplete.List>
        </Autocomplete.Popup>,
    ]}</Autocomplete.Root>;
Incomplete snippet: `FixtureItem` could not be resolved statically.
With Item Descriptions incomplete example
Item descriptions contribute to each suggestion's accessible description.
const WithItemDescriptions = () => <Autocomplete.Root items={URLS.slice( 0, 3 )}>{[
        <Autocomplete.Input aria-label="URL" key="input" />,
        <Autocomplete.Popup key="popup">
            <Autocomplete.List>
                <Autocomplete.ListBody>
                    <Autocomplete.Collection>
                        { ( item: FixtureItem ) => (
                            <Autocomplete.Item
                                key={ item.id }
                                value={ item }
                            >
                                <Autocomplete.ItemLabel>
                                    { item.value }
                                </Autocomplete.ItemLabel>
                                <Autocomplete.ItemDescription>
                                    Suggested URL
                                </Autocomplete.ItemDescription>
                            </Autocomplete.Item>
                        ) }
                    </Autocomplete.Collection>
                </Autocomplete.ListBody>
            </Autocomplete.List>
        </Autocomplete.Popup>,
    ]}</Autocomplete.Root>;
Incomplete snippet: `FixtureItem` could not be resolved statically.
Open Only On Match story ok
Controls the popup so it only opens when there is at least one match.
const OpenOnlyOnMatch = args => {
    const [ open, setOpen ] = useState( false );
    const [ filteredItems, setFilteredItems ] = useState( URLS );

    return (
        <Autocomplete.Root
            items={ URLS }
            open={ open }
            onOpenChange={ ( nextOpen ) => {
                setOpen( nextOpen && filteredItems.length > 0 );
            } }
            onValueChange={ ( value, ...changeArgs ) => {
                const matches = URLS.filter( ( bookmark ) =>
                    bookmark.value
                        .toLowerCase()
                        .includes( value.toLowerCase() )
                );
                setFilteredItems( matches );
                setOpen( value.length > 0 && matches.length > 0 );
                args.onValueChange?.( value, ...changeArgs );
            } }
            filteredItems={ filteredItems }>
            <Autocomplete.Input aria-label="URL" placeholder="Enter a URL" />
            <Autocomplete.Popup>
                <Autocomplete.List>
                    <Autocomplete.ListBody>
                        <Autocomplete.Collection>
                            { ( item: FixtureItem ) => (
                                <Autocomplete.Item
                                    key={ item.id }
                                    value={ item }
                                >
                                    <Autocomplete.ItemLabel>
                                        { item.value }
                                    </Autocomplete.ItemLabel>
                                </Autocomplete.Item>
                            ) }
                        </Autocomplete.Collection>
                    </Autocomplete.ListBody>
                </Autocomplete.List>
            </Autocomplete.Popup>
        </Autocomplete.Root>
    );
};
Async Items story ok
Fetches matching items asynchronously. `Status` shows loading, then a visually hidden result count. Use `Empty` for no results.
const AsyncItems = args => {
    const [ query, setQuery ] = useState( '' );
    const [ loading, setLoading ] = useState( false );
    const [ results, setResults ] = useState< typeof URLS >( [] );
    const timeoutRef = useRef< ReturnType< typeof setTimeout > >( null );

    return (
        <Autocomplete.Root
            items={ results }
            value={ query }
            onValueChange={ ( newValue, ...changeArgs ) => {
                setQuery( newValue );
                setLoading( true );
                setResults( [] );
                if ( timeoutRef.current ) {
                    clearTimeout( timeoutRef.current );
                }
                timeoutRef.current = setTimeout( () => {
                    setResults(
                        URLS.filter( ( item ) =>
                            item.value
                                .toLowerCase()
                                .includes( newValue.toLowerCase() )
                        )
                    );
                    setLoading( false );
                }, 500 );
                args.onValueChange?.( newValue, ...changeArgs );
            } }>
            <Autocomplete.Input aria-label="URL" placeholder="Enter a URL" />
            <Autocomplete.Popup>
                <Autocomplete.Status>
                    { loading ? (
                        <Stack direction="row" gap="sm" align="center">
                            <Spinner />
                            Loading…
                        </Stack>
                    ) : (
                        <HiddenResultCount />
                    ) }
                </Autocomplete.Status>
                <Autocomplete.Empty>
                    { loading ? null : 'No matching items.' }
                </Autocomplete.Empty>
                <Autocomplete.List>
                    <Autocomplete.ListBody>
                        <Autocomplete.Collection>
                            { ( item: FixtureItem ) => (
                                <Autocomplete.Item
                                    key={ item.id }
                                    value={ item }
                                >
                                    <Autocomplete.ItemLabel>
                                        { item.value }
                                    </Autocomplete.ItemLabel>
                                </Autocomplete.Item>
                            ) }
                        </Autocomplete.Collection>
                    </Autocomplete.ListBody>
                </Autocomplete.List>
            </Autocomplete.Popup>
        </Autocomplete.Root>
    );
};
Inline story ok
The suggestion list can be rendered inline by enabling `inline` and `open`.
const Inline = args => {
    const [ value, setValue ] = useState( '' );

    return (
        <Autocomplete.Root
            items={COMMANDS}
            inline
            open
            value={ value }
            onValueChange={ ( newValue, ...changeArgs ) => {
                setValue( newValue );
                args.onValueChange?.( newValue, ...changeArgs );
            } }>
            <Autocomplete.Input aria-label="Command" placeholder="Type a command" />
            <div
                style={ {
                    minHeight: '200px',
                    maxHeight: '200px',
                    marginTop: 8,
                    overflow: 'auto',
                } }>
                <Autocomplete.Empty>No commands found.</Autocomplete.Empty>
                <Autocomplete.List>
                    <Autocomplete.Collection>
                        { ( command: FixtureItem ) => (
                            <Autocomplete.Item
                                key={ command.id }
                                value={ command }
                            >
                                <Autocomplete.ItemLabel>
                                    { command.value }
                                </Autocomplete.ItemLabel>
                            </Autocomplete.Item>
                        ) }
                    </Autocomplete.Collection>
                </Autocomplete.List>
            </div>
        </Autocomplete.Root>
    );
};
With Search Icon And Clear Button incomplete example
const WithSearchIconAndClearButton = () => <Autocomplete.Root items={URLS}>{[
        <Autocomplete.InputGroup key="inputGroup">
            <Autocomplete.Input
                aria-label="Search URLs"
                placeholder="Search URLs"
                render={
                    <Input
                        prefix={
                            <InputLayout.Slot padding="minimal">
                                <Icon icon={ search } />
                            </InputLayout.Slot>
                        }
                        suffix={
                            <InputLayout.Slot padding="minimal">
                                <Autocomplete.Clear />
                            </InputLayout.Slot>
                        }
                    />
                }
            />
        </Autocomplete.InputGroup>,
        <Autocomplete.Popup key="popup">
            <Autocomplete.Empty>No matching items.</Autocomplete.Empty>
            <Autocomplete.List>
                <Autocomplete.ListBody>
                    <Autocomplete.Collection>
                        { ( item: FixtureItem ) => (
                            <Autocomplete.Item
                                key={ item.id }
                                value={ item }
                            >
                                <Autocomplete.ItemLabel>
                                    { item.value }
                                </Autocomplete.ItemLabel>
                            </Autocomplete.Item>
                        ) }
                    </Autocomplete.Collection>
                </Autocomplete.ListBody>
            </Autocomplete.List>
        </Autocomplete.Popup>,
    ]}</Autocomplete.Root>;
Incomplete snippet: `FixtureItem` could not be resolved statically.
Inline Mention Autocomplete story ok
Experimental: Inline autocomplete triggered by `@`.
const InlineMentionAutocomplete = function Template( args ) {
    const inputRef = useRef< HTMLInputElement >( null );
    const [ value, setValue ] = useState( '' );
    const [ open, setOpen ] = useState( false );
    const [ filteredItems, setFilteredItems ] = useState< FixtureItem[] >(
        []
    );
    const triggerInfo = useRef< {
        offset: number;
        query: string;
    } | null >( null );

    function findTrigger( text: string, caretPos: number ) {
        const textBeforeCaret = text.slice( 0, caretPos );
        const triggerIndex = textBeforeCaret.lastIndexOf( '@' );
        if ( triggerIndex < 0 ) {
            return null;
        }

        const query = textBeforeCaret.slice( triggerIndex + 1 );
        if ( /\s/.test( query ) ) {
            return null;
        }
        if ( triggerIndex > 0 && ! /\s/.test( text[ triggerIndex - 1 ] ) ) {
            return null;
        }

        return { offset: triggerIndex, query };
    }

    function handleValueChange(
        newValue: string,
        details: { reason: string }
    ) {
        const trigger = triggerInfo.current;

        if ( details.reason === 'item-press' && trigger ) {
            const before = value.slice( 0, trigger.offset );
            const afterEndPos = trigger.offset + 1 + trigger.query.length;
            const after = value.slice( afterEndPos );
            const needsSpace = after.length > 0 && after[ 0 ] !== ' ';
            const inserted = `@${ newValue }${ needsSpace ? ' ' : '' }`;
            const fullValue = before + inserted + after;

            setValue( fullValue );
            triggerInfo.current = null;
            setOpen( false );

            const caretPos = before.length + inserted.length;
            requestAnimationFrame( () => {
                inputRef.current?.setSelectionRange( caretPos, caretPos );
                inputRef.current?.focus();
            } );
            return;
        }

        setValue( newValue );

        const input = inputRef.current;
        if ( ! input ) {
            return;
        }

        const caretPos = input.selectionStart ?? 0;
        const detected = findTrigger( newValue, caretPos );

        if ( detected ) {
            triggerInfo.current = detected;
            const matches = USERS.filter( ( user ) =>
                user.value
                    .toLowerCase()
                    .startsWith( detected.query.toLowerCase() )
            );
            setFilteredItems( matches );
            setOpen( matches.length > 0 );
        } else {
            triggerInfo.current = null;
            setOpen( false );
        }
    }

    return (
        <Autocomplete.Root
            items={ USERS }
            value={ value }
            onValueChange={ ( newValue, ...changeArgs ) => {
                handleValueChange( newValue, ...changeArgs );
                args.onValueChange?.( newValue, ...changeArgs );
            } }
            filteredItems={ filteredItems }
            open={ open }
            onOpenChange={ ( nextOpen ) => {
                if ( ! nextOpen ) {
                    setOpen( false );
                    triggerInfo.current = null;
                }
            } }
            mode="none"
            openOnInputClick={ false }
            autoHighlight
        >
            <Autocomplete.Input
                ref={ inputRef }
                aria-label="Comment"
                placeholder="Type @ to mention someone"
            />

            <Autocomplete.Popup>
                <Autocomplete.List>
                    <Autocomplete.ListBody>
                        <Autocomplete.Collection>
                            { ( item: FixtureItem ) => (
                                <Autocomplete.Item
                                    key={ item.id }
                                    value={ item }
                                >
                                    <Autocomplete.ItemLabel>
                                        { item.value }
                                    </Autocomplete.ItemLabel>
                                </Autocomplete.Item>
                            ) }
                        </Autocomplete.Collection>
                    </Autocomplete.ListBody>
                </Autocomplete.List>
            </Autocomplete.Popup>
        </Autocomplete.Root>
    );
};
With Custom z-index incomplete example
Popovers in Gutenberg are managed with explicit z-index values, which can create situations where an autocomplete popup renders below another popover when you want it above. The `--wp-ui-autocomplete-z-index` CSS variable controls the z-index of the `Autocomplete` positioner. Override it either: - **Globally**, by setting the variable on `:root` or `body` (raises every `Autocomplete` popup in the page), or - **Per instance**, by passing an `Autocomplete.Portal` with a `style` (or `className`) to `Autocomplete.Popup`'s `portal` prop. The variable cascades from the portal wrapper to everything rendered inside it. This story demonstrates the per-instance approach.
const WithCustomZIndex = () => <Autocomplete.Root items={URLS}>{[
        <Autocomplete.Input
            aria-label="URL"
            placeholder="Enter a URL"
            key="input"
        />,
        <Autocomplete.Popup
            portal={
                <Autocomplete.Portal
                    style={ { '--wp-ui-autocomplete-z-index': '9999' } }
                />
            }
            key="popup"
        >
            <Autocomplete.List>
                <Autocomplete.ListBody>
                    <Autocomplete.Collection>
                        { ( item: FixtureItem ) => (
                            <Autocomplete.Item
                                key={ item.id }
                                value={ item }
                            >
                                <Autocomplete.ItemLabel>
                                    { item.value }
                                </Autocomplete.ItemLabel>
                            </Autocomplete.Item>
                        ) }
                    </Autocomplete.Collection>
                </Autocomplete.ListBody>
            </Autocomplete.List>
        </Autocomplete.Popup>,
    ]}</Autocomplete.Root>;
Incomplete snippet: `FixtureItem` could not be resolved statically.
Grouped incomplete example
Suggestions can be organized into labeled groups with `Autocomplete.Group` and `Autocomplete.GroupLabel`.
const Grouped = () => <Autocomplete.Root items={GROUPED_COMMANDS}>{[
        <Autocomplete.Input
            aria-label="Command"
            placeholder="Type a command"
            key="input"
        />,
        <Autocomplete.Popup key="popup">
            <Autocomplete.Empty>No matching items.</Autocomplete.Empty>
            <Autocomplete.List>
                <Autocomplete.ListBody>
                    <Autocomplete.Collection>
                        { ( group: FixtureGroup ) => (
                            <Autocomplete.Group
                                key={ group.label }
                                items={ group.items }
                            >
                                <Autocomplete.GroupLabel>
                                    { group.label }
                                </Autocomplete.GroupLabel>
                                <Autocomplete.Collection>
                                    { ( item: FixtureItem ) => (
                                        <Autocomplete.Item
                                            key={ item.id }
                                            value={ item }
                                        >
                                            <Autocomplete.ItemLabel>
                                                { item.value }
                                            </Autocomplete.ItemLabel>
                                        </Autocomplete.Item>
                                    ) }
                                </Autocomplete.Collection>
                            </Autocomplete.Group>
                        ) }
                    </Autocomplete.Collection>
                </Autocomplete.ListBody>
            </Autocomplete.List>
        </Autocomplete.Popup>,
    ]}</Autocomplete.Root>;
Incomplete snippet: `FixtureGroup`, `FixtureItem` could not be resolved statically.
With Separator incomplete example
Use `Autocomplete.Separator` to set choices apart from each other.
const WithSeparator = () => <Autocomplete.Root
    items={[ ...COMMANDS.slice( 0, 3 ), { id: 'help', value: 'Get help' } ]}
    openOnInputClick>{[
        <Autocomplete.Input
            aria-label="Command"
            placeholder="Type a command"
            key="input"
        />,
        <Autocomplete.Popup key="popup">
            <Autocomplete.List>
                <Autocomplete.ListBody>
                    <Autocomplete.Collection>
                        { ( item: FixtureItem, index: number ) => (
                            <Fragment key={ item.id }>
                                { item.id === 'help' && index > 0 && (
                                    <Autocomplete.Separator />
                                ) }
                                <Autocomplete.Item value={ item }>
                                    <Autocomplete.ItemLabel>
                                        { item.value }
                                    </Autocomplete.ItemLabel>
                                </Autocomplete.Item>
                            </Fragment>
                        ) }
                    </Autocomplete.Collection>
                </Autocomplete.ListBody>
            </Autocomplete.List>
        </Autocomplete.Popup>,
    ]}</Autocomplete.Root>;
Incomplete snippet: `FixtureItem` could not be resolved statically.
Grid story ok
`Autocomplete.Row` groups multiple `Autocomplete.Item` cells into grid rows. Enable `grid` on `Autocomplete.Root` so the listbox uses grid navigation.
const Grid = () => {
    return (
        <Autocomplete.Root items={EMOJI_GROUPS} inline open grid>
            <Autocomplete.Input aria-label="Search emojis" placeholder="Search emojis" />
            <div
                style={ {
                    marginTop: 'var(--wpds-dimension-gap-sm)',
                } }>
                <Autocomplete.Empty>No matching emojis.</Autocomplete.Empty>
                <Autocomplete.List>
                    { ( group: ( typeof EMOJI_GROUPS )[ number ] ) => (
                        <Autocomplete.Group
                            key={ group.value }
                            items={ group.items }
                        >
                            <Autocomplete.GroupLabel>
                                { group.label }
                            </Autocomplete.GroupLabel>
                            { chunkItems( group.items, EMOJI_COLUMNS ).map(
                                ( row, rowIndex ) => (
                                    <Autocomplete.Row
                                        key={ rowIndex }
                                        style={ emojiPickerRowStyle }
                                    >
                                        { row.map( ( emoji ) => (
                                            <Autocomplete.Item
                                                key={ emoji.value }
                                                value={ emoji }
                                                aria-label={ emoji.label }
                                                style={
                                                    emojiPickerCellStyle
                                                }
                                            >
                                                <Autocomplete.ItemLabel
                                                    style={
                                                        emojiPickerLabelStyle
                                                    }
                                                >
                                                    <span aria-hidden="true">
                                                        { emoji.emoji }
                                                    </span>
                                                </Autocomplete.ItemLabel>
                                            </Autocomplete.Item>
                                        ) ) }
                                    </Autocomplete.Row>
                                )
                            ) }
                        </Autocomplete.Group>
                    ) }
                </Autocomplete.List>
            </div>
        </Autocomplete.Root>
    );
};
Popup Width story ok
Use `width` on `Autocomplete.Popup` to constrain the popup relative to a narrow anchor.
const PopupWidth = () => <Autocomplete.Root items={longLabelPopupItems.map( ( item ) => item.label )}>
    <Autocomplete.Input aria-label="Label" />
    <Autocomplete.Popup width="sm">
        <Autocomplete.List>
            <Autocomplete.ListBody>
                <Autocomplete.Collection>
                    { ( item: string ) => (
                        <Autocomplete.Item key={ item } value={ item }>
                            <Autocomplete.ItemLabel>
                                { item }
                            </Autocomplete.ItemLabel>
                        </Autocomplete.Item>
                    ) }
                </Autocomplete.Collection>
            </Autocomplete.ListBody>
        </Autocomplete.List>
    </Autocomplete.Popup>
</Autocomplete.Root>;
Autocomplete.Portal 5 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
Used to apply custom portal behavior to `Autocomplete`'s popup content. `container` defaults to the `@wordpress/ui` compat overlay slot.
import { Portal } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::Portal (react-component-meta)
/**
 * CSS class name to apply to the element.
 */
className?: string

/**
 * A parent element to render the portal element into.
 */
container?: HTMLElement | ShadowRoot | RefObject<HTMLElement | ShadowRoot | null> | null | undefined

/**
 * Whether to keep the portal mounted in the DOM while the popup is hidden.
 */
keepMounted?: boolean = false

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Autocomplete.Positioner 15 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
Used to apply custom positioning to `Autocomplete`'s popup content.
import { Positioner } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::Positioner (react-component-meta)
/**
 * How to align the popup relative to the specified side.
 */
align?: "center" | "end" | "start" = 'center'

/**
 * Additional offset along the alignment axis in pixels.
 * Also accepts a function that returns the offset to read the dimensions of the anchor
 * and positioner elements, along with its side and alignment.
 * 
 * The function takes a `data` object parameter with the following properties:
 * - `data.anchor`: the dimensions of the anchor element with properties `width` and `height`.
 * - `data.positioner`: the dimensions of the positioner element with properties `width` and `height`.
 * - `data.side`: which side of the anchor element the positioner is aligned against.
 * - `data.align`: how the positioner is aligned relative to the specified side.
 */
alignOffset?: number | OffsetFunction | undefined = 0

/**
 * An element to position the popup against.
 * By default, the popup will be positioned against the trigger.
 */
anchor?: Element | VirtualElement | RefObject<Element | null> | (() => Element | VirtualElement | null) | null | undefined

/**
 * Minimum distance to maintain between the arrow and the edges of the popup.
 * 
 * Use it to prevent the arrow element from hanging out of the rounded corners of a popup.
 */
arrowPadding?: number = 5

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

/**
 * Determines how to handle collisions when positioning the popup.
 * 
 * `side` controls overflow on the preferred placement axis (`top`/`bottom` or `left`/`right`):
 * - `'flip'`: keep the requested side when it fits; otherwise try the opposite side
 *   (`top` and `bottom`, or `left` and `right`).
 * - `'shift'`: never change side; keep the requested side and move the popup within
 *   the clipping boundary so it stays visible.
 * - `'none'`: do not correct side-axis overflow.
 * 
 * `align` controls overflow on the alignment axis (`start`/`center`/`end`):
 * - `'flip'`: keep side, but swap `start` and `end` when the requested alignment overflows.
 * - `'shift'`: keep side and requested alignment, then nudge the popup along the
 *   alignment axis to fit.
 * - `'none'`: do not correct alignment-axis overflow.
 * 
 * `fallbackAxisSide` controls fallback behavior on the perpendicular axis when the
 * preferred axis cannot fit:
 * - `'start'`: allow perpendicular fallback and try the logical start side first
 *   (`top` before `bottom`, or `left` before `right` in LTR).
 * - `'end'`: allow perpendicular fallback and try the logical end side first
 *   (`bottom` before `top`, or `right` before `left` in LTR).
 * - `'none'`: do not fallback to the perpendicular axis.
 * 
 * When `side` is `'shift'`, explicitly setting `align` only supports `'shift'` or `'none'`.
 * If `align` is omitted, it defaults to `'flip'`.
 */
collisionAvoidance?: CollisionAvoidance | undefined

/**
 * An element or a rectangle that delimits the area that the popup is confined to.
 */
collisionBoundary?: Boundary | undefined = 'clipping-ancestors'

/**
 * Additional space to maintain from the edge of the collision boundary.
 */
collisionPadding?: Padding | undefined = 5

/**
 * Whether to disable the popup from tracking any layout shift of its positioning anchor.
 */
disableAnchorTracking?: boolean = false

/**
 * Determines which CSS `position` property to use.
 */
positionMethod?: "fixed" | "absolute" = 'absolute'

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * Which side of the anchor element to align the popup against.
 * May automatically change to avoid collisions.
 */
side?: "left" | "right" | "bottom" | "top" | "inline-end" | "inline-start" = 'bottom'

/**
 * Distance between the anchor and the popup in pixels.
 * Also accepts a function that returns the distance to read the dimensions of the anchor
 * and positioner elements, along with its side and alignment.
 * 
 * The function takes a `data` object parameter with the following properties:
 * - `data.anchor`: the dimensions of the anchor element with properties `width` and `height`.
 * - `data.positioner`: the dimensions of the positioner element with properties `width` and `height`.
 * - `data.side`: which side of the anchor element the positioner is aligned against.
 * - `data.align`: how the positioner is aligned relative to the specified side.
 */
sideOffset?: number | OffsetFunction | undefined = 0

/**
 * Whether to maintain the popup in the viewport after
 * the anchor element was scrolled out of view.
 */
sticky?: boolean = false

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Autocomplete.Popup 9 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
import { Popup } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::Popup (react-component-meta)
children?: ReactNode

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

/**
 * Determines the element to focus when the popup is closed.
 * 
 * - `false`: Do not move focus.
 * - `true`: Move focus based on the default behavior (trigger or previously focused element).
 * - `RefObject`: Move focus to the ref element.
 * - `function`: Called with the interaction type (`mouse`, `touch`, `pen`, or `keyboard`).
 *   Return an element to focus, `true` to use the default behavior, or `false`/`undefined` to do nothing.
 */
finalFocus?: boolean | RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | void | HTMLElement | null) | undefined

/**
 * Determines the element to focus when the popup is opened.
 * 
 * - `false`: Do not move focus.
 * - `true`: Move focus based on the default behavior (first tabbable element or popup).
 * - `RefObject`: Move focus to the ref element.
 * - `function`: Called with the interaction type (`mouse`, `touch`, `pen`, or `keyboard`).
 *   Return an element to focus, `true` to use the default behavior, or `false`/`undefined` to do nothing.
 */
initialFocus?: boolean | RefObject<HTMLElement | null> | ((openType: InteractionType) => boolean | void | HTMLElement | null) | undefined

/**
 * Optional portal element, typically `<Autocomplete.Portal />` with custom
 * `container`. When omitted, `Autocomplete.Popup` uses
 * `Autocomplete.Portal` with default props. Do not pass `children` on the
 * portal element; they would be ignored.
 */
portal?: ReactElement<Omit<PortalProps, "children">, string | JSXElementConstructor<any>>

/**
 * Optional positioner element, typically `<Autocomplete.Positioner />`
 * with custom positioning props (`side`, `align`, `sideOffset`, collision
 * settings, etc.). When omitted, `Autocomplete.Popup` uses
 * `Autocomplete.Positioner` with default props. Do not pass `children` on
 * the positioner element; they would be ignored.
 */
positioner?: ReactElement<Omit<PositionerProps, "children">, string | JSXElementConstructor<any>>

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * Controls how the popup width is constrained relative to its anchor.
 * 
 * For all presets, the popup is never narrower than its anchor.
 * 
 * - `'anchor'`: Fixed width matching the anchor width.
 * - `'content'`: Width grows with item labels between the anchor and available
 *   viewport bounds.
 * - `'sm'`: Fixed width at the small surface width token (`--wpds-dimension-surface-width-sm`).
 * - `'md'`: Fixed width at the medium surface width token (`--wpds-dimension-surface-width-md`).
 * - `'lg'`: Fixed width at the large surface width token (`--wpds-dimension-surface-width-lg`).
 * - `'available'`: Fixed width at the available viewport width (`--available-width`).
 */
width?: "anchor" | "content" | "sm" | "md" | "lg" | "available" = 'anchor'
Autocomplete.Input 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
import { Input } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::Input (react-component-meta)
/**
 * CSS class name to apply to the element.
 */
className?: string

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

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined = ( props: AutocompleteInputProps ) => (
	<InputPrimitive { ...props } />
)

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Autocomplete.InputGroup 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
Wrapper around `Autocomplete.Input` that defines the visual control boundary when the input is composed with prefix/suffix slots or other elements. Without this wrapper, the popup anchors to the bare `<input>` instead of the full control. Also adds `role="group"`.
import { InputGroup } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::InputGroup (react-component-meta)
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Autocomplete.List 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
import { List } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::List (react-component-meta)
children?: ReactNode | ((item: any, index: number) => ReactNode)

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Autocomplete.ListBody 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
A layout container for the main scrolling area in the `List`, for holding `Item`s.
import { ListBody } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::ListBody (react-component-meta)
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Autocomplete.Collection 1 prop type
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
import { Collection } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::Collection (react-component-meta)
children: (item: any, index: number) => ReactNode
Autocomplete.Group 5 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
Groups related items together with an associated label rendered by `Autocomplete.GroupLabel`. When `items` is provided, child `Autocomplete.Collection` components iterate over them.
import { Group } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::Group (react-component-meta)
children?: ReactNode

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

/**
 * Items to be rendered within this group.
 * When provided, child `Collection` components will use these items.
 */
items?: readonly any[]

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Autocomplete.GroupLabel 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
Renders a label for an `Autocomplete.Group`, describing the group of items it is associated with.
import { GroupLabel } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::GroupLabel (react-component-meta)
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Autocomplete.Item 9 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
import { Item } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::Item (react-component-meta)
/**
 * One direct ItemLabel, followed by zero or more ItemDescription components.
 */
children: AutocompleteItemChildren

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

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

/**
 * The index of the item in the list. Improves performance when specified by avoiding the need to calculate the index automatically from the DOM.
 */
index?: number

/**
 * Whether the component renders a native `<button>` element when replacing it
 * via the `render` prop.
 * Set to `true` if the rendered element is a native button.
 */
nativeButton?: boolean = false

/**
 * An optional click handler for the item when selected.
 * It fires when clicking the item with the pointer, as well as when pressing `Enter` with the keyboard if the item is highlighted when the `Input` or `List` element has focus.
 */
onClick?: (event: BaseUIEvent<MouseEvent<HTMLDivElement, MouseEvent>>) => void

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * A unique value that identifies this item.
 */
value?: any = null
Autocomplete.ItemLabel 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
The primary label and accessible name of an autocomplete item.
import { ItemLabel } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::ItemLabel (react-component-meta)
/**
 * The primary label and accessible name of an autocomplete item.
 */
children: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Autocomplete.ItemDescription 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
Supplementary content for an autocomplete item. Its text contributes to the item's accessible description.
import { ItemDescription } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::ItemDescription (react-component-meta)
/**
 * Content that contributes to the autocomplete item's accessible description.
 */
children: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Autocomplete.Row 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
Groups multiple `Autocomplete.Item` cells into a single row in a grid layout. Enable `grid` on `Autocomplete.Root` to turn the listbox into a grid and use two-dimensional keyboard navigation.
import { Row } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::Row (react-component-meta)
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Autocomplete.Separator 3 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
Renders a visual separator between autocomplete items or groups.
import { Separator } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::Separator (react-component-meta)
/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Autocomplete.Value 1 prop type
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
import { Value } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::Value (react-component-meta)
children?: ReactNode | ((value: string) => ReactNode)
Autocomplete.Empty 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
import { Empty } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::Empty (react-component-meta)
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Autocomplete.Status 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
Announces a status message politely to screen readers. Use it for the status of an asynchronously loaded list. Keep this element mounted. Do not hide it with `display: none`, `hidden`, `aria-hidden`, or by omitting the component. Change or omit the children instead.
import { Status } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::Status (react-component-meta)
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Autocomplete.Clear 7 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/autocomplete/index.ts
A button that clears the input value.
import { Clear } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/autocomplete/index.ts::Clear (react-component-meta)
children?: ReactNode

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

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

/**
 * Whether the component should remain mounted in the DOM when not visible.
 */
keepMounted?: boolean = false

/**
 * Whether the component renders a native `<button>` element when replacing it
 * via the `render` prop.
 * Set to `false` if the rendered element is not a button (for example, `<div>`).
 */
nativeButton?: boolean = true

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined = (
	{
		'aria-label': ariaLabel = __( 'Clear' ),
		...props
	}: AutocompleteClearProps,
	{ disabled }: _Autocomplete.Clear.State
) => (
	<IconButton
		icon={ closeSmall }
		focusableWhenDisabled={ false }
		disabled={ disabled }
		aria-hidden={ disabled || undefined }
		size="small"
		variant="minimal"
		tone="neutral"
		label={ ariaLabel }
		{ ...props }
	/>
)

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

Badge

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

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

/**
 * The semantic intent of the badge, communicating its meaning through color.
 */
intent?: "medium" | "high" | "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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
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">Badge</Badge>;
Medium story ok
const Medium = () => <Badge intent="medium">Badge</Badge>;
Low story ok
const Low = () => <Badge intent="low">Badge</Badge>;
Stable story ok
const Stable = () => <Badge intent="stable">Badge</Badge>;
Informational story ok
const Informational = () => <Badge intent="informational">Badge</Badge>;
Draft story ok
const Draft = () => <Badge intent="draft">Badge</Badge>;
None story ok
const None = () => <Badge intent="none">Badge</Badge>;
All Intents story ok
const AllIntents = ( args ) => (
    <div
        style={ {
            display: 'grid',
            gridTemplateColumns: 'max-content min-content',
            gap: '1rem',
            color: 'var(--wpds-color-foreground-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
`BaseControl` is a low-level component used to generate labels and help text for components handling user inputs. ```jsx import { BaseControl, useBaseControlProps } from '@wordpress/components'; // Render a `BaseControl` for a textarea input const MyCustomTextareaControl = ({ children, ...baseProps }) => ( // `useBaseControlProps` is a convenience hook to get the props for the `BaseControl` // and the inner control itself. Namely, it takes care of generating a unique `id`, // properly associating it with the `label` and `help` elements. const { baseControlProps, controlProps } = useBaseControlProps( baseProps ); return ( <BaseControl { ...baseControlProps }> <textarea { ...controlProps }> { children } </textarea> </BaseControl> ); ); ```
Prop types (react-component-meta) 8 prop types
Component: ../packages/components/src/base-control/index.tsx::default
Props:
/**
 * Start opting into the new margin-free styles that will become the default in a future version.
 */
__nextHasNoMarginBottom?: boolean

/**
 * The HTML element or React component to render the component as.
 */
as?: JSXElementConstructor<any> | keyof IntrinsicElements | null | undefined

/**
 * The content to be displayed within the `BaseControl`.
 */
children: ReactNode

className?: string

/**
 * Additional description for the control.
 * 
 * Only use for meaningful description or instructions for the control. An element containing the description will be programmatically associated to the BaseControl by the means of an `aria-describedby` attribute.
 */
help?: ReactNode

/**
 * If true, the label will only be visible to screen readers.
 */
hideLabelFromVision?: boolean = false

/**
 * The HTML `id` of the control element (passed in as a child to `BaseControl`) to which labels and help text are being generated.
 * This is necessary to accessibly associate the label with that element.
 * 
 * The recommended way is to use the `useBaseControlProps` hook, which takes care of generating a unique `id` for you.
 * Otherwise, if you choose to pass an explicit `id` to this prop, you are responsible for ensuring the uniqueness of the `id`.
 */
id?: string

/**
 * If this property is added, a label will be generated using label property as the content.
 */
label?: ReactNode
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>
	);
};
BaseControl.VisualLabel 2 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/base-control/index.tsx
import { BaseControl } from '@wordpress/components';
Component: ../packages/components/src/base-control/index.tsx::default (react-component-meta)
/**
 * The HTML element or React component to render the component as.
 */
as?: JSXElementConstructor<any> | keyof IntrinsicElements | undefined

/**
 * The content to be displayed within the `BaseControl.VisualLabel`.
 */
children: ReactNode

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 (react-component-meta) 28 prop types
Component: ../packages/components/src/button/index.tsx::default
Props:
/**
 * Whether to keep the button focusable when disabled.
 */
__experimentalIsFocusable?: boolean = false

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

/**
 * Whether to keep the button focusable when disabled.
 * 
 * In most cases, it is recommended to set this to `true`. Disabling a control without maintaining focusability
 * can cause accessibility issues, by hiding their presence from screen reader users,
 * or by preventing focus from returning to a trigger element.
 * 
 * Learn more about the [focusability of disabled controls](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#focusabilityofdisabledcontrols)
 * in the WAI-ARIA Authoring Practices Guide.
 */
accessibleWhenDisabled?: boolean = false

/**
 * The button's children.
 */
children?: ReactNode

/**
 * A visually hidden accessible description for the button.
 */
describedBy?: string

/**
 * A visually hidden accessible description for the button.
 */
description?: string

/**
 * Whether the button is disabled. If `true`, this will force a `button` element
 * to be rendered, even when an `href` is given.
 * 
 * In most cases, it is recommended to also set the `accessibleWhenDisabled` prop to `true`.
 */
disabled?: boolean

/**
 * If provided, renders `a` instead of `button`.
 */
href?: string

/**
 * If provided, renders an Icon component inside the button.
 */
icon?: IconType | null | undefined

/**
 * If provided with `icon`, sets the position of icon relative to the `text`.
 */
iconPosition?: "left" | "right" = 'left'

/**
 * If provided with `icon`, sets the icon size.
 * Please refer to the Icon component for more details regarding
 * the default value of its `size` prop.
 */
iconSize?: number

/**
 * Indicates activity while a action is being performed.
 */
isBusy?: boolean

/**
 * Gives the button a default style.
 */
isDefault?: boolean

/**
 * Renders a red text-based button style to indicate destructive behavior.
 */
isDestructive?: boolean

/**
 * Gives the button a link style.
 */
isLink?: boolean

/**
 * Renders a pressed button style.
 */
isPressed?: boolean

/**
 * Gives the button a primary style.
 */
isPrimary?: boolean

/**
 * Gives the button a default style.
 */
isSecondary?: boolean

/**
 * Decreases the size of the button.
 */
isSmall?: boolean

/**
 * Gives the button a text-based style.
 */
isTertiary?: boolean

/**
 * Sets the `aria-label` of the component, if none is provided.
 * Sets the Tooltip content if `showTooltip` is provided.
 */
label?: string

/**
 * If provided with `showTooltip`, appends the Shortcut label to the tooltip content.
 * If an object is provided, it should contain `display` and `ariaLabel` keys.
 */
shortcut?: string | { display: string; ariaLabel: string; } | undefined

/**
 * If provided, renders a Tooltip component for the button.
 */
showTooltip?: boolean

/**
 * 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.
 * 
 * If the deprecated `isSmall` prop is also defined, this prop will take precedence.
 */
size?: "small" | "default" | "compact" = 'default'

/**
 * If provided with `href`, sets the `target` attribute to the `a`.
 */
target?: string

/**
 * If provided, displays the given text inside the button. If the button contains children elements, the text is displayed before them.
 */
text?: string

/**
 * If provided with `showTooltip`, sets the position of the tooltip.
 * Please refer to the Tooltip component for more details regarding the defaults.
 */
tooltipPosition?: "bottom" | "top" | "middle" | "bottom center" | "bottom left" | "bottom right" | "top center" | "top left" | "top right" | "middle center" | "middle left" | "middle right" | "bottom center left" | "bottom center right" | "bottom center bottom" | "bottom center top" | "bottom left left" | "bottom left right" | "bottom left bottom" | "bottom left top" | "bottom right left" | "bottom right right" | "bottom right bottom" | "bottom right top" | "top center left" | "top center right" | "top center bottom" | "top center top" | "top left left" | "top left right" | "top left bottom" | "top left top" | "top right left" | "top right right" | "top right bottom" | "top right top" | "middle center left" | "middle center right" | "middle center bottom" | "middle center top" | "middle left left" | "middle left right" | "middle left bottom" | "middle left top" | "middle right left" | "middle right right" | "middle right bottom" | "middle right top"

/**
 * Specifies the button's style.
 * 
 * The accepted values are:
 * 
 * 1. `'primary'` (the primary button styles)
 * 2. `'secondary'` (the default button styles)
 * 3. `'tertiary'` (the text-based button styles)
 * 4. `'link'` (the link button styles)
 */
variant?: "link" | "primary" | "secondary" | "tertiary"
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>
	);
}

Calendar

design-system-components-calendar-calendar · ../packages/ui/src/calendar/stories/index.story.tsx
`Calendar` 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 (react-component-meta) 23 prop types
Component: ../packages/ui/src/calendar/index.ts::Calendar
Props:
/**
 * Focus the first selected day (if set) or today's date (if not disabled).
 * 
 * Use this prop when the calendar should receive initial focus as it opens,
 * such as in a calendar popover. Do not use it to move focus after updates
 * to an open calendar.
 */
autoFocus?: boolean

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

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

/**
 * The initially selected date (uncontrolled).
 */
defaultValue?: 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.
 */
fixedWeeks?: boolean = false

/**
 * Use custom labels, useful for translating the component.
 * 
 * For a correct localized experience, consumers should make sure the locale
 * used for translated labels and date text is consistent.
 */
labels?: { labelNav?: (() => string) | undefined; labelGrid?: ((date: Date) => string) | undefined; labelGridcell?: ((date: Date, modifiers?: Modifiers | undefined) => string) | undefined; labelNext?: ((month: Date | undefined) => string) | undefined; labelPrevious?: ((month: Date | undefined) => string) | undefined; labelDa...

/**
 * A BCP 47 locale code or date-fns locale object used to localize date text,
 * numerals, the default text direction, and the first day of the week.
 * 
 * The locale code derives the first day of the week when the browser provides
 * that information, whether passed directly or through a date-fns locale
 * object. Use `weekStartsOn` to override this default.
 * 
 * Invalid or unsupported locale codes fall back to `en-US` for date text.
 * A date-fns locale object with an unsupported code retains its own first-day
 * setting.
 * 
 * For a correct localized experience, consumers should make sure the locale
 * used for translated labels and date text is consistent.
 * 
 * The calendar always uses a Gregorian date grid. The locale does not change
 * the underlying calendar system.
 */
locale?: string | Locale | undefined = The `enUS` locale from `date-fns/locale`

/**
 * 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.
 */
numberOfMonths?: number = 1

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

/**
 * Event handler called when the selected date changes.
 */
onValueChange?: OnValueChangeHandler<Date | null>

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

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

/**
 * The ARIA role for the calendar's root element.
 * 
 * The default `application` role helps assistive technologies pass calendar
 * navigation keys to the component. Its accessible name includes the current
 * month.
 * 
 * Changing this role can affect screen-reader keyboard navigation. Only
 * override it for a tested composition. Apply roles that require additional
 * behavior, such as `dialog`, to a wrapper.
 */
role?: AriaRole | undefined = 'application'

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

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

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * 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 from the
 * [`@date-fns/tz`](https://www.npmjs.com/package/@date-fns/tz) package
 * instead of the native `Date` object.
 */
timeZone?: string

/**
 * The selected date (controlled). Use `null` when there is no selection.
 * To render an uncontrolled calendar, use `defaultValue` instead.
 */
value?: Date | null | undefined

/**
 * The index of the first day of the week (0 - Sunday). Overrides the locale's
 * one.
 */
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 = Based on the `locale` prop when available
Imports
import { Calendar } from '@wordpress/ui';
import { fn } from 'storybook/test';
import { DISABLED_DATES_SAMPLE, firstDayOfNextMonth } from './shared';
Default story ok
const Default = () => <Calendar onMonthChange={fn()} onValueChange={fn()} endMonth={ toDate( endMonth ) } />;
Disabled Dates story ok
const DisabledDates = () => <Calendar
    onMonthChange={fn()}
    onValueChange={fn()}
    disabled={DISABLED_DATES_SAMPLE}
    endMonth={ toDate( endMonth ) } />;
With Selected Date And Month story ok
const WithSelectedDateAndMonth = () => <Calendar
    onMonthChange={fn()}
    onValueChange={fn()}
    defaultValue={firstDayOfNextMonth}
    defaultMonth={firstDayOfNextMonth}
    endMonth={ toDate( endMonth ) } />;
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 = () => <Calendar
    onMonthChange={fn()}
    onValueChange={fn()}
    showOutsideDays
    fixedWeeks
    endMonth={ toDate( endMonth ) } />;
With Time Zone story ok
When working with time zones, use the `TZDate` object from the [`@date-fns/tz`](https://www.npmjs.com/package/@date-fns/tz) package instead of the native `Date` object.
const WithTimeZone = ({ endMonth, ...args }) => {
    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 (
        <>
            <Calendar
                onMonthChange={fn()}
                timeZone="Pacific/Auckland"
                endMonth={ toDate( endMonth ) }
                value={ selected }
                onValueChange={ ( selectedDate, ...rest ) => {
                    setSelected(
                        selectedDate
                            ? new TZDate( selectedDate, args.timeZone )
                            : null
                    );
                    args.onValueChange?.( 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>
        </>
    );
};

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 (react-component-meta) 4 prop types
Component: ../packages/ui/src/card/index.ts::Root
Props:
/**
 * The content to be rendered inside the card.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Imports
import { Content, FullBleed, Header, Root, Title, Stack, Text } from '@wordpress/ui';
import * as Card from '../index';
import { Text } from '../../text';
import { Stack } from '../../stack';
Default story ok
const Default = () => <Card.Root>{[
        <Card.Header key="header">
            <Card.Title>Card title</Card.Title>
        </Card.Header>,
        <Card.Content key="content">
            <Text render={ <p /> }>
                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 render={ <p /> }>
                This is the main content area. It can contain any elements.
            </Text>
        </Card.Content>,
    ]}</Card.Root>;
Full Bleed Cover Only story ok
`Card.FullBleed` as the sole child of `Card.Content` spans edge-to-edge with no padding around it.
const FullBleedCoverOnly = () => <Card.Root>(<Card.Content>
        <Card.FullBleed>
            <div
                style={ {
                    height: 180,
                    background:
                        'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
                } }
            />
        </Card.FullBleed>
    </Card.Content>)</Card.Root>;
Full Bleed Cover With Header story ok
When `Card.FullBleed` is the sole child of `Card.Content` and a `Card.Header` sits above it, the image bumps against the card's side and bottom edges while the header retains its normal padding.
const FullBleedCoverWithHeader = () => <Card.Root>{[
        <Card.Header key="header">
            <Card.Title>Card title</Card.Title>
        </Card.Header>,
        <Card.Content key="content">
            <Card.FullBleed>
                <div
                    style={ {
                        height: 180,
                        background:
                            'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
                    } }
                />
            </Card.FullBleed>
        </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 key="header">
            <Card.Title>Featured image</Card.Title>
        </Card.Header>,
        <Card.Content
            key="content"
            render={ <Stack direction="column" gap="lg" /> }
        >
            <Card.FullBleed>
                <div
                    style={ {
                        height: 160,
                        background:
                            'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
                    } }
                />
            </Card.FullBleed>
            <Text render={ <p /> }>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>;
Full Bleed Hero With Title story ok
When `Card.FullBleed` is the **first child** of `Card.Header`, it extends flush to the card's top and side edges — ideal for hero images. Content that follows inside the header is padded normally.
const FullBleedHeroWithTitle = () => <Card.Root>{[
        <Card.Header
            key="header"
            render={ <Stack direction="column" gap="lg" /> }
        >
            <Card.FullBleed>
                <div
                    style={ {
                        height: 180,
                        background:
                            'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
                    } }
                />
            </Card.FullBleed>
            <Card.Title>Hero image card</Card.Title>
        </Card.Header>,
        <Card.Content key="content">
            <Text render={ <p /> }>
                The image above bleeds to the card&apos;s top and side
                edges.
            </Text>
        </Card.Content>,
    ]}</Card.Root>;
Full Bleed Hero Only story ok
When `Card.FullBleed` is the **only child** of `Card.Header`, it fills the header entirely — top and sides flush to the card edges, no extra padding below.
const FullBleedHeroOnly = () => <Card.Root>{[
        <Card.Header key="header">
            <Card.FullBleed>
                <div
                    style={ {
                        height: 180,
                        background:
                            'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
                    } }
                />
            </Card.FullBleed>
        </Card.Header>,
        <Card.Content key="content">
            <Text render={ <p /> }>
                The image above bleeds to the card&apos;s top and side
                edges.
            </Text>
        </Card.Content>,
    ]}</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 key="header">
            <Card.Title render={ <h2 /> }>Section heading</Card.Title>
        </Card.Header>,
        <Card.Content key="content">
            <Text render={ <p /> }>
                Semantically meaningful card content.
            </Text>
        </Card.Content>,
    ]}</Card.Root>;
Card.Header 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/card/index.ts
A structural container for the card's heading area, typically containing `Card.Title`.
import { Header } from '@wordpress/ui';
Component: ../packages/ui/src/card/index.ts::Header (react-component-meta)
/**
 * The content to be rendered inside the header.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Card.Content 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/card/index.ts
The main content area of the card.
import { Content } from '@wordpress/ui';
Component: ../packages/ui/src/card/index.ts::Content (react-component-meta)
/**
 * The content to be rendered inside the content area.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Card.FullBleed 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/card/index.ts
A container that breaks out of the card's padding to span edge-to-edge. Useful for full-width images, dividers, or embedded content. Additional edge-bumping behavior based on placement: - As the **first child** of `Card.Header`, it extends flush to the card's top edge — ideal for hero images. - As the **only child** of `Card.Content`, it extends flush to the card's top edge when `Content` is the first card section, and to the bottom edge when it is the last. Inter-sibling spacing inside `Card.Header` / `Card.Content` is consumer- managed. To add space between a hero `FullBleed` and the following siblings, compose the parent with `Stack` via the `render` prop: `<Card.Header render={ <Stack direction="column" gap="lg" /> }>`. This keeps `FullBleed` a direct child of `Card.Header` so the edge-bump still fires, while `Stack` provides the gap. Inside `CollapsibleCard`, place full-bleed media in `CollapsibleCard.Content` (not the header). The trigger/panel gap is preserved by design. Must be used as a direct child of `Card.Content` or `Card.Header`.
import { FullBleed } from '@wordpress/ui';
Component: ../packages/ui/src/card/index.ts::FullBleed (react-component-meta)
/**
 * The content to be rendered edge-to-edge, breaking out of the
 * card's padding.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Card.Title 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/card/index.ts
The title for a card. Renders as a `<div>` by default — use the `render` prop to swap in a semantic heading element when appropriate.
import { Title } from '@wordpress/ui';
Component: ../packages/ui/src/card/index.ts::Title (react-component-meta)
/**
 * The title text for the card.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined = <div />

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

Checkbox

design-system-components-form-primitives-checkbox · ../packages/ui/src/form/primitives/checkbox/stories/index.story.tsx
A low-level checkbox primitive. Prefer `CheckboxControl` for labeled items. For grouping and nested parent checkboxes, see the [Checkbox Groups](https://wordpress.github.io/gutenberg/?path=/docs/design-system-components-form-checkbox-groups--docs) documentation.
Prop types (react-component-meta) 18 prop types
Component: ../packages/ui/src/form/primitives/checkbox/index.ts::Checkbox
Props:
/**
 * Whether the checkbox is currently ticked.
 * 
 * To render an uncontrolled checkbox, use the `defaultChecked` prop instead.
 */
checked?: boolean = undefined

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

/**
 * Whether the checkbox is initially ticked.
 * 
 * To render a controlled checkbox, use the `checked` prop instead.
 */
defaultChecked?: boolean = false

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

/**
 * Identifies the form that owns the hidden input.
 * Useful when the checkbox is rendered outside the form.
 */
form?: string

/**
 * The id of the input element.
 */
id?: string

/**
 * Whether the checkbox is in a mixed state: neither ticked, nor unticked.
 */
indeterminate?: boolean = false

/**
 * A ref to access the hidden `<input>` element.
 */
inputRef?: Ref<HTMLInputElement> | undefined

/**
 * Identifies the field when a form is submitted.
 */
name?: string = undefined

/**
 * Whether the component renders a native `<button>` element when replacing it
 * via the `render` prop.
 * Set to `true` if the rendered element is a native button.
 */
nativeButton?: boolean = false

/**
 * Event handler called when the checkbox is ticked or unticked.
 */
onCheckedChange?: (checked: boolean, eventDetails: { reason: "none"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void

/**
 * Whether the checkbox controls a group of child checkboxes.
 * 
 * Must be used in a [Checkbox Group](https://base-ui.com/react/components/checkbox-group).
 */
parent?: boolean = false

/**
 * Whether the user should be unable to tick or untick the checkbox.
 */
readOnly?: boolean = false

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * Whether the user must tick the checkbox before submitting a form.
 */
required?: boolean = false

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The value submitted with the form when the checkbox is unchecked.
 * By default, unchecked checkboxes do not submit any value, matching native checkbox behavior.
 */
uncheckedValue?: string

/**
 * The checkbox's value. Identifies it within a [Checkbox Group](https://base-ui.com/react/components/checkbox-group), falling back to `name` when omitted.
 * When submitting a form, a checked box submits `value`; with no `value`, it submits the native "on".
 */
value?: string
Imports
import { Checkbox } from '@wordpress/ui';
Default story ok
const Default = () => <Checkbox aria-label="Option" />;
Checked story ok
const Checked = () => <Checkbox aria-label="Option" defaultChecked />;
Indeterminate story ok
const Indeterminate = () => <Checkbox aria-label="Option" indeterminate />;
Disabled story ok
const Disabled = () => <Checkbox aria-label="Option" disabled />;
Disabled Checked story ok
const DisabledChecked = () => <Checkbox aria-label="Option" disabled defaultChecked />;

CheckboxControl

design-system-components-form-checkboxcontrol · ../packages/ui/src/form/checkbox-control/stories/index.story.tsx
A complete checkbox field with integrated label and description. For grouping and nested parent checkboxes, see the [Checkbox Groups](https://wordpress.github.io/gutenberg/?path=/docs/design-system-components-form-checkbox-groups--docs) documentation.
Prop types (react-component-meta) 22 prop types
Component: ../packages/ui/src/form/checkbox-control/index.ts::CheckboxControl
Props:
/**
 * Whether the checkbox is currently ticked.
 * 
 * To render an uncontrolled checkbox, use the `defaultChecked` prop instead.
 */
checked?: boolean = undefined

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

/**
 * Whether the checkbox is initially ticked.
 * 
 * To render a controlled checkbox, use the `checked` prop instead.
 */
defaultChecked?: boolean = false

/**
 * The accessible description, associated using `aria-describedby`.
 * 
 * For screen reader accessibility, this should only contain plain text,
 * and no semantics such as links.
 */
description?: string

/**
 * 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?: ReactNode

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

/**
 * Identifies the form that owns the hidden input.
 * Useful when the checkbox is rendered outside the form.
 */
form?: string

/**
 * Whether to visually hide the label while keeping it accessible
 * to screen readers.
 */
hideLabelFromVision?: boolean = false

/**
 * The id of the input element.
 */
id?: string

/**
 * Whether the checkbox is in a mixed state: neither ticked, nor unticked.
 */
indeterminate?: boolean = false

/**
 * A ref to access the hidden `<input>` element.
 */
inputRef?: Ref<HTMLInputElement> | undefined

/**
 * The accessible label. All controls must be labeled.
 */
label: string

/**
 * Identifies the field when a form is submitted.
 */
name?: string = undefined

/**
 * Whether the component renders a native `<button>` element when replacing it
 * via the `render` prop.
 * Set to `true` if the rendered element is a native button.
 */
nativeButton?: boolean = false

/**
 * Event handler called when the checkbox is ticked or unticked.
 */
onCheckedChange?: (checked: boolean, eventDetails: { reason: "none"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void

/**
 * Whether the checkbox controls a group of child checkboxes.
 * 
 * Must be used in a [Checkbox Group](https://base-ui.com/react/components/checkbox-group).
 */
parent?: boolean = false

/**
 * Whether the user should be unable to tick or untick the checkbox.
 */
readOnly?: boolean = false

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * Whether the user must tick the checkbox before submitting a form.
 */
required?: boolean = false

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The value submitted with the form when the checkbox is unchecked.
 * By default, unchecked checkboxes do not submit any value, matching native checkbox behavior.
 */
uncheckedValue?: string

/**
 * The checkbox's value. Identifies it within a [Checkbox Group](https://base-ui.com/react/components/checkbox-group), falling back to `name` when omitted.
 * When submitting a form, a checked box submits `value`; with no `value`, it submits the native "on".
 */
value?: string
Imports
import { CheckboxControl } from '@wordpress/ui';
import { DETAILS_EXAMPLE } from '../../stories/shared';
Default story ok
const Default = () => <CheckboxControl label="Label" />;
With Description story ok
const WithDescription = () => <CheckboxControl label="Label" description="This is the description." />;
With Long Label story ok
const WithLongLabel = () => <CheckboxControl
    label="This is a long label that should wrap to the next line. This is a long label that should wrap to the next line. This is a long label that should wrap to the next line." />;
Visually Hidden Label story ok
const VisuallyHiddenLabel = () => <CheckboxControl label="Label" hideLabelFromVision />;
With Details story ok
const WithDetails = () => <CheckboxControl label="Label" details={DETAILS_EXAMPLE} />;
Disabled story ok
const Disabled = () => <CheckboxControl label="Label" disabled />;

CheckboxGroup

design-system-components-form-primitives-checkboxgroup · ../packages/ui/src/form/primitives/checkbox-group/stories/index.story.tsx
A low-level primitive that groups checkboxes so they share one selected-values state. Prefer composing `CheckboxControl` inside the group for labeled items. For one labeled group, pass `CheckboxGroup` to `Fieldset.Root`'s `render` prop. When a `Fieldset` contains multiple groups, give each `CheckboxGroup` its own accessible name.
Prop types (react-component-meta) 9 prop types
Component: ../packages/ui/src/form/primitives/checkbox-group/index.ts::CheckboxGroup
Props:
/**
 * Names of all checkboxes in the group. Use this when creating a parent checkbox.
 */
allValues?: string[]

/**
 * The checkboxes and optional nested items in the group.
 */
children?: ReactNode

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

/**
 * Names of the checkboxes in the group that should be initially ticked.
 * 
 * To render a controlled checkbox group, use the `value` prop instead.
 */
defaultValue?: string[]

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

/**
 * Event handler called when a checkbox in the group is ticked or unticked.
 * Provides the new value as an argument.
 */
onValueChange?: (value: string[], eventDetails: { reason: "none"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined = ( props: React.ComponentProps< typeof Stack > ) => (
	<Stack { ...props } direction="column" gap="sm" />
)

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * Names of the checkboxes in the group that should be ticked.
 * 
 * To render an uncontrolled checkbox group, use the `defaultValue` prop instead.
 */
value?: string[]
Imports
import { Checkbox, CheckboxGroup } from '@wordpress/ui';
Default story ok
const Default = () => <CheckboxGroup defaultValue={[]} aria-label="Fruit">
    { [ 'Apple', 'Banana', 'Orange' ].map( ( label ) => (
        <Checkbox key={ label } value={ label } aria-label={ label } />
    ) ) }
</CheckboxGroup>;
With Parent Checkbox story ok
`CheckboxGroup` can be used to control a group of checkboxes from a single parent checkbox. For screen reader accessibility, do not nest more than one level. See the [Checkbox Groups](?path=/docs/design-system-components-form-checkbox-groups--docs#nesting) documentation for a full example.
const WithParentCheckbox = function Template( args ) {
    const [ fruitValue, setFruitValue ] = useState( [ 'apple' ] );

    return (
        <CheckboxGroup
            value={ fruitValue }
            onValueChange={ ( nextValue, ...changeArgs ) => {
                setFruitValue( nextValue );
                args.onValueChange?.( nextValue, ...changeArgs );
            } }
            allValues={ [ 'apple', 'orange', 'banana' ] }
            aria-label="Fruit"
        >
            <Checkbox parent value="fruit" aria-label="Fruit" />
            <CheckboxGroup.NestedItems>
                <Checkbox value="apple" aria-label="Apple" />
                <Checkbox value="orange" aria-label="Orange" />
                <Checkbox value="banana" aria-label="Banana" />
            </CheckboxGroup.NestedItems>
        </CheckboxGroup>
    );
};
CheckboxGroup.NestedItems 9 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/checkbox-group/index.ts
A layout wrapper that indents nested checkbox items.
import { CheckboxGroup } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/checkbox-group/index.ts::CheckboxGroup (react-component-meta)
/**
 * The alignment of the stack items along the cross axis.
 */
align?: AlignItems | undefined = 'initial'

/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

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

/**
 * The direction of the stack.
 */
direction?: "-moz-initial" | "inherit" | "initial" | "revert" | "revert-layer" | "unset" | "row" | "column"

/**
 * The amount of space between each child element using design system tokens.
 */
gap?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" = undefined

/**
 * The alignment of the stack items along the main axis.
 */
justify?: JustifyContent | undefined = 'initial'

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * Whether the stack items should wrap to the next line.
 */
wrap?: "-moz-initial" | "inherit" | "initial" | "revert" | "revert-layer" | "unset" | "wrap" | "nowrap"

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 (react-component-meta) 8 prop types
Component: ../packages/ui/src/collapsible/index.ts::Root
Props:
/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

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

/**
 * Whether the collapsible panel is initially open.
 * 
 * To render a controlled collapsible, use the `open` prop instead.
 */
defaultOpen?: boolean = false

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

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

/**
 * Whether the collapsible panel is currently open.
 * 
 * To render an uncontrolled collapsible, use the `defaultOpen` prop 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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Imports
import { Panel, Root, Trigger } from '@wordpress/ui';
import * as Collapsible from '../index';
Default story ok
const Default = () => <Collapsible.Root>{[
        <Collapsible.Trigger key="trigger">Toggle</Collapsible.Trigger>,
        <Collapsible.Panel key="panel">
            <p>Collapsible content here.</p>
        </Collapsible.Panel>,
    ]}</Collapsible.Root>;
Default Open story ok
const DefaultOpen = () => <Collapsible.Root defaultOpen>{[
        <Collapsible.Trigger key="trigger">Toggle</Collapsible.Trigger>,
        <Collapsible.Panel key="panel">
            <p>This panel is open by default.</p>
        </Collapsible.Panel>,
    ]}</Collapsible.Root>;
Disabled story ok
const Disabled = () => <Collapsible.Root disabled>{[
        <Collapsible.Trigger key="trigger">
            Toggle (disabled)
        </Collapsible.Trigger>,
        <Collapsible.Panel key="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 HiddenUntilFoundRender() {
    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 ControlledRender() {
    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>
    );
};
Collapsible.Trigger 5 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/collapsible/index.ts
A button that opens and closes the collapsible panel. `Collapsible` is a collection of React components that combine to render a collapsible panel controlled by a button.
import { Trigger } from '@wordpress/ui';
Component: ../packages/ui/src/collapsible/index.ts::Trigger (react-component-meta)
/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

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

/**
 * Whether the component renders a native `<button>` element when replacing it
 * via the `render` prop.
 * Set to `false` if the rendered element is not a button (for example, `<div>`).
 */
nativeButton?: boolean = true

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Collapsible.Panel 6 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/collapsible/index.ts
A panel with the collapsible contents. Hidden when collapsed, visible when expanded. `Collapsible` is a collection of React components that combine to render a collapsible panel controlled by a button.
import { Panel } from '@wordpress/ui';
Component: ../packages/ui/src/collapsible/index.ts::Panel (react-component-meta)
/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

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

/**
 * Allows the browser's built-in page search to find and expand the panel contents.
 * 
 * Overrides the `keepMounted` prop and uses `hidden="until-found"`
 * to hide the element without removing it from the DOM.
 */
hiddenUntilFound?: boolean = false

/**
 * Whether to keep the element in the DOM while the panel is hidden.
 * This prop is ignored when `hiddenUntilFound` is used.
 */
keepMounted?: boolean = false

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

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 (react-component-meta) 8 prop types
Component: ../packages/ui/src/collapsible-card/index.ts::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 element.
 */
className?: string

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

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

/**
 * 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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Imports
import { Content, FullBleed, Header, Root, Title, HeaderDescription, Stack, Text } from '@wordpress/ui';
import * as CollapsibleCard from '../index';
import * as Card from '../../card';
import { Text } from '../../text';
import { Stack } from '../../stack';
Default story ok
A collapsible card that is open by default.
const Default = () => <CollapsibleCard.Root>{[
        <CollapsibleCard.Header key="header">
            <Card.Title>Collapsible card (closed by default)</Card.Title>
        </CollapsibleCard.Header>,
        <CollapsibleCard.Content key="content">
            <Text render={ <p /> }>
                This is the collapsible content area. It can contain any
                elements, just like a regular Card.Content.
            </Text>
            <Text render={ <p /> }>
                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 key="header">
            <Card.Title>Collapsed by default</Card.Title>
        </CollapsibleCard.Header>,
        <CollapsibleCard.Content key="content">
            <Text render={ <p /> }>
                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 key="header">
            <Card.Title>Disabled card</Card.Title>
        </CollapsibleCard.Header>,
        <CollapsibleCard.Content key="content">
            <Text render={ <p /> }>
                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 = () => (
    <Stack direction="column" 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 render={ <p /> }>
                        Configure all { title.toLowerCase() } settings for
                        your site. Changes here affect how your site behaves
                        across all pages and posts.
                    </Text>
                    <Text render={ <p /> }>
                        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 render={ <p /> }>
                        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>
        ) ) }
    </Stack>
);
With Heading Element story ok
`CollapsibleCard.Header` renders a `<div>` wrapper by default. Pass an `<h1>`–`<h6>` React element to the `render` prop to wrap the trigger in a heading and contribute to the document outline. The right level depends on the surrounding outline, so the consumer is expected to opt in.
const WithHeadingElement = () => (
    <Stack direction="column" gap="lg">
        <CollapsibleCard.Root>
            <CollapsibleCard.Header render={ <h2 /> }>
                <Card.Title>Heading level 2</Card.Title>
            </CollapsibleCard.Header>
            <CollapsibleCard.Content>
                <Text render={ <p /> }>
                    The wrapper renders as an h2 element when the consumer
                    passes an h2 React element to the render prop.
                </Text>
            </CollapsibleCard.Content>
        </CollapsibleCard.Root>
        <CollapsibleCard.Root>
            <CollapsibleCard.Header render={ <h3 /> }>
                <Card.Title>Heading level 3</Card.Title>
            </CollapsibleCard.Header>
            <CollapsibleCard.Content>
                <Text render={ <p /> }>
                    Pass any of h1–h6 to choose the level that fits the
                    surrounding document outline.
                </Text>
            </CollapsibleCard.Content>
        </CollapsibleCard.Root>
        <CollapsibleCard.Root>
            <CollapsibleCard.Header>
                <Card.Title>No heading (default)</Card.Title>
            </CollapsibleCard.Header>
            <CollapsibleCard.Content>
                <Text render={ <p /> }>
                    Without a render prop, the header wraps the trigger in a
                    plain div and does not contribute to the document
                    outline.
                </Text>
            </CollapsibleCard.Content>
        </CollapsibleCard.Root>
    </Stack>
);
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: _open,
    defaultOpen: _defaultOpen,
    onOpenChange: _onOpenChange,
    ...restArgs
} ) => (
    <CollapsibleCard.Root { ...restArgs }>
        <CollapsibleCard.Header>
            <Stack justify="space-between" align="center">
                <Card.Title>Settings</Card.Title>
                <CollapsibleCard.HeaderDescription>
                    3 items configured
                </CollapsibleCard.HeaderDescription>
            </Stack>
        </CollapsibleCard.Header>
        <CollapsibleCard.Content>
            <Text render={ <p /> }>
                The description appears next to the title.
            </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 } ) => (
    <Stack direction="column" 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 render={ <p /> }>
                    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 render={ <p /> }>
                    Content should align with the collapsible card above.
                </Text>
            </Card.Content>
        </Card.Root>
    </Stack>
);
Full Bleed Cover With Header story ok
When `Card.FullBleed` is the sole child of `CollapsibleCard.Content` and a header sits above it, the media bumps against the card&apos;s side and bottom edges while the header retains its normal padding. (Unlike a plain `Card`, a header is always required here for the collapse trigger — see `Card` stories for a body-only `FullBleedCoverOnly` example.)
const FullBleedCoverWithHeader = () => <CollapsibleCard.Root defaultOpen>{[
        <CollapsibleCard.Header key="header">
            <Card.Title>Card title</Card.Title>
        </CollapsibleCard.Header>,
        <CollapsibleCard.Content key="content">
            <Card.FullBleed>
                <div
                    style={ {
                        height: 180,
                        background:
                            'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
                    } }
                />
            </Card.FullBleed>
        </CollapsibleCard.Content>,
    ]}</CollapsibleCard.Root>;
With Full Bleed story ok
`Card.FullBleed` breaks out of the content padding to span edge-to-edge. Useful for images, dividers, or embedded content inside the collapsible region.
const WithFullBleed = () => <CollapsibleCard.Root defaultOpen>{[
        <CollapsibleCard.Header key="header">
            <Card.Title>Featured image</Card.Title>
        </CollapsibleCard.Header>,
        <CollapsibleCard.Content
            render={ <Stack direction="column" gap="lg" /> }
            key="content"
        >
            <Card.FullBleed>
                <div
                    style={ {
                        height: 160,
                        background:
                            'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
                    } }
                />
            </Card.FullBleed>
            <Text render={ <p /> }>Content below the full-bleed area.</Text>
        </CollapsibleCard.Content>,
    ]}</CollapsibleCard.Root>;
CollapsibleCard.Header 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/collapsible-card/index.ts
The header of a collapsible card. Always visible, and acts as the toggle trigger — clicking anywhere on it expands or collapses the card's content. Defaults to a `<div>` wrapper around the trigger. Since the right heading level depends on the surrounding document outline, the consumer is expected to opt in to heading semantics. Pass `render` to wrap the trigger in a heading (e.g. `render={ <h2 /> }`), following the W3C APG accordion pattern (heading wraps button). Avoid placing interactive elements (buttons, links, inputs) inside the header, since the entire area is clickable and their events will bubble to trigger the collapse toggle. Place full-bleed media in `CollapsibleCard.Content`, not the header.
import { Header } from '@wordpress/ui';
Component: ../packages/ui/src/collapsible-card/index.ts::Header (react-component-meta)
/**
 * The content to be rendered inside the header.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
CollapsibleCard.HeaderDescription 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/collapsible-card/index.ts
Secondary content placed in the collapsible card header that describes the trigger button via `aria-describedby`. Use it for supplementary information such as status badges or summary values. Must be rendered inside `CollapsibleCard.Header`. The content is visually rendered but marked `aria-hidden` so that assistive technologies consume it only through the `aria-describedby` relationship on the trigger, avoiding double announcements. Avoid interactive elements (buttons, links, inputs) inside this component — the entire header is the toggle trigger.
import { HeaderDescription } from '@wordpress/ui';
Component: ../packages/ui/src/collapsible-card/index.ts::HeaderDescription (react-component-meta)
/**
 * Secondary content that describes the header trigger via
 * `aria-describedby`. Rendered visually but marked `aria-hidden`
 * so assistive technologies consume it only through the description
 * relationship, avoiding double announcements.
 * 
 * Avoid interactive elements — the entire header is the toggle trigger.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined = <div />

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
CollapsibleCard.Content 5 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/collapsible-card/index.ts
The collapsible content area of the card. Hidden when collapsed, visible when expanded.
import { Content } from '@wordpress/ui';
Component: ../packages/ui/src/collapsible-card/index.ts::Content (react-component-meta)
/**
 * The content to be rendered inside the collapsible content area.
 */
children?: ReactNode

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

/**
 * Allows the browser’s built-in page search to find and expand the panel contents.
 * 
 * Overrides the `keepMounted` prop and uses `hidden="until-found"`
 * to hide the element without removing it from the DOM.
 */
hiddenUntilFound?: boolean = true

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Card.FullBleed 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/card/index.ts
A container that breaks out of the card's padding to span edge-to-edge. Useful for full-width images, dividers, or embedded content. Additional edge-bumping behavior based on placement: - As the **first child** of `Card.Header`, it extends flush to the card's top edge — ideal for hero images. - As the **only child** of `Card.Content`, it extends flush to the card's top edge when `Content` is the first card section, and to the bottom edge when it is the last. Inter-sibling spacing inside `Card.Header` / `Card.Content` is consumer- managed. To add space between a hero `FullBleed` and the following siblings, compose the parent with `Stack` via the `render` prop: `<Card.Header render={ <Stack direction="column" gap="lg" /> }>`. This keeps `FullBleed` a direct child of `Card.Header` so the edge-bump still fires, while `Stack` provides the gap. Inside `CollapsibleCard`, place full-bleed media in `CollapsibleCard.Content` (not the header). The trigger/panel gap is preserved by design. Must be used as a direct child of `Card.Content` or `Card.Header`.
import { FullBleed } from '@wordpress/ui';
Component: ../packages/ui/src/card/index.ts::FullBleed (react-component-meta)
/**
 * The content to be rendered edge-to-edge, breaking out of the
 * card's padding.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

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" />; ```
Prop types (react-component-meta) 1 prop type
Component: ../packages/components/src/color-indicator/index.tsx::default
Props:
/**
 * The color of the indicator. Any value from the CSS `background` property
 * is supported.
 */
colorValue: Background<string | number> | undefined
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 ) } /> ); } ); ```
Prop types (react-component-meta) 15 prop types
Component: ../packages/components/src/color-palette/index.tsx::default
Props:
/**
 * Whether this is rendered in the sidebar.
 */
__experimentalIsRenderedInSidebar?: boolean = false

/**
 * A label to identify the purpose of the control.
 */
aria-label?: string

/**
 * An ID of an element to provide a label for the control.
 */
aria-labelledby?: string

/**
 * The HTML element or React component to render the component as.
 */
as?: JSXElementConstructor<any> | keyof IntrinsicElements | undefined

/**
 * Whether the control should present as toggle buttons.
 */
asButtons?: boolean = false

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

/**
 * Array with the colors to be shown. When displaying multiple color palettes
 * to choose from, the format of the array changes from an array of colors
 * objects, to an array of color palettes.
 */
colors?: PaletteObject[] | ColorObject[] | undefined = []

/**
 * Whether to allow the user to pick a custom color on top of the predefined
 * choices (defined via the `colors` prop).
 */
disableCustomColors?: boolean = false

/**
 * This controls whether the alpha channel will be offered when selecting
 * custom colors.
 */
enableAlpha?: boolean = false

/**
 * The heading level.
 */
headingLevel?: 1 | 2 | "1" | "2" | "3" | 3 | 4 | 5 | 6 | "4" | "5" | "6" = 2

/**
 * Prevents keyboard interaction from wrapping around.
 * Only used with the `listbox` presentation.
 */
loop?: boolean = true

/**
 * Callback called when a color is selected.
 * The third argument is the slug of the selected palette entry, when available.
 */
onChange: (newColor?: string | undefined, index?: number | undefined, slug?: string | undefined) => void

/**
 * How predefined color swatches behave and are exposed to assistive
 * technology.
 * 
 * - `listbox` uses one tab stop and arrow-key navigation, and exposes
 *   selection with `aria-selected`.
 * - `toggle-buttons` gives each swatch a tab stop and exposes selection with
 *   `aria-pressed`.
 * - `command-buttons` gives each swatch a tab stop and exposes no selection
 *   state. `value` and `selectedSlug` do not mark predefined swatches as
 *   selected, and activating a swatch always calls `onChange` with that
 *   swatch. `value` still controls the custom color picker.
 */
presentation?: "listbox" | "toggle-buttons" | "command-buttons" = 'listbox'

/**
 * The slug of the currently selected palette entry.
 * 
 * When set to a non-empty string, selection is determined by slug rather
 * than by color value — this correctly handles palettes where two entries
 * share the same color. Palette entries without a slug will not appear
 * selected in this mode, even if their color value matches `value`.
 * 
 * An empty string is treated the same as `undefined`: selection falls
 * back to matching by color value.
 */
selectedSlug?: string

/**
 * Currently active value.
 */
value?: string
Imports
import { ColorPalette } from '@wordpress/components';
Default story ok
const Default = () => {
    const [ color, setColor ] = useState< string | undefined >( value );
    const [ slug, setSlug ] = useState< string | undefined >( selectedSlug );

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

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

    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 }
            selectedSlug={ slug }
            onChange={ ( newColor, index, newSlug ) => {
				setColor( newColor );
				setSlug( newSlug );
				onChange?.( newColor, index, newSlug );
			} } />
    );
};
Duplicate Colors story ok
const DuplicateColors = () => {
    const [ color, setColor ] = useState< string | undefined >( value );
    const [ slug, setSlug ] = useState< string | undefined >( selectedSlug );

    return (
        <ColorPalette
            colors={[
                { name: 'Dark Background', slug: 'dark-background', color: '#000' },
                { name: 'Dark Text', slug: 'dark-text', color: '#000' },
                { name: 'Brand', slug: 'brand', color: '#0073aa' },
            ]}
            value={ color }
            selectedSlug={ slug }
            onChange={ ( newColor, index, newSlug ) => {
				setColor( newColor );
				setSlug( newSlug );
				onChange?.( newColor, index, newSlug );
			} } />
    );
};
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>;

ColorPicker

components-colorpicker · ../packages/components/src/color-picker/stories/index.story.tsx
`ColorPicker` lets users select a color from a visual color surface, or by editing its hex, RGB, or HSL values.
Prop types (react-component-meta) 5 prop types
Component: ../packages/components/src/color-picker/component.tsx::ColorPicker
Props:
/**
 * The current color value to display in the picker.
 * Must be a hex or hex8 string.
 */
color?: string

/**
 * The format to copy when clicking the displayed color format.
 */
copyFormat?: "rgb" | "hsl" | "hex"

/**
 * An optional default value to use for the color picker.
 */
defaultValue?: string = '#fff'

/**
 * When `true` the color picker will display the alpha channel both in
 * the bottom inputs as well as in the color picker itself.
 */
enableAlpha?: boolean = false

/**
 * Fired when the color changes. Always passes a hex or hex8 color string.
 */
onChange?: (color: string) => void
Imports
import { ColorPicker } from '@wordpress/components';
import { fn } from 'storybook/test';
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 label="Font Size" value={ fontSize } onChange={ setFontSize } options={ filteredOptions } onFilterValueChange={ ( inputValue ) => setFilteredOptions( options.filter( ( option ) => option.label .toLowerCase() .startsWith( inputValue.toLowerCase() ) ) ) } /> ); } ```
Prop types (react-component-meta) 17 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; }) => ReactNode

/**
 * Deprecated. Use `__next40pxDefaultSize` instead.
 */
__next36pxDefaultSize?: boolean = false

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

/**
 * Start opting into the new margin-free styles that will become the default in a future version.
 */
__nextHasNoMarginBottom?: boolean

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

className?: string

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

/**
 * Additional description for the control.
 * 
 * Only use for meaningful description or instructions for the control. An element containing the description will be programmatically associated to the BaseControl by the means of an `aria-describedby` attribute.
 */
help?: ReactNode

/**
 * If true, the label will only be visible to screen readers.
 */
hideLabelFromVision?: boolean = false

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

/**
 * If this property is added, a label will be generated using label property as the content.
 */
label?: ReactNode

/**
 * Customizable UI messages.
 */
messages?: { selected: string; } = {
			selected: __( 'Item selected.' ),
		}

/**
 * Function called with the selected value changes.
 */
onChange?: (value: ComboboxControlValue) => void

/**
 * Function called when the control's search input value changes. The argument contains the next input value.
 */
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?: ComboboxControlValue | undefined
Imports
import { ComboboxControl } from '@wordpress/components';
import { fn } from 'storybook/test';
Default incomplete example
const Default = () => {
    const [ value, setValue ] =
		useState< ComboboxControlProps[ 'value' ] >( null );

    return (
        <>
            <ComboboxControl
                onFilterValueChange={fn()}
                label="Country"
                options={countries.map( mapCountryOption )}
                help="Help text to describe the control."
                value={ value }
                onChange={ ( ...changeArgs ) => {
					setValue( ...changeArgs );
					onChange?.( ...changeArgs );
				} } />
        </>
    );
};
Incomplete snippet: `countries`, `mapCountryOption` could not be resolved statically.
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
                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',
                    },
                ]}
                help="Help text to describe the control."
                __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 incomplete example
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
                onFilterValueChange={fn()}
                label="Country"
                options={countryOptions.map( ( option, index ) => ( {
                    ...option,
                    disabled: index % 3 === 0, // Disable options at index 0, 3, 6, etc.
                } ) )}
                help="Help text to describe the control."
                value={ value }
                onChange={ ( ...changeArgs ) => {
					setValue( ...changeArgs );
					onChange?.( ...changeArgs );
				} } />
        </>
    );
};
Incomplete snippet: `countryOptions` could not be resolved statically.
Not Expand On Focus incomplete example
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
                onFilterValueChange={fn()}
                label="Country"
                options={countries.map( mapCountryOption )}
                help="Help text to describe the control."
                expandOnFocus={false}
                value={ value }
                onChange={ ( ...changeArgs ) => {
					setValue( ...changeArgs );
					onChange?.( ...changeArgs );
				} } />
        </>
    );
};
Incomplete snippet: `countries`, `mapCountryOption` could not be resolved statically.

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 (react-component-meta) 15 prop types
Component: ../packages/components/src/composite/index.tsx::Composite
Props:
/**
 * Indicates whether the element should be focusable even when it is
 * `disabled`.
 * 
 * This is important when discoverability is a concern. For example:
 * 
 * > A toolbar in an editor contains a set of special smart paste functions
 * that are disabled when the clipboard is empty or when the function is not
 * applicable to the current content of the clipboard. It could be helpful to
 * keep the disabled buttons focusable if the ability to discover their
 * functionality is primarily via their presence on the toolbar.
 * 
 * Learn more on [Focusability of disabled
 * controls](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#focusabilityofdisabledcontrols).
 */
accessibleWhenDisabled?: boolean

/**
 * The current active item `id`. The active item is the element within the
 * composite widget that has either DOM or virtual focus (in case
 * the `virtualFocus` prop is enabled).
 * - `null` represents the base composite element (the one with a [composite
 *   role](https://w3c.github.io/aria/#composite)). Users will be able to
 *   navigate out of it using arrow keys.
 * - If `activeId` 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.
 */
activeId?: string | null | undefined

/**
 * The contents of the component.
 */
children?: ReactNode

/**
 * The composite item id that should be active by default when the composite
 * widget is rendered. If `null`, the composite 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.
 */
defaultActiveId?: string | null | undefined

/**
 * Determines if the element is disabled. This sets the `aria-disabled`
 * attribute accordingly, enabling support for all elements, including those
 * that don't support the native `disabled` attribute.
 * 
 * This feature can be combined with the `accessibleWhenDisabled` prop to
 * make disabled elements still accessible via keyboard.
 * 
 * **Note**: For this prop to work, the `focusable` prop must be set to
 * `true`, if it's not set by default.
 */
disabled?: boolean = false

/**
 * Makes the component a focusable element. When this element gains keyboard
 * focus, it gets a `data-focus-visible` attribute and triggers the
 * `onFocusVisible` prop.
 * The component supports the `disabled` prop even for those elements not
 * supporting the native `disabled` attribute. Disabled elements may be
 * still accessible via keyboard by using the `accessibleWhenDisabled`
 * prop.
 * Non-native focusable elements will lose their focusability entirely.
 * However, native focusable elements will retain their inherent focusability.
 */
focusable?: boolean

/**
 * Determines how the focus behaves when the user reaches the end of the
 * composite widget.
 * 
 * On one-dimensional composite widgets:
 * - `true` loops from the last item to the first item and vice-versa.
 * - `horizontal` loops only if `orientation` is `horizontal` or not set.
 * - `vertical` loops only if `orientation` is `vertical` or not set.
 * - If `activeId` is initially set to `null`, the composite element will
 *   be focused in between the last and first items.
 * 
 * On two-dimensional composite widgets (ie. when using `CompositeRow`):
 * - `true` loops from the last row/column item to the first item in the same
 *   row/column and vice-versa. If it's the last item in the last row, it
 *   moves to the first item in the first row and vice-versa.
 * - `horizontal` loops only from the last row item to the first item in the
 *   same row.
 * - `vertical` loops only from the last column item to the first item in the
 *   column row.
 * - If `activeId` is initially set to `null`, vertical loop will have no
 *   effect as moving down from the last row or up from the first row will
 *   focus on the composite element.
 * - If `focusWrap` matches the value of `focusLoop`, it'll wrap between the
 *   last item in the last row or column and the first item in the first row or
 *   column and vice-versa.
 */
focusLoop?: boolean | Orientation | undefined = false

/**
 * **Works only on two-dimensional composite widgets**.
 * 
 * If enabled, moving up or down when there's no next item or when the next
 * item is disabled will shift to the item right before it.
 */
focusShift?: boolean = false

/**
 * **Works only on two-dimensional composite widgets**.
 * 
 * If enabled, moving to the next item from the last one in a row or column
 * will focus on the first item in the next row or column and vice-versa.
 * - `true` wraps between rows and columns.
 * - `horizontal` wraps only between rows.
 * - `vertical` wraps only between columns.
 * - If `focusLoop` matches the value of `focusWrap`, it'll wrap between the
 *   last item in the last row or column and the first item in the first row or
 *   column and vice-versa.
 */
focusWrap?: boolean | Orientation | undefined = false

/**
 * Custom event handler invoked when the element gains focus through keyboard
 * interaction or a key press occurs while the element is in focus. This is
 * the programmatic equivalent of the `data-focus-visible` attribute.
 * 
 * **Note**: For this prop to work, the `focusable` prop must be set to `true`
 * if it's not set by default.
 */
onFocusVisible?: BivariantCallback<(event: SyntheticEvent<HTMLElement, Event>) => void>

/**
 * 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:
 * - `both`: all arrow keys work.
 * - `horizontal`: only left and right arrow keys work.
 * - `vertical`: only up and down arrow keys work.
 * 
 * It doesn't have any effect on two-dimensional composites.
 */
orientation?: "both" | "horizontal" | "vertical" = 'both'

/**
 * Allows the component to be rendered as a different HTML element or React
 * component. The value can be a React element or a function that takes in the
 * original component props and gives back a React element with the props
 * merged.
 */
render?: ReactElement<unknown, string | JSXElementConstructor<any>> | RenderProp<HTMLAttributes<any> & { ref?: Ref<any> | undefined; }> | undefined

/**
 * Controls how the previous and next items are determined.
 * 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.
 */
rtl?: boolean = isRTL()

/**
 * A callback that gets called when the `activeId` state changes.
 */
setActiveId?: (activeId: string | null | undefined) => void

/**
 * If enabled, the composite element will act as an
 * [`aria-activedescendant`](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_focus_activedescendant)
 * container instead of [roving
 * tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex).
 * DOM focus will remain on the composite element while its items receive
 * virtual focus.
 * 
 * In both scenarios, the item in focus will carry the `data-active-item`
 * attribute.
 */
virtualFocus?: boolean = false
Imports
import { Composite, Provider as SlotFillProvider, Tooltip } from '@wordpress/components';
import { Composite } from '..';
import { Tooltip } from '../../tooltip';
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 incomplete example
const WithSlotFill = () => <Composite>(<>
        <Composite.Item>Item one (direct child)</Composite.Item>
        <Slot />
        <Composite.Item>Item four (direct child)</Composite.Item>
    </>)</Composite>;
Incomplete snippet: `Slot` could not be resolved statically.
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>;
Composite.Group 2 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/composite/index.tsx
Renders a group element for composite items.
example: ```jsx import { Composite } from '@wordpress/components'; <Composite> <Composite.Group> <Composite.GroupLabel>Label</Composite.GroupLabel> <Composite.Item>Item 1</Composite.Item> <Composite.Item>Item 2</Composite.Item> </CompositeGroup> </Composite> ```
import { Composite } from '@wordpress/components';
Component: ../packages/components/src/composite/index.tsx::Composite (react-component-meta)
/**
 * The contents of the component.
 */
children?: ReactNode

/**
 * Allows the component to be rendered as a different HTML element or React
 * component. The value can be a React element or a function that takes in the
 * original component props and gives back a React element with the props
 * merged.
 */
render?: ReactElement<unknown, string | JSXElementConstructor<any>> | RenderProp<HTMLAttributes<any> & { ref?: Ref<any> | undefined; }> | undefined
Composite.GroupLabel 2 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/composite/index.tsx
Renders a label in a composite group. This component must be wrapped with `Composite.Group` so the `aria-labelledby` prop is properly set on the composite group element.
example: ```jsx import { Composite } from '@wordpress/components'; <Composite> <Composite.Group> <Composite.GroupLabel>Label</Composite.GroupLabel> <Composite.Item>Item 1</Composite.Item> <Composite.Item>Item 2</Composite.Item> </CompositeGroup> </Composite> ```
import { Composite } from '@wordpress/components';
Component: ../packages/components/src/composite/index.tsx::Composite (react-component-meta)
/**
 * The contents of the component.
 */
children?: ReactNode

/**
 * Allows the component to be rendered as a different HTML element or React
 * component. The value can be a React element or a function that takes in the
 * original component props and gives back a React element with the props
 * merged.
 */
render?: ReactElement<unknown, string | JSXElementConstructor<any>> | RenderProp<HTMLAttributes<any> & { ref?: Ref<any> | undefined; }> | undefined
Composite.Row 2 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/composite/index.tsx
Renders a composite row. Wrapping `Composite.Item` elements within `Composite.Row` will create a two-dimensional composite widget, such as a grid.
example: ```jsx import { Composite } from '@wordpress/components'; <Composite> <Composite.Row> <Composite.Item>Item 1.1</Composite.Item> <Composite.Item>Item 1.2</Composite.Item> <Composite.Item>Item 1.3</Composite.Item> </Composite.Row> <Composite.Row> <Composite.Item>Item 2.1</Composite.Item> <Composite.Item>Item 2.2</Composite.Item> <Composite.Item>Item 2.3</Composite.Item> </Composite.Row> </Composite> ```
import { Composite } from '@wordpress/components';
Component: ../packages/components/src/composite/index.tsx::Composite (react-component-meta)
/**
 * The contents of the component.
 */
children?: ReactNode

/**
 * Allows the component to be rendered as a different HTML element or React
 * component. The value can be a React element or a function that takes in the
 * original component props and gives back a React element with the props
 * merged.
 */
render?: ReactElement<unknown, string | JSXElementConstructor<any>> | RenderProp<HTMLAttributes<any> & { ref?: Ref<any> | undefined; }> | undefined
Composite.Item 3 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/composite/index.tsx
Renders a composite item.
example: ```jsx import { Composite } from '@wordpress/components'; <Composite> <Composite.Item>Item 1</Composite.Item> <Composite.Item>Item 2</Composite.Item> <Composite.Item>Item 3</Composite.Item> </Composite> ```
import { Composite } from '@wordpress/components';
Component: ../packages/components/src/composite/index.tsx::Composite (react-component-meta)
/**
 * Indicates whether the element should be focusable even when it is
 * `disabled`.
 * 
 * This is important when discoverability is a concern. For example:
 * 
 * > A toolbar in an editor contains a set of special smart paste functions
 * that are disabled when the clipboard is empty or when the function is not
 * applicable to the current content of the clipboard. It could be helpful to
 * keep the disabled buttons focusable if the ability to discover their
 * functionality is primarily via their presence on the toolbar.
 * 
 * Learn more on [Focusability of disabled
 * controls](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#focusabilityofdisabledcontrols).
 */
accessibleWhenDisabled?: boolean

/**
 * The contents of the component.
 */
children?: ReactNode

/**
 * Allows the component to be rendered as a different HTML element or React
 * component. The value can be a React element or a function that takes in the
 * original component props and gives back a React element with the props
 * merged.
 */
render?: ReactElement<unknown, string | JSXElementConstructor<any>> | RenderProp<HTMLAttributes<any> & { ref?: Ref<any> | undefined; }> | undefined
Composite.Hover 2 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/composite/index.tsx
Renders an element in a composite widget that receives focus on mouse move and loses focus to the composite base element on mouse leave. This should be combined with the `Composite.Item` component.
example: ```jsx import { Composite } from '@wordpress/components'; <Composite> <Composite.Hover render={ <Composite.Item /> }> Item 1 </Composite.Hover> <Composite.Hover render={ <Composite.Item /> }> Item 2 </Composite.Hover> </Composite> ```
import { Composite } from '@wordpress/components';
Component: ../packages/components/src/composite/index.tsx::Composite (react-component-meta)
/**
 * The contents of the component.
 */
children?: ReactNode

/**
 * Allows the component to be rendered as a different HTML element or React
 * component. The value can be a React element or a function that takes in the
 * original component props and gives back a React element with the props
 * merged.
 */
render?: ReactElement<unknown, string | JSXElementConstructor<any>> | RenderProp<HTMLAttributes<any> & { ref?: Ref<any> | undefined; }> | undefined
Composite.Typeahead 2 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/composite/index.tsx
Renders a component that adds typeahead functionality to composite components. Hitting printable character keys will move focus to the next composite item that begins with the input characters.
example: ```jsx import { Composite } from '@wordpress/components'; <Composite render={ <CompositeTypeahead /> }> <Composite.Item>Item 1</Composite.Item> <Composite.Item>Item 2</Composite.Item> </Composite> ```
import { Composite } from '@wordpress/components';
Component: ../packages/components/src/composite/index.tsx::Composite (react-component-meta)
/**
 * The contents of the component.
 */
children?: ReactNode

/**
 * Allows the component to be rendered as a different HTML element or React
 * component. The value can be a React element or a function that takes in the
 * original component props and gives back a React element with the props
 * merged.
 */
render?: ReactElement<unknown, string | JSXElementConstructor<any>> | RenderProp<HTMLAttributes<any> & { ref?: Ref<any> | undefined; }> | undefined
Composite.Context 2 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/composite/index.tsx
The React context used by the composite components. It can be used by to access the composite store, and to forward the context when composite sub-components are rendered across portals (ie. `SlotFill` components) that would not otherwise forward the context to the `Fill` children.
example: ```jsx import { Composite } from '@wordpress/components'; import { useContext } from '@wordpress/element'; const compositeContext = useContext( Composite.Context ); ```
import { Composite } from '@wordpress/components';
Component: ../packages/components/src/composite/index.tsx::Composite (react-component-meta)
children?: ReactNode

value: CompositeContextProps

ConfirmDialog

components-confirmdialog · ../packages/components/src/confirm-dialog/stories/index.story.tsx
`ConfirmDialog` is built on top of [`Modal`](/packages/components/src/modal/README.md) and displays a confirmation dialog, with _confirm_ and _cancel_ buttons. The dialog is confirmed by clicking the _confirm_ button or by pressing the `Enter` key. It is cancelled (closed) by clicking the _cancel_ button, by pressing the `ESC` key, or by clicking outside the dialog focus (i.e. the overlay). `ConfirmDialog` has two main modes: controlled and uncontrolled. ### Uncontrolled mode Allows the component to be used standalone, just by declaring it as part of another React component's render method: - It will be automatically open (displayed) upon mounting. - It will be automatically closed when clicking the _cancel_ button, by pressing the `ESC` key, or by clicking outside the dialog focus (i.e. the overlay). - `onCancel` is not mandatory but can be passed. Even if passed, the dialog will still be able to close itself. Activating this mode is as simple as omitting the `isOpen` prop. The only mandatory prop in this case is the `onConfirm` callback. The message is passed as the `children`. ```jsx import { __experimentalConfirmDialog as ConfirmDialog } from '@wordpress/components'; function Example() { return ( <ConfirmDialog onConfirm={ () => console.debug( 'Confirmed!' ) }> Are you sure? <strong>This action cannot be undone!</strong> </ConfirmDialog> ); } ``` ### Controlled mode Let the parent component control when the dialog is open/closed. It's activated when a boolean value is passed to `isOpen`: - It will not be automatically closed. You need to let it know when to open/close by updating the value of the `isOpen` prop. - Both `onConfirm` and the `onCancel` callbacks are mandatory props in this mode. - You'll want to update the state that controls `isOpen` from the `onCancel` and `onConfirm` callbacks. ```jsx import { useState } from '@wordpress/element'; import { __experimentalConfirmDialog as ConfirmDialog } from '@wordpress/components'; function Example() { const [ isOpen, setIsOpen ] = useState( true ); const handleConfirm = () => { console.debug( 'Confirmed!' ); setIsOpen( false ); }; const handleCancel = () => { console.debug( 'Cancelled!' ); setIsOpen( false ); }; return ( <ConfirmDialog isOpen={ isOpen } onConfirm={ handleConfirm } onCancel={ handleCancel } > Are you sure? <strong>This action cannot be undone!</strong> </ConfirmDialog> ); } ```
Prop types (react-component-meta) 10 prop types
Component: ../packages/components/src/confirm-dialog/component.tsx::ConfirmDialog
Props:
/**
 * Whether the underlying `Modal` should hide its header, `title` included.
 */
__experimentalHideHeader?: boolean = true

/**
 * The optional custom text to display as the cancellation button's label.
 */
cancelButtonText?: string

/**
 * The actual message for the dialog. It's passed as children and any valid `ReactNode` is accepted.
 */
children: ReactNode

/**
 * The optional custom text to display as the confirmation button's label.
 */
confirmButtonText?: string

/**
 * Indicates activity while an action is being performed.
 * When `true`, the confirm button will show a busy state.
 * Both buttons will be disabled.
 */
isBusy?: boolean

/**
 * Defines if the dialog is open (displayed) or closed (not rendered/displayed).
 * It also implicitly toggles the controlled mode if set or the uncontrolled mode if it's not set.
 */
isOpen?: boolean

/**
 * The callback that's called when the user cancels. A cancellation can happen
 * when the `Cancel` button is clicked, when the `ESC` key is pressed, or when
 * a click outside of the dialog focus is detected (i.e. in the overlay).
 * 
 * It's not required if `isOpen` is not set (uncontrolled mode), as the component
 * will take care of closing itself, but you can still pass a callback if something
 * must be done upon cancelling (the component will still close itself in this case).
 * 
 * If `isOpen` is set (controlled mode), then it's required, and you need to set
 * the state that defines `isOpen` to `false` as part of this callback if you want the
 * dialog to close when the user cancels.
 */
onCancel?: (event: DialogInputEvent) => void

/**
 * The callback that's called when the user confirms.
 * A confirmation can happen when the `OK` button is clicked or when `Enter` is pressed.
 */
onConfirm: (event: DialogInputEvent) => void

/**
 * Size of the underlying Modal. See `Modal`'s `size` prop.
 */
size?: "small" | "fill" | "medium" | "large"

/**
 * The title of the underlying `Modal`: its accessible name, and the
 * visible heading unless `__experimentalHideHeader` is `true`.
 */
title?: string
Imports
import { Button, ConfirmDialog } from '@wordpress/components';
import { fn } from 'storybook/test';
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 }>
                Would you like to privately publish the post now?
            </ConfirmDialog>
        </>
    );
};

CustomSelectControl

components-customselectcontrol · ../packages/components/src/custom-select-control/stories/index.story.tsx
`CustomSelectControl` is a dropdown for selecting a single option from a list, with support for custom styling. Use it instead of the `SelectControl` when options need richer markup (e.g. per-option styles or hints).
Prop types (react-component-meta) 16 prop types
Component: ../packages/components/src/custom-select-control/index.tsx::default
Props:
/**
 * Use the `showSelectedHint` property instead.
 */
__experimentalShowSelectedHint?: boolean

/**
 * Start opting into the larger default height that will become the default size in a future version.
 */
__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.
 */
__nextUnconstrainedWidth?: 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.
 */
onBlur?: FocusEventHandler<HTMLButtonElement>

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

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

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

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

/**
 * The list of options that can be chosen from.
 */
options: readonly CustomSelectOption[]

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

/**
 * The size of the control.
 */
size?: "small" | "default" = 'default'

/**
 * Can be used to externally control the value of the control.
 */
value?: NoInfer<CustomSelectOption>
Imports
import { CustomSelectControl } from '@wordpress/components';
import { fn } from 'storybook/test';
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
			{ ...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
			{ ...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
			{ ...props }
			onChange={ onChange }
			value={ value }
		/>
	);
};

DataForm

dataviews-dataform · ../packages/dataviews/src/dataform/stories/index.story.tsx
`DataForm` renders an auto-generated form for viewing and editing the fields of a data item, driven by a fields and form layout configuration. Use it to edit items of a dataset, often alongside `DataViews`.
Prop types (react-component-meta) 5 prop types
Component: ../packages/dataviews/src/dataform/index.tsx::default
Props:
/**
 * The item being edited.
 */
data: Item

/**
 * The field definitions for the item.
 */
fields: Field<Item>[]

/**
 * The form configuration: which fields to render and with which layout.
 */
form: Form

/**
 * Callback invoked when the user edits a field, receiving the partial
 * item returned by the field's `setValue`. By default that is an object
 * keyed by field id, nested for dotted ids (e.g. `{ a: { b: value } }`
 * for the field `a.b`); a custom `setValue` may return any other partial
 * shape of the item.
 */
onChange: (value: Record<string, any>) => void

/**
 * The validity state of the form's fields, keyed by field id.
 */
validity?: Record<string, FieldValidity>
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" showPlaceholderIfEmpty={false} disabled={false} />;
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} />;
Validation Panel Error Indicator story ok
const ValidationPanelErrorIndicator = () => <DataForm />;
Visibility story ok
const Visibility = () => <DataForm />;
Data Adapter story ok
const DataAdapter = () => <DataForm />;

DataForm

dataviews-dataform-content · ../packages/dataviews/src/dataform/stories/content.story.tsx
`DataForm` renders an auto-generated form for viewing and editing the fields of a data item, driven by a fields and form layout configuration. Use it to edit items of a dataset, often alongside `DataViews`.
Prop types (react-component-meta) 5 prop types
Component: ../packages/dataviews/src/dataform/index.tsx::default
Props:
/**
 * The item being edited.
 */
data: SampleData

/**
 * The field definitions for the item.
 */
fields: Field<SampleData>[]

/**
 * The form configuration: which fields to render and with which layout.
 */
form: Form

/**
 * Callback invoked when the user edits a field, receiving the partial
 * item returned by the field's `setValue`. By default that is an object
 * keyed by field id, nested for dotted ids (e.g. `{ a: { b: value } }`
 * for the field `a.b`); a custom `setValue` may return any other partial
 * shape of the item.
 */
onChange: (value: Record<string, any>) => void

/**
 * The validity state of the form's fields, keyed by field id.
 */
validity?: Record<string, FieldValidity>
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>
    );
};
Docs doc ok
../packages/dataviews/src/dataform/stories/content.story.mdx
# Content Elements Guidance on understanding the semantics and proper usage of content ele...
import { Canvas, Meta } from '@storybook/addon-docs/blocks';
import * as ContentStories from './content.story';

<Meta of={ ContentStories } />

# Content Elements

Guidance on understanding the semantics and proper usage of content elements in `DataForm` instances, including when and how to use high-level help text, labels, placeholders, field-level help text, and validation messages.

## Accessibility

Proper use of content elements is essential for accessibility. Each element serves a specific semantic purpose that assistive technologies rely on:

- **Labels** are announced by screen readers to identify form fields. Every field must have a label.
- **Placeholders** provide example input to hint at expected format. They are not a substitute for labels—they disappear on input and are not reliably announced.
- **Help text** provides additional context that is programmatically associated with fields and read by assistive technologies.
- **Validation messages** are announced when they appear so users know how to correct errors.

Following these semantics benefits all users, including those navigating with keyboards, using screen readers, or experiencing cognitive challenges.

## High-level help text

High-level help text provides context and guidance for an entire form. It should be used to explain the purpose of the form, the information that will be collected, and how the information will be used. To add high-level help text, use the `description` property on a field group object (a `FormField` type) in the form configuration's `fields` array that wraps all the form fields as children.

<Canvas of={ ContentStories.HighLevelHelpText } />

## Labels

A label tells users what information they need to enter in a field. Labels must be short, clear, and descriptive to avoid confusion.

<Canvas of={ ContentStories.Labels } />

### Guidelines

<table style={ { width: '100%' } }>
	<thead>
		<tr>
			<th style={ { width: '50%' } }>✅ Do</th>
			<th style={ { width: '50%' } }>🚫 Don't</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td style={ { width: '50%' } }>Use clear and straightforward language.</td>
			<td style={ { width: '50%' } }>Use vague or ambiguous terms like "Information" or "Details".</td>
		</tr>
		<tr>
			<td style={ { width: '50%' } }>Limit labels to 1 to 3 concise words.</td>
			<td style={ { width: '50%' } }>Exceed 3 words—longer labels create visual clutter.</td>
		</tr>
		<tr>
			<td style={ { width: '50%' } }>Remove filler words and redundant phrasing.</td>
			<td style={ { width: '50%' } }>Include filler words like "Please enter your" or "Kindly provide".</td>
		</tr>
		<tr>
			<td style={ { width: '50%' } }>Use plain language that users understand.</td>
			<td style={ { width: '50%' } }>Use technical jargon that users might not understand.</td>
		</tr>
		<tr>
			<td style={ { width: '50%' } }>Be specific and descriptive.</td>
			<td style={ { width: '50%' } }>Use generic labels like "Input" or "Field 1".</td>
		</tr>
	</tbody>
</table>

## Placeholders

A placeholder provides example input to help users understand the expected format. Use placeholders sparingly, keep them short (1 to 3 words), and use real-world examples where possible. They should only be used for formatting hints or common examples, never as a replacement for labels or instructions.

<Canvas of={ ContentStories.Placeholders } />

<table style={ { width: '100%' } }>
	<thead>
		<tr>
			<th style={ { width: '50%' } }>✅ Good</th>
			<th style={ { width: '50%' } }>🚫 Bad</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td style={ { width: '50%' } }>For a name field: "Jane Doe".</td>
			<td style={ { width: '50%' } }>For a name field: "Enter your full name here" (Should be a label or help text, not a placeholder).</td>
		</tr>
		<tr>
			<td style={ { width: '50%' } }>For an email field: "you@example.com".</td>
			<td style={ { width: '50%' } }>For a password field: "At least 8 characters" (Belongs in help text, not a placeholder).</td>
		</tr>
	</tbody>
</table>

## Help text

For complicated inputs, use help text to explain how the user should proceed. Help text is always visible, appears immediately after the input, and provides essential guidance for completing the input correctly. Help text can also inform users about how their information might be used, providing transparency and context that helps build trust and sets appropriate expectations.

Use help text when the user needs contextual guidance upfront to avoid errors, when the instruction explains why or how to complete the field correctly, when the form field has complex requirements or constraints (e.g., password rules, business logic), or when the information should be accessible without additional interaction.

<Canvas of={ ContentStories.HelpText } />

### Guidelines

<table style={ { width: '100%' } }>
	<thead>
		<tr>
			<th style={ { width: '50%' } }>✅ Do</th>
			<th style={ { width: '50%' } }>🚫 Don't</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td style={ { width: '50%' } }>Keep help text concise—one to two sentences maximum.</td>
			<td style={ { width: '50%' } }>Write lengthy paragraphs that overwhelm the user.</td>
		</tr>
		<tr>
			<td style={ { width: '50%' } }>Provide actionable, contextual guidance about why or how to complete the field.</td>
			<td style={ { width: '50%' } }>State the obvious or repeat what the label already conveys.</td>
		</tr>
		<tr>
			<td style={ { width: '50%' } }>Explain requirements or constraints that aren't obvious from the label.</td>
			<td style={ { width: '50%' } }>Duplicate format examples that belong in placeholders (e.g., "Use YYYY-MM-DD format").</td>
		</tr>
		<tr>
			<td style={ { width: '50%' } }>Focus on what the user needs to know to succeed.</td>
			<td style={ { width: '50%' } }>Include unnecessary background information or explanations.</td>
		</tr>
		<tr>
			<td style={ { width: '50%' } }>Write in plain, user-friendly language.</td>
			<td style={ { width: '50%' } }>Use technical terms or system-specific jargon.</td>
		</tr>
		<tr>
			<td style={ { width: '50%' } }>For radios or selects, explain how to choose between options.</td>
			<td style={ { width: '50%' } }>Use help text to describe what a selected value means after selection.</td>
		</tr>
	</tbody>
</table>

## Validation messages

Validation messages help users understand and fix errors in a form. They should be clear, concise, and actionable to guide users toward correcting their input.

Where possible, messages should infer what is wrong and how the user can fix it.

<Canvas of={ ContentStories.ValidationMessages } />

### Guidelines

<table style={ { width: '100%' } }>
	<thead>
		<tr>
			<th style={ { width: '50%' } }>✅ Good</th>
			<th style={ { width: '50%' } }>🚫 Bad</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td style={ { width: '50%' } }>Name must be at least 2 characters long.</td>
			<td style={ { width: '50%' } }>Invalid name.</td>
		</tr>
	</tbody>
</table>

DataViews

dataviews-dataviews · ../packages/dataviews/src/dataviews/stories/index.story.tsx
`DataViews` renders a dataset using configurable layouts (table, grid, list) with built-in search, filtering, sorting, pagination, and actions. Use it to display and manage a collection of records.
Prop types (react-component-meta) 22 prop types
Component: ../packages/dataviews/src/dataviews/index.tsx::default
Props:
/**
 * The actions that can be performed on items, shown per item and, for
 * actions supporting bulk, on multi-selections.
 */
actions?: Action<Item>[] = []

/**
 * Custom component tree rendered instead of the default layout
 * composition, using the internal `DataViews.*` sub-components.
 */
children?: ReactNode

/**
 * Static configuration of the component's UI.
 */
config?: { perPageSizes: number[]; mediaFitControl?: boolean | undefined; } = { perPageSizes: [ 10, 20, 50, 100 ] }

/**
 * The dataset to render, already filtered, sorted, and paginated
 * according to the current view.
 */
data: Item[]

/**
 * The layouts the user can switch between, mapping each supported layout
 * type to view settings applied when switching to it (or `true` for
 * defaults).
 */
defaultLayouts?: SupportedLayouts = { table: {}, grid: {}, list: {} }

/**
 * Content rendered when the dataset is empty (no items match the
 * current view).
 */
empty?: ReactNode

/**
 * The fields describing each item's data: how to get and render a value,
 * plus its sorting and filtering capabilities.
 */
fields: Field<Item>[]

/**
 * Returns a unique id for an item. Optional when items already
 * have a string `id` property, which is used by default.
 * Returns a unique id for an item. Required when items have no
 * string `id` property.
 */
getItemId?: ((item: Item) => string) | ((item: Item) => string) | undefined = ( item: ItemWithId ) => item.id

/**
 * Returns the hierarchical depth of an item, used to indent items when
 * the view's `showLevels` option is enabled.
 */
getItemLevel?: (item: Item) => number

/**
 * Extra content rendered in the toolbar area, next to the view
 * configuration controls.
 */
header?: ReactNode

/**
 * Whether an item is clickable, i.e. whether `onClickItem` or
 * `renderItemLink` applies to it.
 */
isItemClickable?: (item: Item) => boolean = () => true

/**
 * Whether the data is loading, in which case a loading state is shown.
 */
isLoading?: boolean = false

/**
 * Callback invoked with the new list of selected item ids whenever the
 * selection changes.
 */
onChangeSelection?: (items: string[]) => void

/**
 * Callback invoked with the new view whenever the user changes it
 * (filtering, sorting, switching layout, changing page, etc.).
 * Consumers own the view state and must store the new value.
 */
onChangeView: (view: View) => void

/**
 * Callback invoked when the user clicks an item's title or media.
 * Ignored when `renderItemLink` is provided.
 */
onClickItem?: (item: Item) => void

/**
 * Callback to reset the view to its initial state, wired to the
 * "Reset view" button in the view options popover. When provided, the
 * view options toggle also shows a "modified" indicator. Pass `false` to
 * render the button disabled (the view is not modified); omit the prop
 * to hide the button altogether (no reset support).
 */
onReset?: false | (() => void) | undefined

/**
 * Pagination totals for the full dataset (not just the current page).
 */
paginationInfo: { totalItems: number; totalPages: number; }

/**
 * Renders the item's title and media as a link. Receives the item along
 * with anchor props to spread onto the link element. Takes precedence
 * over `onClickItem`.
 */
renderItemLink?: (props: { item: Item; } & ClassAttributes<HTMLAnchorElement> & AnchorHTMLAttributes<HTMLAnchorElement>) => ReactElement<...>

/**
 * Whether the global search input is displayed.
 */
search?: boolean = true

/**
 * The accessible label and placeholder for the search input.
 */
searchLabel?: string = undefined

/**
 * The currently selected items, as a list of item ids. When provided
 * (together with `onChangeSelection`), selection is controlled.
 */
selection?: string[]

/**
 * The current view configuration: layout type, filters, sorting,
 * pagination, search term, and visible fields.
 */
view: View
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
    mediaFit="cover"
    mediaFitControl
    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" />;
Hierarchical Levels story ok
const HierarchicalLevels = () => <DataViews containerHeight="auto" showLevels />;
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" />;
Async Infinite Scroll story ok
Infinite scroll where pages load asynchronously (with `isLoading`), like a real network-backed consumer that fetches one window at a time. Reproduces the scroll-position jump that the synchronous story does not.
const AsyncInfiniteScroll = () => <DataViews containerHeight="auto" />;
Best practices doc ok
../packages/dataviews/src/dataviews/stories/best-practices.story.mdx
# Data Views Data Views allow users to display and interact with information through diffe...
import { Meta } from '@storybook/addon-docs/blocks';
import * as DataViewsStories from './index.story';

<Meta of={ DataViewsStories } name="Best practices" />

# Data Views

Data Views allow users to display and interact with information through different layouts such as table or grid. It includes features like search, filtering, sorting, pagination, and customization options to adjust column order, items per page, and hide columns, enhancing data exploration and flexibility.

A typical flow might be:

-   Use search and filters to narrow down a large collection.
-   Adjust the layout and visible fields to match the task (compare, skim, or visually scan).
-   Take inline actions on item metadata, or open an editing interface when more detail is needed.

## Choosing a layout

### When to use **List**

Use the **List** layout when:

-   **Content needs the most compact layout**, whether because it's used in a constrained context, or if paired with a preview surface.
-   Default information density allows for a reduced set of secondary metadata.
-   The view needs to work well in **narrow spaces**.

List is a good fit for items like Pages that benefit from a live preview next to the list.

### When to use **Grid**

Use the **Grid** layout when:

-   **Visual previews across multiple items at once are important** for recognition (patterns, templates, media, products).
-   You want a **card‑based experience**, with each item having its own tile (image + metadata).
-   You expect more **browsing and scanning by look** than comparing raw values.

Grid works well when choosing “by look” is more important than comparing precise numbers or dates.

### When to use **Table**

Use the **Table** layout when:

-   Users need to **compare multiple attributes across items** at once.
-   **Column headers and alignment** are critical for understanding the data.
-   The task involves working with structured data.

Table is ideal for dense, structured information where sorting and scanning down aligned columns is the primary workflow, such as posts or comments where metadata is important for choosing the next action.

## When to use something else

Data Views are designed for **browsing and managing collections**. In other situations, consider other components in the `@wordpress/dataviews` package:

-   **Use `DataForm`** when the primary workflow primarily relates to **creating or editing a single item** at a level that doesn't require a full editor.
-   **Use `DataViewsPicker`** when the goal is **selecting one or more items** and returning that selection to another part of the UI. This is a better fit for dialogs and sidebars where the outcome is a selection, not ongoing management of a collection, e.g. inserting from a media library.

DataViewsPicker

dataviews-dataviewspicker · ../packages/dataviews/src/dataviews-picker/stories/index.story.tsx
`DataViewsPicker` renders a dataset allowing users to select one or multiple items. It shares the layouts, search, and filtering of `DataViews` but is geared toward choosing items rather than managing them.
Prop types (react-component-meta) 18 prop types
Component: ../packages/dataviews/src/dataviews-picker/index.tsx::default
Props:
/**
 * The button actions that can be performed on items. Unlike `DataViews`,
 * pickers only support button actions (no modals).
 */
actions?: ActionButton<SpaceObject>[] = []

/**
 * Custom component tree rendered instead of the default layout
 * composition, using the internal `DataViewsPicker.*` sub-components.
 */
children?: ReactNode

/**
 * Static configuration of the component's UI.
 */
config?: { perPageSizes: number[]; mediaFitControl?: boolean | undefined; } = { perPageSizes: [ 10, 20, 50, 100 ] }

/**
 * The dataset to render, already filtered, sorted, and paginated
 * according to the current view.
 */
data: SpaceObject[]

/**
 * The layouts the user can switch between, mapping each supported layout
 * type to view settings applied when switching to it (or `true` for
 * defaults). Only picker layouts (`pickerGrid`, `pickerTable`,
 * `pickerActivity`) are supported; other layout types are ignored.
 */
defaultLayouts?: SupportedLayouts = {
	pickerGrid: true,
	pickerTable: true,
}

/**
 * Content rendered when the dataset is empty (no items match the
 * current view).
 */
empty?: ReactNode

/**
 * The fields describing each item's data: how to get and render a value,
 * plus its sorting and filtering capabilities.
 */
fields: Field<SpaceObject>[]

/**
 * Returns a unique id for an item. Required when items have no
 * string `id` property.
 */
getItemId: (item: SpaceObject) => string = ( item: ItemWithId ) => item.id

/**
 * Whether the data is loading, in which case a loading state is shown.
 */
isLoading?: boolean = false

/**
 * The accessible label for the list of items rendered by the layout.
 */
itemListLabel?: string

/**
 * Callback invoked with the new list of selected item ids whenever the
 * selection changes.
 */
onChangeSelection: (items: string[]) => void

/**
 * Callback invoked with the new view whenever the user changes it
 * (filtering, sorting, switching layout, changing page, etc.).
 * Consumers own the view state and must store the new value.
 */
onChangeView: (view: View) => void

/**
 * Callback to reset the view to its initial state, wired to the
 * "Reset view" button in the view options popover. When provided, the
 * view options toggle also shows a "modified" indicator. Pass `false` to
 * render the button disabled (the view is not modified); omit the prop
 * to hide the button altogether (no reset support).
 */
onReset?: false | (() => void) | undefined

/**
 * Pagination totals for the full dataset (not just the current page).
 */
paginationInfo: { totalItems: number; totalPages: number; }

/**
 * Whether the global search input is displayed.
 */
search?: boolean = true

/**
 * The accessible label and placeholder for the search input.
 */
searchLabel?: string = undefined

/**
 * The currently selected items, as a list of item ids. Selection is
 * always controlled in pickers, so this prop is required.
 */
selection: string[]

/**
 * The current view configuration: layout type, filters, sorting,
 * pagination, search term, and visible fields.
 */
view: View
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,
	mediaFit,
	mediaFitControl,
}: {
	perPageSizes: number[];
	isMultiselectable: boolean;
	isGrouped: boolean;
	infiniteScrollEnabled: boolean;
	mediaFit?: MediaFit;
	mediaFitControl?: boolean;
} ) => (
	<DataViewsPickerContent
		perPageSizes={ perPageSizes }
		isMultiselectable={ isMultiselectable }
		isGrouped={ isGrouped }
		infiniteScrollEnabled={ infiniteScrollEnabled }
		mediaFit={ mediaFit }
		mediaFitControl={ mediaFitControl }
	/>
);
Free Composition story ok
const FreeComposition = () => <DataViewsPicker pagination="page-select" />;
With Modal story ok
const WithModal = ( {
	perPageSizes = [ 10, 25, 50, 100 ],
	isMultiselectable,
	isGrouped,
	infiniteScrollEnabled,
	mediaFit,
	mediaFitControl,
}: {
	perPageSizes: number[];
	isMultiselectable: boolean;
	isGrouped: boolean;
	infiniteScrollEnabled: boolean;
	mediaFit?: MediaFit;
	mediaFitControl?: 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"
					__next40pxDefaultSize
					onClick={ () => setIsModalOpen( true ) }
				>
					Open Picker Modal
				</Button>
				<Button
					onClick={ () => setSelectedItems( [] ) }
					disabled={ ! selectedItems.length }
					accessibleWhenDisabled
					__next40pxDefaultSize
				>
					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 }
							mediaFit={ mediaFit }
							mediaFitControl={ mediaFitControl }
							actions={ modalActions }
							selection={ selectedItems.map( ( item ) =>
								String( item.id )
							) }
						/>
					</Modal>
				</>
			) }
		</>
	);
};

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 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 (react-component-meta) 3 prop types
Component: ../packages/components/src/disabled/index.tsx::default
Props:
/**
 * The HTML element or React component to render the component as.
 */
as?: JSXElementConstructor<any> | keyof IntrinsicElements | undefined

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

/**
 * Whether to disable all the descendant fields.
 */
isDisabled?: boolean = 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>
    );
};

Dropdown

components-dropdown · ../packages/components/src/dropdown/stories/index.story.tsx
Renders a button that opens a floating content modal when clicked. ```jsx import { Button, Dropdown } from '@wordpress/components'; const MyDropdown = () => ( <Dropdown className="my-container-class-name" contentClassName="my-dropdown-content-classname" popoverProps={ { placement: 'bottom-start' } } renderToggle={ ( { isOpen, onToggle } ) => ( <Button variant="primary" onClick={ onToggle } aria-expanded={ isOpen } > Toggle Dropdown! </Button> ) } renderContent={ () => <div>This is the content of the dropdown.</div> } /> ); ```
Prop types (react-component-meta) 15 prop types
Component: ../packages/components/src/dropdown/index.tsx::default
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.
 */
expandOnMobile?: boolean = false

/**
 * 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_.
 */
focusOnMount?: Mode | undefined = 'firstElement'

/**
 * 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<Omit<Omit<WordPressComponentProps<PopoverProps, "div", false>, "layout" | "onDrag" | "onDragEnd" | "onDragStart" | "onAnimationStart" | ... 52 more ... | "ignoreStrict"> & Pick<...>, "ref">, "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._
 */
position?: "bottom" | "top" | "middle" | "bottom center" | "bottom left" | "bottom right" | "top center" | "top left" | "top right" | "middle center" | "middle left" | "middle right" | "bottom center left" | "bottom center right" | "bottom center bottom" | "bottom center top" | "bottom left left" | "bottom left right" | "bottom left bottom" | "bottom left top" | "bottom right left" | "bottom right right" | "bottom right bottom" | "bottom right top" | "top center left" | "top center right" | "top center bottom" | "top center top" | "top left left" | "top left right" | "top left bottom" | "top left top" | "top right left" | "top right right" | "top right bottom" | "top right top" | "middle center left" | "middle center right" | "middle center bottom" | "middle center top" | "middle left left" | "middle left right" | "middle left bottom" | "middle left top" | "middle right left" | "middle right right" | "middle right bottom" | "middle right top"

/**
 * Allows getting a ref to the component instance.
 * Once the component unmounts, React will set `ref.current` to `null`
 * (or call the ref with `null` if you passed a callback ref).
 */
ref?: Ref<any> | undefined

/**
 * 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';
import { fn } from 'storybook/test';
import Button from '../../button';
import { DropdownContentWrapper } from '../dropdown-content-wrapper';
import MenuItem from '../../menu-item';
import MenuGroup from '../../menu-group';
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()}
    renderToggle={( { isOpen, onToggle } ) => (
        <Button
            __next40pxDefaultSize
            onClick={ onToggle }
            aria-expanded={ isOpen }
            variant="primary"
        >
            Open dropdown
        </Button>
    )}
    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()}
    renderToggle={( { isOpen, onToggle } ) => (
        <Button
            __next40pxDefaultSize
            onClick={ onToggle }
            aria-expanded={ isOpen }
            variant="primary"
        >
            Open dropdown
        </Button>
    )}
    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()}
    renderToggle={( { isOpen, onToggle } ) => (
        <Button
            __next40pxDefaultSize
            onClick={ onToggle }
            aria-expanded={ isOpen }
            variant="primary"
        >
            Open dropdown
        </Button>
    )}
    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>
        </>
    )} />;
DropdownContentWrapper 2 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/dropdown/dropdown-content-wrapper.tsx
A convenience wrapper for the `renderContent` when you want to apply different padding. (Default is `paddingSize="small"`). ```jsx import { Dropdown, __experimentalDropdownContentWrapper as DropdownContentWrapper, } from '@wordpress/components'; <Dropdown renderContent={ () => ( <DropdownContentWrapper paddingSize="medium"> My dropdown content </DropdownContentWrapper> ) } /> ```
import { DropdownContentWrapper } from '@wordpress/components';
Component: ../packages/components/src/dropdown/dropdown-content-wrapper.tsx::DropdownContentWrapper (react-component-meta)
/**
 * The content to render inside the wrapper.
 */
children?: ReactNode

/**
 * Amount of padding to apply on the dropdown content.
 */
paddingSize?: "small" | "medium" | "none" = 'small'

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 (react-component-meta) 7 prop types
Component: ../packages/components/src/drop-zone/index.tsx::default
Props:
/**
 * A CSS `class` to give to the wrapper element.
 */
className?: string

/**
 * An icon to be shown within the drop zone area.
 */
icon?: Element = upload

/**
 * A function to determine if the drop zone is eligible to handle the drop
 * data transfer items.
 */
isEligible?: (dataTransfer: DataTransfer) => boolean = () => true

/**
 * A string to be shown within the drop zone area.
 */
label?: string = `__( 'Drop files to upload' )`

/**
 * The function is generic drop handler called if the `onFilesDrop` or `onHTMLDrop` are not called.
 * It receives the drop `event` object as an argument.
 */
onDrop?: (event: DragEvent) => void

/**
 * The function is called when dropping a file into the `DropZone`.
 * It receives an array of dropped files as an argument.
 */
onFilesDrop?: (files: File[]) => void

/**
 * The function is called when dropping HTML into the `DropZone`.
 * It receives the HTML being dropped as an argument.
 */
onHTMLDrop?: (html: string) => void
Imports
import { DropZone } from '@wordpress/components';
import { fn } from 'storybook/test';
Default story ok
const Default = ( props ) => {
	return (
		<div
			style={ {
				background: 'lightgray',
				padding: 32,
				position: 'relative',
			} }
		>
			Drop something here
			<DropZone { ...props } />
		</div>
	);
};

EmptyState.Root

design-system-components-emptystate · ../packages/ui/src/empty-state/stories/index.story.tsx
The root container for an empty state component.
Prop types (react-component-meta) 4 prop types
Component: ../packages/ui/src/empty-state/index.ts::Root
Props:
/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Imports
import { Button, Actions, Description, Icon, Root, Title, Visual } from '@wordpress/ui';
import * as EmptyState from '../';
import { search } from '@wordpress/icons';
import { Button } from '../../button';
Default story ok
const Default = () => <EmptyState.Root>{[
        <EmptyState.Icon icon={ search } key="icon" />,
        <EmptyState.Title key="title">No results found</EmptyState.Title>,
        <EmptyState.Description key="description">
            Try adjusting your search or filter to find what you&apos;re
            looking for.
        </EmptyState.Description>,
        <EmptyState.Actions key="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 key="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 key="title">All caught up!</EmptyState.Title>,
        <EmptyState.Description key="description">
            You&apos;ve completed all your tasks. Great work!
        </EmptyState.Description>,
        <EmptyState.Actions key="actions">
            <Button>Create new task</Button>
        </EmptyState.Actions>,
    ]}</EmptyState.Root>;
EmptyState.Visual 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/empty-state/index.ts
A container for visual content in an empty state (e.g., icons, illustrations). Provides appropriate spacing and alignment for visual elements.
import { Visual } from '@wordpress/ui';
Component: ../packages/ui/src/empty-state/index.ts::Visual (react-component-meta)
/**
 * The visual content of the empty state (e.g., icon, illustration).
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
EmptyState.Icon 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/empty-state/index.ts
An icon visual for empty states. Renders an icon with styling treatment for empty states.
import { Icon } from '@wordpress/ui';
Component: ../packages/ui/src/empty-state/index.ts::Icon (react-component-meta)
/**
 * CSS class name to apply to the element.
 */
className?: string

/**
 * The icon to render.
 */
icon: ReactElement<SVGProps<SVGSVGElement>, string | JSXElementConstructor<any>>

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
EmptyState.Title 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/empty-state/index.ts
The title is a short heading that communicates the empty state.
import { Title } from '@wordpress/ui';
Component: ../packages/ui/src/empty-state/index.ts::Title (react-component-meta)
/**
 * The title text of the empty state.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined = <h2 />

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
EmptyState.Description 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/empty-state/index.ts
The description text for an empty state, providing additional context and guidance on what the user should do next.
import { Description } from '@wordpress/ui';
Component: ../packages/ui/src/empty-state/index.ts::Description (react-component-meta)
/**
 * The description text of the empty state.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined = <p />

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
EmptyState.Actions 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/empty-state/index.ts
A container for action buttons in an empty state. Actions are optional, and can include a primary and optional secondary action button.
import { Actions } from '@wordpress/ui';
Component: ../packages/ui/src/empty-state/index.ts::Actions (react-component-meta)
/**
 * The action buttons for the empty state.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

Field.Root

design-system-components-form-primitives-field · ../packages/ui/src/form/primitives/field/stories/index.story.tsx
A low-level component that associates an accessible label and description with a single form control element. To label a group of multiple form control elements, use the `Fieldset` component instead. Simply wrapping a control with this component does not guarantee accessible labeling. See examples for how to associate the label in different cases.
Prop types (react-component-meta) 7 prop types
Component: ../packages/ui/src/form/primitives/field/index.ts::Root
Props:
/**
 * A ref to imperative actions.
 * - `validate`: Validates the field when called.
 */
actionsRef?: RefObject<FieldRootActions | null>

children?: ReactNode

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

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

/**
 * Identifies the field when a form is submitted.
 * Takes precedence over the `name` prop on the `<Field.Control>` component.
 */
name?: string

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined = ( props: React.ComponentProps< typeof Stack > ) => (
	<Stack { ...props } direction="column" gap="sm" />
)

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Imports
import { Button, Control, Description, Details, Item, Label, Root, VisualLabel, Stack } from '@wordpress/ui';
import * as Field from '../';
import { DETAILS_EXAMPLE } from '../../../stories/shared';
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 key="label">Label</Field.Label>,
        <Field.Control
            render={ <input type="text" placeholder="Placeholder" /> }
            key="control"
        />,

        <Field.Description key="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 key="label">
            Label
        </Field.Label>,
        <Field.Control
            render={ <input type="text" placeholder="Placeholder" /> }
            key="control"
        />,
    ]}</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 key="label">Label</Field.Label>,
        <Field.Control
            render={ <input type="text" placeholder="Placeholder" /> }
            key="control"
        />,

        <Field.Details key="details">{ DETAILS_EXAMPLE }</Field.Details>,
    ]}</Field.Root>;
With Visual Label story ok
`Field.VisualLabel` renders a purely visual label with the same styling as `Field.Label`. It can be used outside `Field.Root` when the control is already accessibly labeled, but a visual label is still needed for layout consistency.
const WithVisualLabel = () => (
    <Stack direction="column" gap="sm" align="flex-start">
        <Field.VisualLabel>Author</Field.VisualLabel>
        <Button variant="outline">Select an author</Button>
    </Stack>
);
Field.Item 5 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/field/index.ts
import { Item } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/field/index.ts::Item (react-component-meta)
children?: ReactNode

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

/**
 * Whether the wrapped control should ignore user interaction.
 * The `disabled` prop on `<Field.Root>` takes precedence over this.
 */
disabled?: boolean = false

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Field.Label 7 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/field/index.ts
import { Label } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/field/index.ts::Label (react-component-meta)
/**
 * The label string, or the string and the element to associate it with.
 * 
 * To keep things accessible, do not include other interactive
 * elements such as links or buttons.
 */
children?: ReactNode

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

/**
 * Whether to visually hide the label while keeping it accessible
 * to screen readers.
 */
hideFromVision?: boolean = false

/**
 * Whether the component renders a native `<label>` element when replacing it via the `render` prop.
 * Set to `false` if the rendered element is not a label (for example, `<div>`).
 * 
 * This is useful to avoid inheriting label behaviors on `<button>` controls (such as `<Select.Trigger>` and `<Combobox.Trigger>`), including avoiding `:hover` on the button when hovering the label, and preventing clicks on the label from firing on the button.
 */
nativeLabel?: boolean = true

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The visual variant of the label.
 * 
 * Use 'plain' for controls like checkboxes and radio buttons.
 */
variant?: "default" | "plain" = 'default'
Field.Control 6 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/field/index.ts
import { Control } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/field/index.ts::Control (react-component-meta)
children?: ReactNode

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

/**
 * The default value to use in uncontrolled mode.
 */
defaultValue?: string | number | readonly string[] | undefined

/**
 * Callback fired when the `value` changes. Use when controlled.
 */
onValueChange?: (value: string, eventDetails: { reason: "none"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Field.Description 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/field/index.ts
import { Description } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/field/index.ts::Description (react-component-meta)
/**
 * The accessible description, associated using `aria-describedby`.
 * 
 * For screen reader accessibility, this should only contain plain text,
 * and no semantics such as links.
 */
children?: string

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Field.Details 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/field/index.ts
A component for showing additional information about the field, styled similarly to a normal `Field.Description`. Unlike a normal description, it can include links and other semantic elements. 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.
import { Details } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/field/index.ts::Details (react-component-meta)
/**
 * Additional information about the field, which unlike a normal description,
 * can include links and other semantic elements.
 * 
 * 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.
 * 
 * Do not use this component when the details content is only plain text,
 * as it makes the readout unnecessarily verbose for screen reader users.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Field.VisualLabel 5 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/field/index.ts
Renders a purely visual label with the same styling as `Field.Label`. It can be used outside `Field.Root` when the control is already accessibly labeled, but a visual label is still needed for layout consistency. Unlike `Field.Label`, this component does not carry semantics and is not associated with a control.
import { VisualLabel } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/field/index.ts::VisualLabel (react-component-meta)
/**
 * Visible label text. Not associated with a control.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The visual variant of the label.
 * 
 * Use 'plain' for controls like checkboxes and radio buttons.
 */
variant?: "default" | "plain" = 'default'

Fieldset.Root

design-system-components-form-primitives-fieldset · ../packages/ui/src/form/primitives/fieldset/stories/index.story.tsx
A low-level component that associates an accessible legend and description with a group of multiple form control elements. To label a single form control element, use the `Field` component instead.
Prop types (react-component-meta) 4 prop types
Component: ../packages/ui/src/form/primitives/fieldset/index.ts::Root
Props:
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Imports
import { Description, Details, Legend, Root } from '@wordpress/ui';
import * as Fieldset from '../';
import { DETAILS_EXAMPLE } from '../../../stories/shared';
Default story ok
const Default = () => <Fieldset.Root>{[
        <Fieldset.Legend key="legend">Legend</Fieldset.Legend>,
        <Fieldset.Description key="description">
            This is a description for the entire fieldset.
        </Fieldset.Description>,
        [ 'Apples', 'Bananas' ].map( ( fruit ) => (
            // eslint-disable-next-line jsx-a11y/label-has-associated-control
            (<label key={ fruit }>
                <input type="checkbox" /> { fruit }
            </label>)
        ) ),
    ]}</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 key="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.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 key="legend">Legend</Fieldset.Legend>,
        <Fieldset.Details key="details">
            { DETAILS_EXAMPLE }
        </Fieldset.Details>,
        [ 'Apples', 'Bananas' ].map( ( fruit ) => (
            // eslint-disable-next-line jsx-a11y/label-has-associated-control
            (<label key={ fruit }>
                <input type="checkbox" /> { fruit }
            </label>)
        ) ),
    ]}</Fieldset.Root>;
Fieldset.Legend 5 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/fieldset/index.ts
import { Legend } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/fieldset/index.ts::Legend (react-component-meta)
children?: ReactNode

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

/**
 * Whether to visually hide the legend while keeping it accessible
 * to screen readers.
 */
hideFromVision?: boolean = false

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Fieldset.Description 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/fieldset/index.ts
import { Description } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/fieldset/index.ts::Description (react-component-meta)
/**
 * The accessible description, associated using `aria-describedby`.
 * 
 * For screen reader accessibility, this should only contain plain text,
 * and no semantics such as links.
 */
children?: string

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Fieldset.Details 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/fieldset/index.ts
A component for showing additional information about the fieldset, styled similarly to a normal `Fieldset.Description`. Unlike a normal description, it can include links and other semantic elements. 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.
import { Details } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/fieldset/index.ts::Details (react-component-meta)
/**
 * Additional information about the fieldset, which unlike a normal description,
 * can include links and other semantic elements.
 * 
 * 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.
 * 
 * Do not use this component when the details content is only plain text,
 * as it makes the readout unnecessarily verbose for screen reader users.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

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 accept="image/*" onChange={ ( event ) => console.log( event.currentTarget.files ) } > Upload </FormFileUpload> ); ```
Prop types (react-component-meta) 8 prop types
Component: ../packages/components/src/form-file-upload/index.tsx::default
Props:
/**
 * Start opting into the larger default height that will become the default size in a future version.
 */
__next40pxDefaultSize?: boolean

/**
 * A string passed to the `input` element that tells the browser which
 * [file types](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Unique_file_type_specifiers)
 * can be uploaded by the user. e.g: `image/*,video/*`.
 */
accept?: string

/**
 * Children are passed as children of `Button`.
 */
children?: ReactNode

/**
 * The icon to render in the default button.
 * 
 * See the `Icon` component docs for more information.
 */
icon?: IconType | null | undefined

/**
 * Whether to allow multiple selection of files or not.
 */
multiple?: boolean = false

/**
 * Callback function passed directly to the `input` file element.
 * 
 * Select files will be available in `event.currentTarget.files`.
 */
onChange: ChangeEventHandler<HTMLInputElement, HTMLInputElement> | undefined

/**
 * Callback function passed directly to the `input` file element.
 * 
 * This can be useful when you want to force a `change` event to fire when
 * the user chooses the same file again. To do this, set the target value to
 * an empty string in the `onClick` function.
 * 
 * ```jsx
 * <FormFileUpload
 *   onClick={ ( event ) => ( event.target.value = '' ) }
 *   onChange={ onChange }
 * >
 *   Upload
 * </FormFileUpload>
 * ```
 */
onClick?: MouseEventHandler<HTMLInputElement>

/**
 * Optional callback function used to render the UI.
 * 
 * If passed, the component does not render the default UI (a button) and
 * calls this function to render it. The function receives an object with
 * property `openFileDialog`, a function that, when called, opens the browser
 * native file upload modal window.
 */
render?: (arg: { openFileDialog: () => void; }) => ReactNode
Imports
import { FormFileUpload } from '@wordpress/components';
import { upload as uploadIcon } from '@wordpress/icons';
Default story ok
const Default = ( props ) => {
	return <FormFileUpload { ...props } />;
};
Restrict File Types story ok
const RestrictFileTypes = ( props ) => {
	return <FormFileUpload { ...props } />;
};
Allow Multiple Files story ok
const AllowMultipleFiles = ( props ) => {
	return <FormFileUpload { ...props } />;
};
With Icon story ok
const WithIcon = ( props ) => {
	return <FormFileUpload { ...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 { ...props } />;
};

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 (react-component-meta) 28 prop types
Component: ../packages/components/src/form-token-field/index.tsx::default
Props:
/**
 * If true, the select the first matching suggestion when the user presses
 * the Enter key (or space when tokenizeOnSpace is true).
 */
__experimentalAutoSelectFirstMatch?: boolean = false

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

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

/**
 * Use the `help` prop instead. The `help` prop now defaults to the previous
 * how-to text; if you were passing `__experimentalShowHowTo={ false }` to
 * hide it, pass an empty string to `help` instead.
 */
__experimentalShowHowTo?: boolean

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

/**
 * Deprecated. Use `__next40pxDefaultSize` instead.
 */
__next36pxDefaultSize?: boolean = false

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

/**
 * Start opting into the new margin-free styles that will become the default in a future version.
 */
__nextHasNoMarginBottom?: boolean = false

autoCapitalize?: "none" | (string & {}) | "off" | "on" | "sentences" | "words" | "characters" | undefined

autoComplete?: HTMLInputAutoCompleteAttribute | undefined

className?: string

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

/**
 * 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 = ( value: string ) => value

/**
 * Additional description for the control.
 * 
 * Only use for meaningful description or instructions for the control. An
 * element containing the description will be programmatically associated to
 * the `FormTokenField` via `aria-describedby`.
 * 
 * Defaults to a how-to message (e.g. _Separate with commas or the Enter key._);
 * pass an empty string to hide it.
 */
help?: ReactNode

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

label?: string = __( 'Add item' )

/**
 * 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.
 */
maxSuggestions?: number = 100

/**
 * 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?: Messages = {
			added: __( 'Item added.' ),
			removed: __( 'Item removed.' ),
			remove: __( 'Remove item' ),
			__experimentalInvalid: __( 'Invalid item' ),
		}

/**
 * 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<Element, Element>) => void = undefined

/**
 * 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.)
 */
saveTransform?: (token: string) => string = ( token ) => token.trim()

/**
 * 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.
 */
tokenizeOnBlur?: boolean = false

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

/**
 * 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
            label="Type a continent"
            suggestions={[
                'Africa',
                'America',
                'Antarctica',
                'Asia',
                'Europe',
                'Oceania',
            ]}
            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
            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
            label="Type a continent"
            suggestions={[
                'Africa',
                'America',
                'Antarctica',
                'Asia',
                'Europe',
                'Oceania',
            ]}
            __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
            label="Type a continent"
            suggestions={[
                'Africa',
                'America',
                'Antarctica',
                'Asia',
                'Europe',
                'Oceania',
            ]}
            displayTransform={( token ) => `📍 ${ token }`}
            __experimentalRenderItem={( { item } ) => (
                <div>{ `${ item } — a nice place to visit` }</div>
            )}
            __experimentalExpandOnFocus
            value={ selectedContinents }
            onChange={ ( tokens ) => setSelectedContinents( tokens ) } />
    );
};
Validate New Tokens incomplete example
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
            label="Type a continent"
            suggestions={[
                'Africa',
                'America',
                'Antarctica',
                'Asia',
                'Europe',
                'Oceania',
            ]}
            __experimentalValidateInput={( input: string ) =>
                continents.includes( input )}
            __experimentalExpandOnFocus
            value={ selectedContinents }
            onChange={ ( tokens ) => setSelectedContinents( tokens ) } />
    );
};
Incomplete snippet: `continents` could not be resolved statically.

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 (react-component-meta) 16 prop types
Component: ../packages/components/src/gradient-picker/index.tsx::default
Props:
/**
 * Whether this is rendered in the sidebar.
 */
__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.)
 */
__nextHasNoMargin?: boolean = false

/**
 * A label to identify the purpose of the control.
 */
aria-label?: string

/**
 * An ID of an element to provide a label for the control.
 */
aria-labelledby?: string

/**
 * Whether the control should present as toggle buttons.
 */
asButtons?: boolean = false

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

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

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

/**
 * Whether to enable alpha transparency options in the picker.
 */
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.
 */
gradients?: GradientsProp | undefined = []

/**
 * 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).
 */
headingLevel?: 1 | 2 | "1" | "2" | "3" | 3 | 4 | 5 | 6 | "4" | "5" | "6" = 2

/**
 * Prevents keyboard interaction from wrapping around.
 * Only used with the `listbox` presentation.
 */
loop?: boolean = true

/**
 * The function called when a new gradient has been defined. It is passed
 * the `currentGradient` as an argument. When a predefined gradient is
 * selected, the second argument is its index (or, for multiple-origin
 * gradients, the origin index) and the third argument is its slug.
 */
onChange: (currentGradient: string | undefined, index?: number | undefined, slug?: string | undefined) => void

/**
 * How predefined gradient swatches behave and are exposed to assistive
 * technology.
 * 
 * - `listbox` uses one tab stop and arrow-key navigation, and exposes
 *   selection with `aria-selected`.
 * - `toggle-buttons` gives each swatch a tab stop and exposes selection with
 *   `aria-pressed`.
 * - `command-buttons` gives each swatch a tab stop and exposes no selection
 *   state. `value` and `selectedSlug` do not mark predefined swatches as
 *   selected, and activating a swatch always calls `onChange` with that
 *   swatch. `value` still controls the custom gradient picker.
 */
presentation?: "listbox" | "toggle-buttons" | "command-buttons" = 'listbox'

/**
 * The slug of the currently selected predefined gradient.
 * 
 * When set to a non-empty string, selection is determined by slug rather
 * than by gradient value, which correctly handles palettes where two
 * entries share the same gradient. Entries whose slug does not match will
 * not appear selected in this mode, even if their gradient value matches
 * `value`.
 * 
 * An empty string is treated the same as `undefined`: selection falls
 * back to matching by gradient value.
 */
selectedSlug?: string

/**
 * 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.
 */
value?: string | null | undefined = 'linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)'
Imports
import { GradientPicker } from '@wordpress/components';
import { fn } from 'storybook/test';
Default story ok
const Default = ( {
	onChange,
	value,
	selectedSlug,
	...props
}: React.ComponentProps< typeof GradientPicker > ) => {
	const [ gradient, setGradient ] = useState<
		React.ComponentProps< typeof GradientPicker >[ 'value' ]
	>( value ?? null );
	const [ slug, setSlug ] = useState< string | undefined >( selectedSlug );
	return (
		<GradientPicker
			{ ...props }
			value={ gradient }
			selectedSlug={ slug }
			onChange={ ( currentGradient, index, newSlug ) => {
				setGradient( currentGradient );
				setSlug( newSlug );
				onChange?.( currentGradient, index, newSlug );
			} }
		/>
	);
};
With No Existing Gradients story ok
const WithNoExistingGradients = ( {
	onChange,
	value,
	selectedSlug,
	...props
}: React.ComponentProps< typeof GradientPicker > ) => {
	const [ gradient, setGradient ] = useState<
		React.ComponentProps< typeof GradientPicker >[ 'value' ]
	>( value ?? null );
	const [ slug, setSlug ] = useState< string | undefined >( selectedSlug );
	return (
		<GradientPicker
			{ ...props }
			value={ gradient }
			selectedSlug={ slug }
			onChange={ ( currentGradient, index, newSlug ) => {
				setGradient( currentGradient );
				setSlug( newSlug );
				onChange?.( currentGradient, index, newSlug );
			} }
		/>
	);
};
Duplicate Gradients story ok
const DuplicateGradients = ( {
	onChange,
	value,
	selectedSlug,
	...props
}: React.ComponentProps< typeof GradientPicker > ) => {
	const [ gradient, setGradient ] = useState<
		React.ComponentProps< typeof GradientPicker >[ 'value' ]
	>( value ?? null );
	const [ slug, setSlug ] = useState< string | undefined >( selectedSlug );
	return (
		<GradientPicker
			{ ...props }
			value={ gradient }
			selectedSlug={ slug }
			onChange={ ( currentGradient, index, newSlug ) => {
				setGradient( currentGradient );
				setSlug( newSlug );
				onChange?.( currentGradient, index, newSlug );
			} }
		/>
	);
};
Multiple Origins incomplete example
const MultipleOrigins = ( {
	onChange,
	value,
	selectedSlug,
	...props
}: React.ComponentProps< typeof GradientPicker > ) => {
	const [ gradient, setGradient ] = useState<
		React.ComponentProps< typeof GradientPicker >[ 'value' ]
	>( value ?? null );
	const [ slug, setSlug ] = useState< string | undefined >( selectedSlug );
	return (
		<GradientPicker
			{ ...props }
			value={ gradient }
			selectedSlug={ slug }
			onChange={ ( currentGradient, index, newSlug ) => {
				setGradient( currentGradient );
				setSlug( newSlug );
				onChange?.( currentGradient, index, newSlug );
			} }
		/>
	);
};
Incomplete snippet: `GRADIENTS` could not be resolved statically.
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>;

Icon

design-system-components-icon · ../packages/ui/src/icon/stories/index.story.tsx
Renders an SVG icon with a 24px default size. ```jsx import { wordpress } from '@wordpress/icons'; <Icon icon={ wordpress } /> ```
Prop types (react-component-meta) 2 prop types
Component: ../packages/ui/src/icon/index.ts::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).
 * 
 * When using `@wordpress/icons`, only version 15.0.0 or later is supported.
 * For custom SVGs, use `currentColor` for any fill or stroke that should
 * follow the surrounding text color.
 */
icon: ReactElement<SVGProps<SVGSVGElement>, string | JSXElementConstructor<any>>

/**
 * The size (width and height) of the icon.
 */
size?: number = 24
Imports
import { Icon } from '@wordpress/ui';
import { wordpress } from '@wordpress/icons';
Default story ok
const Default = () => <Icon icon={wordpress} />;

Input

design-system-components-form-primitives-input · ../packages/ui/src/form/primitives/input/stories/index.story.tsx
A low-level primitive for an input field. Prefer `InputControl` when using with a standard label and description.
Prop types (react-component-meta) 11 prop types
Component: ../packages/ui/src/form/primitives/input/index.ts::Input
Props:
/**
 * CSS class name to apply to the element.
 */
className?: string

/**
 * The default value to use in uncontrolled mode.
 */
defaultValue?: string | number | readonly string[] | undefined

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

/**
 * Callback fired when the `value` changes. Use when controlled.
 */
onValueChange?: (value: string, eventDetails: { reason: "none"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void

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

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

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

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

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

/**
 * The type of the input element.
 */
type?: HTMLInputTypeAttribute | undefined

/**
 * The value to use in controlled mode.
 */
value?: string | number | readonly string[] | undefined
Imports
import { Input, InputLayout } from '@wordpress/ui';
import { InputLayout } from '../../input-layout';
import { WithSuffixControl as InputLayoutWithSuffixControl } from '../../input-layout/stories/index.story';
Default story ok
const Default = () => <Input placeholder="Placeholder" aria-label="Value" />;
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"
    aria-label="Username"
    prefix={<InputLayout.Slot>@</InputLayout.Slot>} />;
With Suffix Control story ok
const WithSuffixControl = () => <Input aria-label="Value" suffix={InputLayoutWithSuffixControl.args?.suffix} />;
Disabled story ok
const Disabled = () => <Input placeholder="Placeholder" aria-label="Value" disabled />;

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 (react-component-meta) 15 prop types
Component: ../packages/ui/src/form/input-control/index.ts::InputControl
Props:
/**
 * CSS class name to apply to the element.
 */
className?: string

/**
 * The default value to use in uncontrolled mode.
 */
defaultValue?: string | number | readonly string[] | undefined

/**
 * The accessible description, associated using `aria-describedby`.
 * 
 * For screen reader accessibility, this should only contain plain text,
 * and no semantics such as links.
 */
description?: string

/**
 * 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?: ReactNode

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

/**
 * Whether to visually hide the label while keeping it accessible
 * to screen readers.
 */
hideLabelFromVision?: boolean = false

/**
 * The accessible label. All controls must be labeled.
 */
label: string

/**
 * Callback fired when the `value` changes. Use when controlled.
 */
onValueChange?: (value: string, eventDetails: { reason: "none"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void

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

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * The size of the field.
 */
size?: "default" | "compact"

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

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

/**
 * The type of the input element.
 */
type?: HTMLInputTypeAttribute | undefined

/**
 * The value to use in controlled mode.
 */
value?: string | number | readonly string[] | undefined
Imports
import { IconButton, InputControl, InputLayout, Stack } from '@wordpress/ui';
import { DETAILS_EXAMPLE } from '../../stories/shared';
Default story ok
const Default = () => <InputControl
    label="Label"
    description="This is the description."
    placeholder="Placeholder" />;
Visually Hidden Label story ok
const VisuallyHiddenLabel = () => <InputControl
    label="Label"
    description="This is the description."
    placeholder="Placeholder"
    hideLabelFromVision />;
With Details story ok
const WithDetails = () => <InputControl
    label="Label"
    description={undefined}
    placeholder="Placeholder"
    details={DETAILS_EXAMPLE} />;
With Prefix incomplete example
const WithPrefix = () => <InputControl
    ref={undefined}
    label="Label"
    description="This is the description."
    placeholder="Placeholder" />;
Incomplete snippet: `...InputWithPrefix.args` could not be resolved statically.
With Suffix Control incomplete example
const WithSuffixControl = () => <InputControl
    ref={undefined}
    label="Label"
    description="This is the description."
    placeholder="Placeholder" />;
Incomplete snippet: `...InputWithSuffixControl.args` could not be resolved statically.
Password story ok
const Password = () => {
    const [ show, setShow ] = useState( false );

    return (
        <InputControl
            label="Label"
            description="This is the description."
            placeholder="Placeholder"
            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
    label="Label"
    description="This is the description."
    placeholder="Placeholder"
    type="date" />;
Number story ok
const Number = () => <InputControl
    label="Label"
    description="This is the description."
    placeholder="0"
    type="number" />;
Number With Steppers story ok
const NumberWithSteppers = () => {
    const [ value, setValue ] = useState( 0 );

    return (
        <InputControl
            label="Label"
            description="This is the description."
            placeholder="0"
            type="number"
            value={ value }
            onValueChange={ ( v ) => setValue( parseInt( v, 10 ) ) }
            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
    label="Label"
    description="This is the description."
    placeholder="Placeholder"
    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 (react-component-meta) 5 prop types
Component: ../packages/ui/src/form/primitives/input-layout/index.ts::InputLayout
Props:
/**
 * Whether the field should hide the border.
 */
isBorderless?: boolean

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

/**
 * The size of the field.
 * 
 * The 'small' size is reserved for rare use cases. Most components should not support it.
 */
size?: "small" | "default" | "compact" = 'default'

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

/**
 * Whether the field should be visually styled as disabled.
 */
visuallyDisabled?: boolean
Imports
import { IconButton, InputLayout } from '@wordpress/ui';
import { InputLayout } from '../';
import { IconButton } from '../../../../icon-button';
import { copy } from '@wordpress/icons';
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" />;
InputLayout.Slot 1 prop type
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/input-layout/index.ts
A layout helper to add paddings in a prefix or suffix.
import { InputLayout } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/input-layout/index.ts::InputLayout (react-component-meta)
/**
 * The padding of the slot.
 * 
 * `minimal` will work best when the slot content is a button or icon.
 */
padding?: "default" | "minimal" = 'default'

ItemGroup

components-itemgroup · ../packages/components/src/item-group/stories/index.story.tsx
`ItemGroup` displays a list of `Item`s grouped and styled together. ```jsx import { __experimentalItemGroup as ItemGroup, __experimentalItem as Item, } from '@wordpress/components'; function Example() { return ( <ItemGroup> <Item>Code</Item> <Item>is</Item> <Item>Poetry</Item> </ItemGroup> ); } ```
Prop types (react-component-meta) 6 prop types
Component: ../packages/components/src/item-group/item-group/component.tsx::ItemGroup
Props:
/**
 * The HTML element or React component to render the component as.
 */
as?: JSXElementConstructor<any> | keyof IntrinsicElements | undefined

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

/**
 * Renders a border around the itemgroup.
 */
isBordered?: boolean = false

/**
 * Renders with rounded corners.
 */
isRounded?: boolean = true

/**
 * Renders a separator between each item.
 */
isSeparated?: boolean = false

/**
 * Determines the amount of padding within the component.
 */
size?: "small" | "medium" | "large" = 'medium'
Imports
import { Item, ItemGroup } from '@wordpress/components';
Default incomplete example
const Default = ( props ) => (
	<ItemGroup { ...props } />
);
Incomplete snippet: `mapPropsToItem` could not be resolved statically.
Non Clickable Items incomplete example
const NonClickableItems = ( props ) => (
	<ItemGroup { ...props } />
);
Incomplete snippet: `mapPropsToItem` could not be resolved statically.
Custom Item Size incomplete example
const CustomItemSize = ( props ) => (
	<ItemGroup { ...props } />
);
Incomplete snippet: `mapPropsToItem` could not be resolved statically.
Without Border incomplete example
const WithoutBorder = ( props ) => (
	<ItemGroup { ...props } />
);
Incomplete snippet: `mapPropsToItem` could not be resolved statically.
Item 3 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/item-group/item/component.tsx
`Item` is used in combination with `ItemGroup` to display a list of items grouped and styled together. ```jsx import { __experimentalItemGroup as ItemGroup, __experimentalItem as Item, } from '@wordpress/components'; function Example() { return ( <ItemGroup> <Item>Code</Item> <Item>is</Item> <Item>Poetry</Item> </ItemGroup> ); } ```
import { Item } from '@wordpress/components';
Component: ../packages/components/src/item-group/item/component.tsx::Item (react-component-meta)
/**
 * The HTML element or React component to render the component as.
 */
as?: JSXElementConstructor<any> | keyof IntrinsicElements | undefined

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

/**
 * Determines the amount of padding within the component.
 */
size?: "small" | "medium" | "large" = 'medium'

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 (react-component-meta) 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?: boolean

/**
 * Elements to render, upon whom key events are to be monitored.
 */
children?: 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?: string

/**
 * 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.
 */
shortcuts: Record<string, (event: ExtendedKeyboardEvent, combo: string) => void>
Imports
import { KeyboardShortcuts } from '@wordpress/components';
Default story ok
const Default = ( props ) => (
	<KeyboardShortcuts { ...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. See the [Usage Guidelines](https://wordpress.github.io/gutenberg/?path=/docs/design-system-components-button-usage-guidelines--docs) for when to use `Button`, `IconButton`, `Link`, or `ButtonLink`.
Prop types (react-component-meta) 8 prop types
Component: ../packages/ui/src/link/index.ts::Link
Props:
/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

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

/**
 * Adds a visual indicator and accessible notice for opening in a new tab.
 * Defaults `target` to `"_blank"` when no explicit target is set.
 */
openInNewTab?: boolean = false

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * Where to open the linked document. `"_blank"` also adds the visual
 * indicator and accessible new-tab notice.
 * 
 * When both `target` and `openInNewTab` are set, `target` determines the
 * browsing context.
 */
target?: HTMLAttributeAnchorTarget | undefined

/**
 * The tone of the link. Tone describes a semantic color intent.
 * Only applies when `variant` is `default`.
 */
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.
 */
variant?: "default" | "unstyled" = 'default'
Imports
import { Link, Stack, Text } from '@wordpress/ui';
Default story ok
const Default = () => <Link href="#">Learn more</Link>;
Open In New Tab story ok
const OpenInNewTab = () => <Link href="https://wordpress.org" openInNewTab>Visit WordPress.org</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 href="#">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, keep `Text` as the host and pass `Link` via `render` so the resulting element stays an `<a>`.
const Standalone = ( args ) => (
    <Text variant="body-md" render={ <Link { ...args } /> }>
        A standalone link with body-md typography
    </Text>
);

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 (react-component-meta) 4 prop types
Component: ../packages/components/src/menu-group/index.tsx::default
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, NavigableMenu } from '@wordpress/components';
Default story ok
const Default = () => {
    return (
        <NavigableMenu>
            <MenuGroup>
                <MenuItem>Menu Item 1</MenuItem>
                <MenuItem>Menu Item 2</MenuItem>
            </MenuGroup>
        </NavigableMenu>
    );
};
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 (
        <NavigableMenu>
            <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>
        </NavigableMenu>
    );
};

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> ); }; ```
Prop types (react-component-meta) 11 prop types
Component: ../packages/components/src/menu-item/index.tsx::default
Props:
/**
 * The children elements.
 */
children?: ReactNode

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

/**
 * The icon to render. Supported values are: Dashicons (specified as
 * strings), functions, Component instances and `null`.
 */
icon?: Element | null | undefined = null

/**
 * Determines where to display the provided `icon`.
 */
iconPosition?: "left" | "right" = 'right'

/**
 * Text to use as description for button text.
 */
info?: string

/**
 * Renders a red text-based button style to indicate destructive behavior.
 */
isDestructive?: boolean

/**
 * Whether or not the menu item is currently selected, `isSelected` is only taken into
 * account when the `role` prop is either `"menuitemcheckbox"` or `"menuitemradio"`.
 */
isSelected?: boolean

/**
 * Human-readable label for item.
 */
label?: string

/**
 * If you need to have selectable menu items use menuitemradio for single select,
 * and menuitemcheckbox for multiselect.
 */
role?: string = 'menuitem'

/**
 * 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?: string | { display: string; ariaLabel: string; } | undefined

/**
 * Allows for markup other than icons or shortcuts to be added to the menu item.
 */
suffix?: ReactNode
Imports
import { MenuGroup, MenuItem, NavigableMenu, Shortcut } from '@wordpress/components';
import { link } from '@wordpress/icons';
import Shortcut from '../../shortcut';
Default story ok
const Default = ( props ) => {
	return (
		<NavigableMenu>
			<MenuGroup>
				<MenuItem { ...props }>Menu Item 1</MenuItem>
			</MenuGroup>
		</NavigableMenu>
	);
};
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 (
		<NavigableMenu>
			<MenuGroup>
				<MenuItem { ...props }>Menu Item 1</MenuItem>
			</MenuGroup>
		</NavigableMenu>
	);
};
With Icon story ok
const WithIcon = ( props ) => {
	return (
		<NavigableMenu>
			<MenuGroup>
				<MenuItem { ...props }>Menu Item 1</MenuItem>
			</MenuGroup>
		</NavigableMenu>
	);
};
With Info story ok
const WithInfo = ( props ) => {
	return (
		<NavigableMenu>
			<MenuGroup>
				<MenuItem { ...props }>Menu Item 1</MenuItem>
			</MenuGroup>
		</NavigableMenu>
	);
};
With Suffix story ok
const WithSuffix = ( props ) => {
	return (
		<NavigableMenu>
			<MenuGroup>
				<MenuItem { ...props }>Menu Item 1</MenuItem>
			</MenuGroup>
		</NavigableMenu>
	);
};

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 (react-component-meta) 4 prop types
Component: ../packages/components/src/menu-items-choice/index.tsx::default
Props:
/**
 * Array of choices.
 */
choices: readonly MenuItemChoice[] = []

/**
 * Callback function to be called with a choice when user
 * hovers over a new choice (will be empty on mouse leave).
 */
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, NavigableMenu } from '@wordpress/components';
Default story ok
const Default = ( {
	onHover,
	onSelect,
	choices,
} ) => {
	const [ choice, setChoice ] = useState( choices[ 0 ]?.value ?? '' );

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

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 (react-component-meta) 23 prop types
Component: ../packages/components/src/modal/index.tsx::default
Props:
/**
 * When set to `true`, the Modal's header (including the icon, title and
 * close button) will not be rendered. A `title` is then applied to the
 * dialog as its `aria-label`, so the dialog keeps an accessible name.
 * 
 * _Warning_: This property is still experimental. “Experimental” means this
 * is an early implementation subject to drastic and breaking changes.
 */
__experimentalHideHeader?: boolean = false

aria?: { describedby?: string | undefined; labelledby?: string | undefined; } = {
			labelledby: undefined,
			describedby: undefined,
		}

/**
 * Class name added to the body element when the modal is open.
 * If you use a custom class name, its styles must set `overflow: hidden`
 * to preserve the Modal's scroll lock.
 */
bodyOpenClassName?: string = 'modal-open'

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

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

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

/**
 * 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_.
 */
focusOnMount?: Mode | "firstContentElement" | undefined = true

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

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

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

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

key?: Key | null | undefined

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

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

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

/**
 * Allows getting a ref to the component instance.
 * Once the component unmounts, React will set `ref.current` to `null`
 * (or call the ref with `null` if you passed a callback ref).
 */
ref?: Ref<HTMLDivElement> | undefined

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

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

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

/**
 * 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" | "fill" | "medium" | "large"

/**
 * If this property is added, it will be added to the modal frame `div`.
 */
style?: 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 = null
Imports
import { Button, InputControl, Modal } from '@wordpress/components';
import Button from '../../button';
import { fullscreen } from '@wordpress/icons';
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 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 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 style={ { marginBottom: '20px' } } />

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

Navigator

components-navigator · ../packages/components/src/navigator/stories/index.story.tsx
The `Navigator` component allows rendering nested views/panels/menus (via the `Navigator.Screen` component) and navigate between them (via the `Navigator.Button` and `Navigator.BackButton` components). ```jsx import { Navigator } from '@wordpress/components'; const MyNavigation = () => ( <Navigator initialPath="/"> <Navigator.Screen path="/"> <p>This is the home screen.</p> <Navigator.Button path="/child"> Navigate to child screen. </Navigator.Button> </Navigator.Screen> <Navigator.Screen path="/child"> <p>This is the child screen.</p> <Navigator.BackButton> Go back </Navigator.BackButton> </Navigator.Screen> </Navigator> ); ```
Prop types (react-component-meta) 3 prop types
Component: ../packages/components/src/navigator/index.tsx::Navigator
Props:
/**
 * The HTML element to render the component as.
 */
as: "symbol" | "object" | "search" | "big" | "link" | "small" | "sub" | "sup" | "map" | "filter" | "data" | "form" | "text" | "time" | "label" | "header" | "desc" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "blockquote" | "body" | "br" | "button" | "canvas" | "caption" | "center" | "cite" | "code" | "col" | "colgroup" | "datalist" | "dd" | "del" | "details" | "dfn" | "dialog" | "div" | "dl" | "dt" | "em" | "embed" | "fieldset" | "figcaption" | "figure" | "footer" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "head" | "hgroup" | "hr" | "html" | "i" | "iframe" | "img" | "input" | "ins" | "kbd" | "keygen" | "legend" | "li" | "main" | "mark" | "menu" | "menuitem" | "meta" | "meter" | "nav" | "noindex" | "noscript" | "ol" | "optgroup" | "option" | "output" | "p" | "param" | "picture" | "pre" | "progress" | "q" | "rp" | "rt" | "ruby" | "s" | "samp" | "slot" | "script" | "section" | "select" | "source" | "span" | "strong" | "style" | "summary" | "table" | "template" | "tbody" | "td" | "textarea" | "tfoot" | "th" | "thead" | "title" | "tr" | "track" | "u" | "ul" | "var" | "video" | "wbr" | "webview" | "svg" | "animate" | "animateMotion" | "animateTransform" | "circle" | "clipPath" | "defs" | "ellipse" | "feBlend" | "feColorMatrix" | "feComponentTransfer" | "feComposite" | "feConvolveMatrix" | "feDiffuseLighting" | "feDisplacementMap" | "feDistantLight" | "feDropShadow" | "feFlood" | "feFuncA" | "feFuncB" | "feFuncG" | "feFuncR" | "feGaussianBlur" | "feImage" | "feMerge" | "feMergeNode" | "feMorphology" | "feOffset" | "fePointLight" | "feSpecularLighting" | "feSpotLight" | "feTile" | "feTurbulence" | "foreignObject" | "g" | "image" | "line" | "linearGradient" | "marker" | "mask" | "metadata" | "mpath" | "path" | "pattern" | "polygon" | "polyline" | "radialGradient" | "rect" | "set" | "stop" | "switch" | "textPath" | "tspan" | "use" | "view"

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

/**
 * The initial active path.
 */
initialPath: string
Imports
import { Button, HStack, Navigator, VStack } from '@wordpress/components';
import { Navigator } from '../';
import { VStack } from '../../v-stack';
import { HStack } from '../../h-stack';
Default incomplete example
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>;
Incomplete snippet: `DynamicScreen` could not be resolved statically.
With Nested Initial Path incomplete example
const WithNestedInitialPath = () => <Navigator initialPath="/child/grandchild">(<>
        <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>;
Incomplete snippet: `DynamicScreen` could not be resolved statically.
Skip Focus incomplete example
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>;
Incomplete snippet: `NavigatorButtonWithSkipFocus` could not be resolved statically.
Screen 2 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/navigator/index.tsx
The `Navigator.Screen` component represents a single view/screen/panel and should be used in combination with the `Navigator`, the `Navigator.Button` and the `Navigator.BackButton` components.
example: ```jsx import { Navigator } from '@wordpress/components'; const MyNavigation = () => ( <Navigator initialPath="/"> <Navigator.Screen path="/"> <p>This is the home screen.</p> <Navigator.Button path="/child"> Navigate to child screen. </Navigator.Button> </Navigator.Screen> <Navigator.Screen path="/child"> <p>This is the child screen.</p> <Navigator.BackButton> Go back </Navigator.BackButton> </Navigator.Screen> </Navigator> ); ```
import { Navigator } from '@wordpress/components';
Component: ../packages/components/src/navigator/index.tsx::Navigator (react-component-meta)
/**
 * The children elements.
 */
children: ReactNode

/**
 * The screen's path, matched against the current path stored in the navigator.
 * 
 * `Navigator` assumes that screens are organized hierarchically according
 * to their `path`, which should follow a URL-like scheme where each path
 * segment starts with and is separated by the `/` character.
 * 
 * `Navigator` will treat "back" navigations as going to the parent screen —
 * it is, therefore, the responsibility of the consumer of the component to
 * create the correct screen hierarchy.
 * 
 * For example:
 *  - `/` is the root of all paths. There should always be a screen with
 *    `path="/"`;
 *  - `/parent/child` is a child of `/parent`;
 *  - `/parent/child/grand-child` is a child of `/parent/child`;
 *  - `/parent/:param` is a child of `/parent` as well;
 *  - if the current screen has a `path="/parent/child/grand-child"`, when
 *    going "back" `Navigator` will try to recursively navigate the path
 *    hierarchy until a matching screen (or the root `/`) is found.
 */
path: string
Button 21 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/navigator/index.tsx
The `Navigator.Button` component can be used to navigate to a screen and should be used in combination with the `Navigator`, the `Navigator.Screen` and the `Navigator.BackButton` components.
example: ```jsx import { Navigator } from '@wordpress/components'; const MyNavigation = () => ( <Navigator initialPath="/"> <Navigator.Screen path="/"> <p>This is the home screen.</p> <Navigator.Button path="/child"> Navigate to child screen. </Navigator.Button> </Navigator.Screen> <Navigator.Screen path="/child"> <p>This is the child screen.</p> <Navigator.BackButton> Go back </Navigator.BackButton> </Navigator.Screen> </Navigator> ); ```
import { Navigator } from '@wordpress/components';
Component: ../packages/components/src/navigator/index.tsx::Navigator (react-component-meta)
/**
 * Start opting into the larger default height that will become the
 * default size in a future version.
 */
__next40pxDefaultSize?: boolean = false

/**
 * Whether to keep the button focusable when disabled.
 * 
 * In most cases, it is recommended to set this to `true`. Disabling a control without maintaining focusability
 * can cause accessibility issues, by hiding their presence from screen reader users,
 * or by preventing focus from returning to a trigger element.
 * 
 * Learn more about the [focusability of disabled controls](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#focusabilityofdisabledcontrols)
 * in the WAI-ARIA Authoring Practices Guide.
 */
accessibleWhenDisabled?: boolean = false

/**
 * The HTML element or React component to render the component as.
 */
as?: JSXElementConstructor<any> | keyof IntrinsicElements | undefined

/**
 * The HTML attribute used to identify the `NavigatorButton`, which is used
 * by `Navigator` to restore focus.
 */
attributeName?: string = 'id'

/**
 * The button's children.
 */
children?: ReactNode

/**
 * A visually hidden accessible description for the button.
 */
description?: string

/**
 * Whether the button is disabled. If `true`, this will force a `button` element
 * to be rendered, even when an `href` is given.
 * 
 * In most cases, it is recommended to also set the `accessibleWhenDisabled` prop to `true`.
 */
disabled?: boolean

/**
 * If provided, renders an Icon component inside the button.
 */
icon?: IconType | null | undefined

/**
 * If provided with `icon`, sets the position of icon relative to the `text`.
 */
iconPosition?: "left" | "right" = 'left'

/**
 * If provided with `icon`, sets the icon size.
 * Please refer to the Icon component for more details regarding
 * the default value of its `size` prop.
 */
iconSize?: number

/**
 * Indicates activity while a action is being performed.
 */
isBusy?: boolean

/**
 * Renders a red text-based button style to indicate destructive behavior.
 */
isDestructive?: boolean

/**
 * Renders a pressed button style.
 */
isPressed?: boolean

/**
 * Sets the `aria-label` of the component, if none is provided.
 * Sets the Tooltip content if `showTooltip` is provided.
 */
label?: string

/**
 * The path of the screen to navigate to. The value of this prop needs to be
 * a valid value for an HTML attribute.
 */
path: string

/**
 * If provided with `showTooltip`, appends the Shortcut label to the tooltip content.
 * If an object is provided, it should contain `display` and `ariaLabel` keys.
 */
shortcut?: string | { display: string; ariaLabel: string; } | undefined

/**
 * If provided, renders a Tooltip component for the button.
 */
showTooltip?: boolean

/**
 * 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.
 * 
 * If the deprecated `isSmall` prop is also defined, this prop will take precedence.
 */
size?: "small" | "default" | "compact" = 'default'

/**
 * If provided, displays the given text inside the button. If the button contains children elements, the text is displayed before them.
 */
text?: string

/**
 * If provided with `showTooltip`, sets the position of the tooltip.
 * Please refer to the Tooltip component for more details regarding the defaults.
 */
tooltipPosition?: "bottom" | "top" | "middle" | "bottom center" | "bottom left" | "bottom right" | "top center" | "top left" | "top right" | "middle center" | "middle left" | "middle right" | "bottom center left" | "bottom center right" | "bottom center bottom" | "bottom center top" | "bottom left left" | "bottom left right" | "bottom left bottom" | "bottom left top" | "bottom right left" | "bottom right right" | "bottom right bottom" | "bottom right top" | "top center left" | "top center right" | "top center bottom" | "top center top" | "top left left" | "top left right" | "top left bottom" | "top left top" | "top right left" | "top right right" | "top right bottom" | "top right top" | "middle center left" | "middle center right" | "middle center bottom" | "middle center top" | "middle left left" | "middle left right" | "middle left bottom" | "middle left top" | "middle right left" | "middle right right" | "middle right bottom" | "middle right top"

/**
 * Specifies the button's style.
 * 
 * The accepted values are:
 * 
 * 1. `'primary'` (the primary button styles)
 * 2. `'secondary'` (the default button styles)
 * 3. `'tertiary'` (the text-based button styles)
 * 4. `'link'` (the link button styles)
 */
variant?: "link" | "primary" | "secondary" | "tertiary"
BackButton 19 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/navigator/index.tsx
The `Navigator.BackButton` component can be used to navigate to a screen and should be used in combination with the `Navigator`, the `Navigator.Screen` and the `Navigator.Button` components.
example: ```jsx import { Navigator } from '@wordpress/components'; const MyNavigation = () => ( <Navigator initialPath="/"> <Navigator.Screen path="/"> <p>This is the home screen.</p> <Navigator.Button path="/child"> Navigate to child screen. </Navigator.Button> </Navigator.Screen> <Navigator.Screen path="/child"> <p>This is the child screen.</p> <Navigator.BackButton> Go back </Navigator.BackButton> </Navigator.Screen> </Navigator> ); ```
import { Navigator } from '@wordpress/components';
Component: ../packages/components/src/navigator/index.tsx::Navigator (react-component-meta)
/**
 * Start opting into the larger default height that will become the
 * default size in a future version.
 */
__next40pxDefaultSize?: boolean = false

/**
 * Whether to keep the button focusable when disabled.
 * 
 * In most cases, it is recommended to set this to `true`. Disabling a control without maintaining focusability
 * can cause accessibility issues, by hiding their presence from screen reader users,
 * or by preventing focus from returning to a trigger element.
 * 
 * Learn more about the [focusability of disabled controls](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#focusabilityofdisabledcontrols)
 * in the WAI-ARIA Authoring Practices Guide.
 */
accessibleWhenDisabled?: boolean = false

/**
 * The HTML element or React component to render the component as.
 */
as?: JSXElementConstructor<any> | keyof IntrinsicElements | undefined

/**
 * The button's children.
 */
children?: ReactNode

/**
 * A visually hidden accessible description for the button.
 */
description?: string

/**
 * Whether the button is disabled. If `true`, this will force a `button` element
 * to be rendered, even when an `href` is given.
 * 
 * In most cases, it is recommended to also set the `accessibleWhenDisabled` prop to `true`.
 */
disabled?: boolean

/**
 * If provided, renders an Icon component inside the button.
 */
icon?: IconType | null | undefined

/**
 * If provided with `icon`, sets the position of icon relative to the `text`.
 */
iconPosition?: "left" | "right" = 'left'

/**
 * If provided with `icon`, sets the icon size.
 * Please refer to the Icon component for more details regarding
 * the default value of its `size` prop.
 */
iconSize?: number

/**
 * Indicates activity while a action is being performed.
 */
isBusy?: boolean

/**
 * Renders a red text-based button style to indicate destructive behavior.
 */
isDestructive?: boolean

/**
 * Renders a pressed button style.
 */
isPressed?: boolean

/**
 * Sets the `aria-label` of the component, if none is provided.
 * Sets the Tooltip content if `showTooltip` is provided.
 */
label?: string

/**
 * If provided with `showTooltip`, appends the Shortcut label to the tooltip content.
 * If an object is provided, it should contain `display` and `ariaLabel` keys.
 */
shortcut?: string | { display: string; ariaLabel: string; } | undefined

/**
 * If provided, renders a Tooltip component for the button.
 */
showTooltip?: boolean

/**
 * 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.
 * 
 * If the deprecated `isSmall` prop is also defined, this prop will take precedence.
 */
size?: "small" | "default" | "compact" = 'default'

/**
 * If provided, displays the given text inside the button. If the button contains children elements, the text is displayed before them.
 */
text?: string

/**
 * If provided with `showTooltip`, sets the position of the tooltip.
 * Please refer to the Tooltip component for more details regarding the defaults.
 */
tooltipPosition?: "bottom" | "top" | "middle" | "bottom center" | "bottom left" | "bottom right" | "top center" | "top left" | "top right" | "middle center" | "middle left" | "middle right" | "bottom center left" | "bottom center right" | "bottom center bottom" | "bottom center top" | "bottom left left" | "bottom left right" | "bottom left bottom" | "bottom left top" | "bottom right left" | "bottom right right" | "bottom right bottom" | "bottom right top" | "top center left" | "top center right" | "top center bottom" | "top center top" | "top left left" | "top left right" | "top left bottom" | "top left top" | "top right left" | "top right right" | "top right bottom" | "top right top" | "middle center left" | "middle center right" | "middle center bottom" | "middle center top" | "middle left left" | "middle left right" | "middle left bottom" | "middle left top" | "middle right left" | "middle right right" | "middle right bottom" | "middle right top"

/**
 * Specifies the button's style.
 * 
 * The accepted values are:
 * 
 * 1. `'primary'` (the primary button styles)
 * 2. `'secondary'` (the default button styles)
 * 3. `'tertiary'` (the text-based button styles)
 * 4. `'link'` (the link button styles)
 */
variant?: "link" | "primary" | "secondary" | "tertiary"

Notice.Root

design-system-components-notice · ../packages/ui/src/notice/stories/index.story.tsx
A notice component that communicates system status and provides actions. It does not announce its content to assistive technology. Consumers are responsible for announcing dynamic updates, for example with `speak()` from `@wordpress/a11y`. ```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.CloseIconButton onClick={() => {}} /> </Notice.Root> ); } ```
Prop types (react-component-meta) 6 prop types
Component: ../packages/ui/src/notice/index.ts::Root
Props:
/**
 * The content to be rendered inside the notice.
 */
children?: ReactNode

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

/**
 * 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?: ReactElement<SVGProps<SVGSVGElement>, string | JSXElementConstructor<any>> | null | undefined

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

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Imports
import { ActionButton, ActionLink, Actions, CloseIconButton, Description, Root, Title } from '@wordpress/ui';
import * as Notice from '../index';
import { unseen, tip } from '@wordpress/icons';
Default story ok
const Default = () => <Notice.Root>{[
        <Notice.Title key="title">Notice Title</Notice.Title>,
        <Notice.Description key="description">
            Description text with details about this notification.
        </Notice.Description>,
        <Notice.Actions key="actions">
            <Notice.ActionButton>Primary button</Notice.ActionButton>
            <Notice.ActionButton variant="outline">
                Secondary button
            </Notice.ActionButton>
            <Notice.ActionLink href="#">Link</Notice.ActionLink>
        </Notice.Actions>,
        <Notice.CloseIconButton key="closeIconButton" />,
    ]}</Notice.Root>;
Info story ok
const Info = () => <Notice.Root intent="info">{[
        <Notice.Title key="title">Notice Title</Notice.Title>,
        <Notice.Description key="description">
            Description text with details about this notification.
        </Notice.Description>,
        <Notice.Actions key="actions">
            <Notice.ActionButton>Primary button</Notice.ActionButton>
            <Notice.ActionButton variant="outline">
                Secondary button
            </Notice.ActionButton>
            <Notice.ActionLink href="#">Link</Notice.ActionLink>
        </Notice.Actions>,
        <Notice.CloseIconButton key="closeIconButton" />,
    ]}</Notice.Root>;
Warning story ok
const Warning = () => <Notice.Root intent="warning">{[
        <Notice.Title key="title">Notice Title</Notice.Title>,
        <Notice.Description key="description">
            Description text with details about this notification.
        </Notice.Description>,
        <Notice.Actions key="actions">
            <Notice.ActionButton>Primary button</Notice.ActionButton>
            <Notice.ActionButton variant="outline">
                Secondary button
            </Notice.ActionButton>
            <Notice.ActionLink href="#">Link</Notice.ActionLink>
        </Notice.Actions>,
        <Notice.CloseIconButton key="closeIconButton" />,
    ]}</Notice.Root>;
Success story ok
const Success = () => <Notice.Root intent="success">{[
        <Notice.Title key="title">Notice Title</Notice.Title>,
        <Notice.Description key="description">
            Description text with details about this notification.
        </Notice.Description>,
        <Notice.Actions key="actions">
            <Notice.ActionButton>Primary button</Notice.ActionButton>
            <Notice.ActionButton variant="outline">
                Secondary button
            </Notice.ActionButton>
            <Notice.ActionLink href="#">Link</Notice.ActionLink>
        </Notice.Actions>,
        <Notice.CloseIconButton key="closeIconButton" />,
    ]}</Notice.Root>;
Error story ok
const Error = () => <Notice.Root intent="error">{[
        <Notice.Title key="title">Notice Title</Notice.Title>,
        <Notice.Description key="description">
            Description text with details about this notification.
        </Notice.Description>,
        <Notice.Actions key="actions">
            <Notice.ActionButton>Primary button</Notice.ActionButton>
            <Notice.ActionButton variant="outline">
                Secondary button
            </Notice.ActionButton>
            <Notice.ActionLink href="#">Link</Notice.ActionLink>
        </Notice.Actions>,
        <Notice.CloseIconButton key="closeIconButton" />,
    ]}</Notice.Root>;
Non Dismissible story ok
Omit Notice.CloseIconButton to make the notice non-dismissable.
const NonDismissible = () => <Notice.Root intent="warning">{[
        <Notice.Title key="title">Action Required</Notice.Title>,
        <Notice.Description key="description">
            This notice cannot be dismissed by the user.
        </Notice.Description>,
        <Notice.Actions key="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 key="title">No Icon</Notice.Title>,
        <Notice.Description key="description">
            This notice has no decorative icon displayed.
        </Notice.Description>,
        <Notice.CloseIconButton key="closeIconButton" />,
    ]}</Notice.Root>;
Without Actions story ok
const WithoutActions = () => <Notice.Root intent="info">{[
        <Notice.Title key="title">Simple Notice</Notice.Title>,
        <Notice.Description key="description">
            A dismissable notice without any action buttons or links.
        </Notice.Description>,
        <Notice.CloseIconButton key="closeIconButton" />,
    ]}</Notice.Root>;
Title Only story ok
Title only, no description or actions.
const TitleOnly = () => <Notice.Root>{[
        <Notice.Title key="title">Just a title</Notice.Title>,
        <Notice.CloseIconButton key="closeIconButton" />,
    ]}</Notice.Root>;
Description Only story ok
Description only, no title or actions.
const DescriptionOnly = () => <Notice.Root intent="info">{[
        <Notice.Description key="description">
            Just a description without title or actions.
        </Notice.Description>,
        <Notice.CloseIconButton key="closeIconButton" />,
    ]}</Notice.Root>;
Custom Icon story ok
Pass a custom icon via the `icon` prop to override the default intent icon.
const CustomIcon = () => <Notice.Root intent="info" icon={unseen}>{[
        <Notice.Description key="description">
            Parent block is hidden on Desktop
        </Notice.Description>,
    ]}</Notice.Root>;
Tip story ok
Use an info notice with the tip icon for contextual guidance.
const Tip = () => <Notice.Root intent="info" icon={tip}>{[
        <Notice.Description key="description">
            While writing, you can press <kbd>/</kbd> to quickly insert new
            blocks.
        </Notice.Description>,
    ]}</Notice.Root>;
Notice.Title 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/notice/index.ts
A short heading that communicates the main message of the notice.
import { Title } from '@wordpress/ui';
Component: ../packages/ui/src/notice/index.ts::Title (react-component-meta)
/**
 * The title text of the notice.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Notice.Description 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/notice/index.ts
The description text for a notice.
import { Description } from '@wordpress/ui';
Component: ../packages/ui/src/notice/index.ts::Description (react-component-meta)
/**
 * The description text of the notice.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Notice.Actions 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/notice/index.ts
A container for Notice.ActionButton and Notice.ActionLink.
import { Actions } from '@wordpress/ui';
Component: ../packages/ui/src/notice/index.ts::Actions (react-component-meta)
/**
 * The action buttons for the notice.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Notice.CloseIconButton 11 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/notice/index.ts
The close button for a notice. Renders an icon button with a close icon.
import { CloseIconButton } from '@wordpress/ui';
Component: ../packages/ui/src/notice/index.ts::CloseIconButton (react-component-meta)
/**
 * Indicates the current "pressed" state of toggle buttons. This should only
 * be used with neutral minimal buttons.
 */
aria-pressed?: boolean | "true" | "false" | "mixed" | undefined

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

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

/**
 * Whether the element should be focusable even when it is disabled.
 */
focusableWhenDisabled?: boolean = true

/**
 * The icon to display in the button.
 */
icon?: ReactElement<SVGProps<SVGSVGElement>, string | JSXElementConstructor<any>> = closeSmall

/**
 * A label describing the button's action, shown as a tooltip and to
 * assistive technology.
 */
label?: string = __( 'Dismiss' )

/**
 * Whether the component renders a native `<button>` element when replacing it
 * via the `render` prop.
 * Set to `false` if the rendered element is not a button (for example, `<div>`).
 */
nativeButton?: boolean = true

/**
 * Customize how the tooltip is positioned relative to the button. Accepts
 * a `<Tooltip.Positioner />` element with custom positioning props
 * (`side`, `align`, `sideOffset`, collision settings, etc.). When omitted,
 * the tooltip uses the default placement.
 */
positioner?: ReactElement<Omit<PositionerProps, "children">, string | JSXElementConstructor<any>>

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * 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 registering the keyboard shortcut and keeping
 * its handler synchronized with the button's disabled state.
 */
shortcut?: KeyboardShortcut

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Notice.ActionButton 11 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/notice/index.ts
An action button for use within Notice.Actions.
import { ActionButton } from '@wordpress/ui';
Component: ../packages/ui/src/notice/index.ts::ActionButton (react-component-meta)
/**
 * Indicates the current "pressed" state of toggle buttons. This should only
 * be used with neutral minimal buttons.
 */
aria-pressed?: boolean | "true" | "false" | "mixed" | undefined

/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

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

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

/**
 * Whether the element should be focusable even when it is disabled.
 */
focusableWhenDisabled?: boolean = true

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

/**
 * The text used for assistive technology to indicate the loading state.
 */
loadingAnnouncement?: string

/**
 * Whether the component renders a native `<button>` element when replacing it
 * via the `render` prop.
 * Set to `false` if the rendered element is not a button (for example, `<div>`).
 */
nativeButton?: boolean = true

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The variant of the button. Variants describe the visual style treatment
 * of the button.
 */
variant?: "outline" | "minimal" | "unstyled" | "solid" = "solid"
Notice.ActionLink 6 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/notice/index.ts
An action link for use within Notice.Actions.
import { ActionLink } from '@wordpress/ui';
Component: ../packages/ui/src/notice/index.ts::ActionLink (react-component-meta)
/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

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

/**
 * Adds a visual indicator and accessible notice for opening in a new tab.
 * Defaults `target` to `"_blank"` when no explicit target is set.
 */
openInNewTab?: boolean = false

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * Where to open the linked document. `"_blank"` also adds the visual
 * indicator and accessible new-tab notice.
 * 
 * When both `target` and `openInNewTab` are set, `target` determines the
 * browsing context.
 */
target?: HTMLAttributeAnchorTarget | undefined

Popover

components-popover · ../packages/components/src/popover/stories/index.story.tsx
`Popover` renders its content in a floating modal. If no explicit anchor is passed via props, it anchors to its parent element by default. ```jsx import { Button, Popover } from '@wordpress/components'; import { useState } from '@wordpress/element'; const MyPopover = () => { const [ isVisible, setIsVisible ] = useState( false ); const toggleVisible = () => { setIsVisible( ( state ) => ! state ); }; return ( <Button variant="secondary" onClick={ toggleVisible }> Toggle Popover! { isVisible && <Popover>Popover is toggled!</Popover> } </Button> ); }; ```
Prop types (react-component-meta) 24 prop types
Component: ../packages/components/src/popover/index.tsx::Popover
Props:
/**
 * Prevent the popover from flipping and resizing when meeting the viewport
 * edges. _Note: this prop is deprecated. Instead, provide use the individual
 * `flip` and `resize` props._
 */
__unstableForcePosition?: boolean

/**
 * The name of the Slot in which the popover should be rendered. It should
 * be also passed to the corresponding `PopoverSlot` component.
 */
__unstableSlotName?: string = 'Popover'

/**
 * The element that should be used by the popover as its anchor. It can either
 * be an `Element` or, alternatively, a `VirtualElement` — ie. an object with
 * the `getBoundingClientRect()` and the `ownerDocument` properties defined.
 * 
 * **The anchor element should be stored in local state** rather than a
 * plain React ref to ensure reactive updating when it changes.
 */
anchor?: Element | VirtualElement | null | undefined

/**
 * An object extending a `DOMRect` with an additional optional `ownerDocument`
 * property, used to specify a fixed popover position.
 */
anchorRect?: DomRectWithOwnerDocument

/**
 * Used to specify a fixed popover position. It can be an `Element`, a React
 * reference to an `element`, an object with a `top` and a `bottom` properties
 * (both pointing to elements), or a `range`.
 */
anchorRef?: Element | PopoverAnchorRefReference | PopoverAnchorRefTopBottom | Range | undefined

/**
 * Whether the popover should animate when opening.
 */
animate?: boolean = true

/**
 * The `children` elements rendered as the popover's content.
 */
children: ReactNode

/**
 * Determines whether tabbing is constrained to within the popover,
 * preventing keyboard focus from leaving the popover content without
 * explicit focus elsewhere, or whether the popover remains part of the wider
 * tab order. If no value is passed, it will be derived from `focusOnMount`.
 */
constrainTabbing?: boolean = `focusOnMount` !== false

/**
 * Show the popover fullscreen on mobile viewports.
 */
expandOnMobile?: boolean

/**
 * Specifies whether the popover should flip across its axis if there isn't
 * space for it in the normal placement.
 * When the using a 'top' placement, the popover will switch to a 'bottom'
 * placement. When using a 'left' placement, the popover will switch to a
 * `right' placement.
 * The popover will retain its alignment of 'start' or 'end' when flipping.
 */
flip?: boolean = true

/**
 * Determines focus behavior when the popover 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_.
 */
focusOnMount?: Mode | undefined = 'firstElement'

/**
 * A function returning the same value as the one expected by the `anchorRect`
 * prop, used to specify a dynamic popover position.
 */
getAnchorRect?: (fallbackReferenceElement: Element | null) => DomRectWithOwnerDocument

/**
 * Used to customize the header text shown when the popover is toggled to
 * fullscreen on mobile viewports (see the `expandOnMobile` prop).
 */
headerTitle?: string

/**
 * Whether to render the popover inline or within the slot.
 */
inline?: boolean = false

/**
 * Used to enable a different visual style for the popover.
 * _Note: this prop is deprecated. Use the `variant` prop with the
 * 'toolbar' value instead._
 */
isAlternate?: boolean

/**
 * Used to show/hide the arrow that points at the popover's anchor.
 */
noArrow?: boolean = true

/**
 * The distance (in px) between the anchor and the popover. Pass an object to
 * also displace the popover along its cross axis.
 */
offset?: number | { mainAxis?: number | undefined; crossAxis?: number | undefined; } | undefined = 0

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

/**
 * A callback invoked when the focus leaves the opened popover. This should
 * only be provided in advanced use-cases when a popover should close under
 * specific circumstances (for example, if the new `document.activeElement`
 * is content of or otherwise controlling popover visibility).
 * 
 * When not provided, the `onClose` callback will be called instead.
 */
onFocusOutside?: (event: SyntheticEvent<Element, Event>) => void

/**
 * Used to specify the popover's position with respect to its anchor.
 */
placement?: "left" | "right" | "bottom" | "overlay" | "top" | "left-end" | "left-start" | "right-end" | "right-start" | "bottom-end" | "bottom-start" | "top-end" | "top-start" = 'bottom-start'

/**
 * Legacy way to specify the popover's position with respect to its anchor.
 * _Note: this prop is deprecated. Use the `placement` prop instead._
 */
position?: "bottom" | "top" | "middle" | "bottom center" | "bottom left" | "bottom right" | "top center" | "top left" | "top right" | "middle center" | "middle left" | "middle right" | "bottom center left" | "bottom center right" | "bottom center bottom" | "bottom center top" | "bottom left left" | "bottom left right" | "bottom left bottom" | "bottom left top" | "bottom right left" | "bottom right right" | "bottom right bottom" | "bottom right top" | "top center left" | "top center right" | "top center bottom" | "top center top" | "top left left" | "top left right" | "top left bottom" | "top left top" | "top right left" | "top right right" | "top right bottom" | "top right top" | "middle center left" | "middle center right" | "middle center bottom" | "middle center top" | "middle left left" | "middle left right" | "middle left bottom" | "middle left top" | "middle right left" | "middle right right" | "middle right bottom" | "middle right top"

/**
 * Adjusts the size of the popover to prevent its contents from going out of
 * view when meeting the viewport edges.
 * _Note: The `resize` and `shift` props are not intended to be used together.
 * Enabling both can cause unexpected behavior._
 */
resize?: boolean = true

/**
 * Enables the `Popover` to shift in order to stay in view when meeting the
 * viewport edges.
 * _Note: The `resize` and `shift` props are not intended to be used together.
 * Enabling both can cause unexpected behavior._
 */
shift?: boolean = false

/**
 * Specifies the popover's style.
 * 
 * Leave undefined for the default style. Other values are:
 * - 'unstyled':  The popover is essentially without any visible style, it
 *                has no background, border, outline or drop shadow, but
 *                the popover contents are still displayed.
 * - 'toolbar':   A style that has no elevation, but a high contrast with
 *                other elements. This is matches the style of the
 *                `Toolbar` component.
 */
variant?: "toolbar" | "unstyled" = undefined
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">(<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>;
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 animate={false}>(<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><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></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>
    );
};
Popover.Slot 3 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/popover/index.tsx
Renders a slot that is used internally by Popover for rendering content.
import { Popover } from '@wordpress/components';
Component: ../packages/components/src/popover/index.tsx::Popover (react-component-meta)
key?: Key | null | undefined

/**
 * The name of the Slot in which the popover should be rendered. It should
 * be also passed to the corresponding `PopoverSlot` component.
 */
name?: string = 'Popover'

/**
 * Allows getting a ref to the component instance.
 * Once the component unmounts, React will set `ref.current` to `null`
 * (or call the ref with `null` if you passed a callback ref).
 */
ref?: Ref<HTMLDivElement> | undefined

Progress.Root

design-system-components-progress · ../packages/ui/src/progress/stories/index.story.tsx
Groups the progress bar, label, and value for a task. Pass `null` as the value for indeterminate progress. Use `Progress.Label`, `aria-label`, or `aria-labelledby` to name the task.
Prop types (react-component-meta) 11 prop types
Component: ../packages/ui/src/progress/index.ts::Root
Props:
/**
 * A string value that provides a user-friendly name for `aria-valuenow`, the current value of the progress bar.
 */
aria-valuetext?: string

/**
 * The parts of the progress indicator, including its label and value.
 */
children?: ReactNode

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

/**
 * Options to format the value.
 */
format?: NumberFormatOptions

/**
 * Accepts a function which returns a string value that provides a human-readable text alternative for the current value of the progress bar.
 */
getAriaValueText?: (formattedValue: string, value: number | null) => string

/**
 * The locale used by `Intl.NumberFormat` when formatting the value.
 * Defaults to the user's runtime locale.
 */
locale?: LocalesArgument

/**
 * The maximum value.
 */
max?: number = 100

/**
 * The minimum value.
 */
min?: number = 0

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined = ( props: React.ComponentProps< typeof Stack > ) => (
	<Stack { ...props } direction="column" gap="sm" />
)

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The current value. The component is indeterminate when value is `null`.
 */
value: number | null
Imports
import { Indicator, Label, Root, Track, Value, Stack, Text } from '@wordpress/ui';
Default story ok
const Default = () => <Progress.Root value={60}>
    <Stack justify="space-between" gap="sm">
        <Progress.Label>Uploading files</Progress.Label>
        <Progress.Value />
    </Stack>
    <Progress.Track>
        <Progress.Indicator color={ color } />
    </Progress.Track>
</Progress.Root>;
Indeterminate story ok
Pass null when the amount of completed work is unknown.
const Indeterminate = () => <Progress.Root value={null}>
    <Stack justify="space-between" gap="sm">
        <Progress.Label>Uploading files</Progress.Label>
        <Progress.Value />
    </Stack>
    <Progress.Track>
        <Progress.Indicator color={ color } />
    </Progress.Track>
</Progress.Root>;
Bar Only story ok
A visible label is optional when the task has an accessible name.
const BarOnly = () => <Progress.Root value={60} aria-label="Uploading files">
    <Progress.Track>
        <Progress.Indicator color={ color } />
    </Progress.Track>
</Progress.Root>;
Custom Color story ok
The color prop changes the indicator, leaving the other parts unchanged.
const CustomColor = () => <Progress.Root value={60} color="#e85d04">
    <Stack justify="space-between" gap="sm">
        <Progress.Label>Uploading files</Progress.Label>
        <Progress.Value />
    </Stack>
    <Progress.Track>
        <Progress.Indicator color={ color } />
    </Progress.Track>
</Progress.Root>;
Current Color story ok
const CurrentColor = () => <Progress.Root value={60} color="currentColor">
    <Stack justify="space-between" gap="sm">
        <Progress.Label>Uploading files</Progress.Label>
        <Progress.Value />
    </Stack>
    <Progress.Track>
        <Progress.Indicator color={ color } />
    </Progress.Track>
</Progress.Root>;
Custom Value Format story ok
Use the same task-specific units for visible and accessible value text.
const CustomValueFormat = () => <Progress.Root
    value={3}
    max={10}
    format={{ style: 'decimal' }}
    getAriaValueText={( formattedValue ) =>
        `${ formattedValue } of 10 images uploaded`}>
    <Progress.Label>Uploading images</Progress.Label>
    <Progress.Track>
        <Progress.Indicator color={ color } />
    </Progress.Track>
    <Progress.Value>
        { ( formattedValue, value ) =>
            value === null
                ? 'Preparing images'
                : `${ formattedValue } of 10 images uploaded`
        }
    </Progress.Value>
</Progress.Root>;
Progress.Track 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/progress/index.ts
The neutral track containing the filled progress indicator.
import { Track } from '@wordpress/ui';
Component: ../packages/ui/src/progress/index.ts::Track (react-component-meta)
/**
 * The progress indicator to render inside the track.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Progress.Indicator 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/progress/index.ts
The filled portion of the track, or an animation for indeterminate progress.
import { Indicator } from '@wordpress/ui';
Component: ../packages/ui/src/progress/index.ts::Indicator (react-component-meta)
/**
 * CSS class name to apply to the element.
 */
className?: string

/**
 * The filled indicator color. Accepts any CSS color value,
 * including `currentColor` to inherit the surrounding text color.
 * The track, label, and value keep their own colors.
 */
color?: string

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Progress.Label 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/progress/index.ts
The visible label, automatically used as the progress bar's accessible name.
import { Label } from '@wordpress/ui';
Component: ../packages/ui/src/progress/index.ts::Label (react-component-meta)
/**
 * The visible, accessible name of the task.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined = <Text />

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Progress.Value 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/progress/index.ts
Displays the formatted progress value. Use a child function to customize it.
import { Value } from '@wordpress/ui';
Component: ../packages/ui/src/progress/index.ts::Value (react-component-meta)
/**
 * A function that receives the formatted and numeric progress values and
 * returns the content to display. The numeric value is null for indeterminate progress.
 */
children?: ((formattedValue: string | null, value: number | null) => ReactNode) | null | undefined

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined = <Text />

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

Radio

design-system-components-form-primitives-radio · ../packages/ui/src/form/primitives/radio/stories/index.story.tsx
A low-level radio button primitive. Prefer `RadioGroupControl` for standard labeled radio groups. Must be rendered inside a `RadioGroup`.
Prop types (react-component-meta) 9 prop types
Component: ../packages/ui/src/form/primitives/radio/index.ts::Radio
Props:
/**
 * CSS class name to apply to the element.
 */
className?: string

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

/**
 * A ref to access the hidden input element.
 */
inputRef?: Ref<HTMLInputElement> | undefined

/**
 * Whether the component renders a native `<button>` element when replacing it
 * via the `render` prop.
 * Set to `true` if the rendered element is a native button.
 */
nativeButton?: boolean = false

/**
 * Whether the user should be unable to select the radio button.
 */
readOnly?: boolean

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * Whether the user must choose a value before submitting a form.
 */
required?: boolean

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The unique identifying value of the radio in a group.
 */
value: unknown
Imports
import { Radio, RadioGroup } from '@wordpress/ui';
Default story ok
const Default = () => <RadioGroup aria-label="Options">
    <Radio value="option" aria-label="Option" />
</RadioGroup>;
Checked story ok
const Checked = () => <RadioGroup aria-label="Options" defaultValue="option">
    <Radio value="option" aria-label="Option" />
</RadioGroup>;
Disabled story ok
const Disabled = () => <RadioGroup aria-label="Options">
    <Radio value="option" aria-label="Option" disabled />
</RadioGroup>;
Disabled Checked story ok
const DisabledChecked = () => <RadioGroup aria-label="Options" defaultValue="option">
    <Radio value="option" aria-label="Option" disabled />
</RadioGroup>;

RadioGroup

design-system-components-form-primitives-radiogroup · ../packages/ui/src/form/primitives/radio-group/stories/index.story.tsx
A low-level primitive that groups radio buttons so they share one selected value. Prefer `RadioGroupControl` for standard labeled radio groups. Must wrap `Radio` items. For one labeled group, pass `RadioGroup` to `Fieldset.Root`'s `render` prop. When a `Fieldset` contains multiple groups, give each `RadioGroup` its own accessible name.
Prop types (react-component-meta) 13 prop types
Component: ../packages/ui/src/form/primitives/radio-group/index.ts::RadioGroup
Props:
/**
 * The radio items and their associated content.
 */
children?: ReactNode

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

/**
 * The uncontrolled value of the radio button that should be initially selected.
 * 
 * To render a controlled radio group, use the `value` prop instead.
 */
defaultValue?: unknown

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

/**
 * Identifies the form that owns the radio inputs.
 * Useful when the radio group is rendered outside the form.
 */
form?: string

/**
 * A ref to access the hidden input element.
 */
inputRef?: Ref<HTMLInputElement> | undefined

/**
 * Identifies the field when a form is submitted.
 */
name?: string

/**
 * Callback fired when the value changes.
 */
onValueChange?: (value: unknown, eventDetails: { reason: "none"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void

/**
 * Whether the user should be unable to select a different radio button in the group.
 */
readOnly?: boolean = false

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined = ( props: React.ComponentProps< typeof Stack > ) => (
	<Stack { ...props } direction="column" gap="sm" />
)

/**
 * Whether the user must choose a value before submitting a form.
 */
required?: boolean = false

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The controlled value of the radio item that should be currently selected.
 * 
 * To render an uncontrolled radio group, use the `defaultValue` prop instead.
 */
value?: unknown
Imports
import { Radio, RadioGroup } from '@wordpress/ui';
Default story ok
const Default = () => <RadioGroup aria-label="Fruit">
    { [ 'Apple', 'Banana', 'Orange' ].map( ( label ) => (
        <Radio key={ label } value={ label } aria-label={ label } />
    ) ) }
</RadioGroup>;
Checked story ok
const Checked = () => <RadioGroup aria-label="Fruit" defaultValue="Apple">
    { [ 'Apple', 'Banana', 'Orange' ].map( ( label ) => (
        <Radio key={ label } value={ label } aria-label={ label } />
    ) ) }
</RadioGroup>;
Disabled story ok
const Disabled = () => <RadioGroup aria-label="Fruit" defaultValue="Apple" disabled>
    { [ 'Apple', 'Banana', 'Orange' ].map( ( label ) => (
        <Radio key={ label } value={ label } aria-label={ label } />
    ) ) }
</RadioGroup>;

RadioGroupControl

design-system-components-form-radiogroupcontrol · ../packages/ui/src/form/radio-group-control/stories/index.story.tsx
A complete radio group with a legend, optional description, and labeled items.
Prop types (react-component-meta) 17 prop types
Component: ../packages/ui/src/form/radio-group-control/index.ts::RadioGroupControl
Props:
/**
 * CSS class name to apply to the element.
 */
className?: string

/**
 * The uncontrolled value of the radio button that should be initially selected.
 * 
 * To render a controlled radio group, use the `value` prop instead.
 */
defaultValue?: string

/**
 * The accessible description, associated using `aria-describedby`.
 * 
 * For screen reader accessibility, this should only contain plain text,
 * and no semantics such as links.
 */
description?: string

/**
 * 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?: ReactNode

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

/**
 * Identifies the form that owns the radio inputs.
 * Useful when the radio group is rendered outside the form.
 */
form?: string

/**
 * Whether to visually hide the label while keeping it accessible
 * to screen readers.
 */
hideLabelFromVision?: boolean = false

/**
 * A ref to access the hidden input element.
 */
inputRef?: Ref<HTMLInputElement> | undefined

/**
 * The radio options to render.
 */
items: { label: string; value: string; description?: string | undefined; disabled?: boolean | undefined; }[]

/**
 * The accessible label. All controls must be labeled.
 */
label: string

/**
 * Identifies the field when a form is submitted.
 */
name?: string

/**
 * Callback fired when the value changes.
 */
onValueChange?: (value: string, eventDetails: { reason: "none"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void

/**
 * Whether the user should be unable to select a different radio button in the group.
 */
readOnly?: boolean = false

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * Whether the user must choose a value before submitting a form.
 */
required?: boolean = false

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The controlled value of the radio item that should be currently selected.
 * 
 * To render an uncontrolled radio group, use the `defaultValue` prop instead.
 */
value?: string
Imports
import { RadioGroupControl } from '@wordpress/ui';
import { DETAILS_EXAMPLE } from '../../stories/shared';
Default story ok
const Default = () => <RadioGroupControl
    label="Label"
    items={[
        {
            label: 'Apple',
            value: 'apple',
            description: 'This is the description for the apple.',
        },
        {
            label: 'Banana',
            value: 'banana',
            description: 'This is the description for the banana.',
        },
    ]} />;
With Description story ok
const WithDescription = () => <RadioGroupControl
    label="Label"
    items={[
        {
            label: 'Apple',
            value: 'apple',
            description: 'This is the description for the apple.',
        },
        {
            label: 'Banana',
            value: 'banana',
            description: 'This is the description for the banana.',
        },
    ]}
    description="This is the description for the entire fieldset." />;
With Long Label story ok
const WithLongLabel = () => <RadioGroupControl
    label="Label"
    items={[
        {
            label: 'This is a long label that should wrap to the next line. This is a long label that should wrap to the next line. This is a long label that should wrap to the next line.',
            value: 'apple',
        },
        {
            label: 'Banana',
            value: 'banana',
        },
    ]} />;
Visually Hidden Label story ok
const VisuallyHiddenLabel = () => <RadioGroupControl
    label="Label"
    items={[
        {
            label: 'Apple',
            value: 'apple',
            description: 'This is the description for the apple.',
        },
        {
            label: 'Banana',
            value: 'banana',
            description: 'This is the description for the banana.',
        },
    ]}
    hideLabelFromVision />;
With Details story ok
const WithDetails = () => <RadioGroupControl
    label="Label"
    items={[
        {
            label: 'Apple',
            value: 'apple',
            description: 'This is the description for the apple.',
        },
        {
            label: 'Banana',
            value: 'banana',
            description: 'This is the description for the banana.',
        },
    ]}
    details={DETAILS_EXAMPLE} />;
With Disabled Item story ok
const WithDisabledItem = () => <RadioGroupControl
    label="Label"
    items={[
        {
            label: 'Apple',
            value: 'apple',
        },
        {
            label: 'Banana',
            value: 'banana',
            description: 'This item is disabled.',
            disabled: true,
        },
        {
            label: 'Orange',
            value: 'orange',
        },
    ]} />;
Disabled story ok
const Disabled = () => <RadioGroupControl
    label="Label"
    items={[
        {
            label: 'Apple',
            value: 'apple',
            description: 'This is the description for the apple.',
        },
        {
            label: 'Banana',
            value: 'banana',
            description: 'This is the description for the banana.',
        },
    ]}
    disabled />;

RangeCalendar

design-system-components-calendar-rangecalendar · ../packages/ui/src/calendar/stories/range-calendar.story.tsx
`RangeCalendar` 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 (react-component-meta) 27 prop types
Component: ../packages/ui/src/calendar/index.ts::RangeCalendar
Props:
/**
 * Focus the first selected day (if set) or today's date (if not disabled).
 * 
 * Use this prop when the calendar should receive initial focus as it opens,
 * such as in a calendar popover. Do not use it to move focus after updates
 * to an open calendar.
 */
autoFocus?: boolean

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

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

/**
 * The initially selected range (uncontrolled).
 */
defaultValue?: DateRange

/**
 * 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.
 */
fixedWeeks?: boolean = false

/**
 * Use custom labels, useful for translating the component.
 * 
 * For a correct localized experience, consumers should make sure the locale
 * used for translated labels and date text is consistent.
 */
labels?: { labelNav?: (() => string) | undefined; labelGrid?: ((date: Date) => string) | undefined; labelGridcell?: ((date: Date, modifiers?: Modifiers | undefined) => string) | undefined; labelNext?: ((month: Date | undefined) => string) | undefined; labelPrevious?: ((month: Date | undefined) => string) | undefined; labelDa...

/**
 * A BCP 47 locale code or date-fns locale object used to localize date text,
 * numerals, the default text direction, and the first day of the week.
 * 
 * The locale code derives the first day of the week when the browser provides
 * that information, whether passed directly or through a date-fns locale
 * object. Use `weekStartsOn` to override this default.
 * 
 * Invalid or unsupported locale codes fall back to `en-US` for date text.
 * A date-fns locale object with an unsupported code retains its own first-day
 * setting.
 * 
 * For a correct localized experience, consumers should make sure the locale
 * used for translated labels and date text is consistent.
 * 
 * The calendar always uses a Gregorian date grid. The locale does not change
 * the underlying calendar system.
 */
locale?: string | Locale | undefined = The `enUS` locale from `date-fns/locale`

/**
 * 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.
 */
numberOfMonths?: number = 1

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

/**
 * Event handler called when the selected range changes.
 */
onValueChange?: OnValueChangeHandler<DateRange | null>

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

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

/**
 * When `true`, clicking a day starts a new range if there is no current start
 * date or if a range is already complete. In those cases, the clicked day
 * becomes the start of the new range. When `required` is `false`, clicking
 * the same day of a single-day range clears the selection.
 */
resetOnSelect?: boolean = true

/**
 * The ARIA role for the calendar's root element.
 * 
 * The default `application` role helps assistive technologies pass calendar
 * navigation keys to the component. Its accessible name includes the current
 * month.
 * 
 * Changing this role can affect screen-reader keyboard navigation. Only
 * override it for a tested composition. Apply roles that require additional
 * behavior, such as `dialog`, to a wrapper.
 */
role?: AriaRole | undefined = 'application'

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

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

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * 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 from the
 * [`@date-fns/tz`](https://www.npmjs.com/package/@date-fns/tz) package
 * instead of the native `Date` object.
 */
timeZone?: string

/**
 * The selected range (controlled). Use `null` when there is no selection.
 * To render an uncontrolled calendar, use `defaultValue` instead.
 */
value?: DateRange | null | undefined

/**
 * The index of the first day of the week (0 - Sunday). Overrides the locale's
 * one.
 */
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 = Based on the `locale` prop when available
Imports
import { RangeCalendar } from '@wordpress/ui';
import { fn } from 'storybook/test';
import { DISABLED_DATES_SAMPLE, firstDayOfNextMonth, fourthDayOfNextMonth } from './shared';
Default story ok
const Default = () => <RangeCalendar onMonthChange={fn()} onValueChange={fn()} endMonth={ toDate( endMonth ) } />;
Disabled Dates story ok
const DisabledDates = () => <RangeCalendar
    onMonthChange={fn()}
    onValueChange={fn()}
    disabled={DISABLED_DATES_SAMPLE}
    endMonth={ toDate( endMonth ) } />;
With Selected Range And Month story ok
const WithSelectedRangeAndMonth = () => <RangeCalendar
    onMonthChange={fn()}
    onValueChange={fn()}
    defaultValue={{
        from: firstDayOfNextMonth,
        to: fourthDayOfNextMonth,
    }}
    defaultMonth={firstDayOfNextMonth}
    endMonth={ toDate( endMonth ) } />;
With Range Constraints story ok
Use `min` and `max` to constrain the number of nights the range may span, and `excludeDisabled` to reset the range when it would include a disabled day.
const WithRangeConstraints = () => <RangeCalendar
    onMonthChange={fn()}
    onValueChange={fn()}
    min={2}
    max={7}
    excludeDisabled
    disabled={{ dayOfWeek: [ 0, 6 ] }}
    endMonth={ toDate( endMonth ) } />;
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 = () => <RangeCalendar
    onMonthChange={fn()}
    onValueChange={fn()}
    showOutsideDays
    fixedWeeks
    endMonth={ toDate( endMonth ) } />;
With Time Zone story ok
When working with time zones, use the `TZDate` object from the [`@date-fns/tz`](https://www.npmjs.com/package/@date-fns/tz) package instead of the native `Date` object.
const WithTimeZone = ({ endMonth, ...args }) => {
    const [ range, setRange ] = useState< typeof args.value >( 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 (
        <>
            <RangeCalendar
                onMonthChange={fn()}
                timeZone="Pacific/Auckland"
                endMonth={ toDate( endMonth ) }
                value={ range }
                onValueChange={ ( selectedDate, ...rest ) => {
                    setRange(
                        // Set controlled state to null if there's no selection
                        ! selectedDate ||
                            ( selectedDate.from === undefined &&
                                selectedDate.to === undefined )
                            ? null
                            : selectedDate
                    );
                    args.onValueChange?.( 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>
        </>
    );
};

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 help="Please select how transparent you would like this." initialPosition={ 50 } label="Opacity" max={ 100 } min={ 0 } value={ value } onChange={ setValue } /> ); }; ```
Prop types (react-component-meta) 32 prop types
Component: ../packages/components/src/range-control/index.tsx::default
Props:
__next40pxDefaultSize?: boolean

/**
 * Start opting into the new margin-free styles that will become the default in a future version.
 */
__nextHasNoMarginBottom?: boolean

/**
 * If this property is added, an Icon component will be rendered
 * after the slider with the icon equal to afterIcon.
 * 
 * For more information on `IconType` see the Icon component:
 * /packages/components/src/icon/index.tsx
 */
afterIcon?: IconType | undefined

/**
 * If this property is true, a button to reset the slider is
 * rendered.
 */
allowReset?: boolean = false

/**
 * If this property is added, an Icon component will be rendered
 * before the slider with the icon equal to beforeIcon.
 * 
 * For more information on `IconType` see the Icon component:
 * /packages/components/src/icon/index.tsx
 */
beforeIcon?: IconType | undefined

/**
 * CSS color string for the `RangeControl` wrapper.
 */
color?: Color | undefined = `var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9))`

/**
 * The current input to use as a fallback if `value` is currently
 * `undefined`.
 */
currentInput?: number

/**
 * Disables the `input`, preventing new values from being applied.
 */
disabled?: boolean = false

/**
 * Additional description for the control.
 * 
 * Only use for meaningful description or instructions for the control. An element containing the description will be programmatically associated to the BaseControl by the means of an `aria-describedby` attribute.
 */
help?: ReactNode

/**
 * If true, the label will only be visible to screen readers.
 */
hideLabelFromVision?: boolean = false

/**
 * The slider starting position, used when no `value` is passed.
 * The `initialPosition` will be clamped between the provided `min`
 * and `max` prop values.
 */
initialPosition?: number

/**
 * Passed as a prop to the `NumberControl` component and is only
 * applicable if `withInputField` is true. If true, while the number
 * input has focus, pressing `UP` or `DOWN` along with the `SHIFT` key
 * will change the value by the `shiftStep` value.
 */
isShiftStepEnabled?: boolean = true

/**
 * If this property is added, a label will be generated using label
 * property as the content.
 */
label?: string

/**
 * Renders a visual representation of `step` ticks. Custom mark indicators
 * can be provided by an `Array`.
 */
marks?: boolean | { value: number; label?: string | undefined; }[] | undefined = false

/**
 * The maximum `value` allowed.
 */
max?: number = 100

/**
 * The minimum `value` allowed.
 */
min?: number = 0

/**
 * Callback for when `RangeControl` input loses focus.
 */
onBlur?: FocusEventHandler<HTMLInputElement> = () => {}

/**
 * A function that receives the new value. The value will be less than
 * `max` and more than `min` unless a reset (enabled by `allowReset`)
 * has occurred. In which case the value will be either that of
 * `resetFallbackValue` if it has been specified or otherwise
 * `undefined`.
 */
onChange?: (value: number | undefined) => void = () => {}

/**
 * Callback for when `RangeControl` input gains focus.
 */
onFocus?: FocusEventHandler<HTMLInputElement> = () => {}

/**
 * Callback for when mouse exits the `RangeControl`.
 */
onMouseLeave?: MouseEventHandler<HTMLInputElement> = () => {}

/**
 * Callback for when mouse moves within the `RangeControl`.
 */
onMouseMove?: MouseEventHandler<HTMLInputElement> = () => {}

/**
 * CSS color string to customize the rail element's background.
 */
railColor?: Color | undefined

/**
 * A way to customize the rendered UI of the value.
 */
renderTooltipContent?: (value?: ControlledRangeValue | undefined) => string | number | null | undefined = ( v ) => v

/**
 * The value to revert to if the Reset button is clicked (enabled by
 * `allowReset`)
 */
resetFallbackValue?: number

/**
 * Define if separator line under/above control row should be disabled
 * or full width. By default it is placed below excluding underline the
 * control icon.
 */
separatorType?: "none" | "fullWidth" | "topFullWidth"

/**
 * Passed as a prop to the `NumberControl` component and is only
 * applicable if `withInputField` and `isShiftStepEnabled` are both true
 * and while the number input has focus. Acts as a multiplier of `step`.
 */
shiftStep?: number = 10

/**
 * Forcing the Tooltip UI to show or hide. This is overridden to `false`
 * when `step` is set to the special string value `any`.
 */
showTooltip?: boolean

/**
 * The minimum amount by which `value` changes. It is also a factor in
 * validation as `value` must be a multiple of `step` (offset by `min`) to
 * be valid. Accepts the special string value `any` that voids the
 * validation constraint and overrides both `withInputField` and
 * `showTooltip` props to `false`.
 */
step?: number | "any" | undefined = 1

/**
 * CSS color string to customize the track element's background.
 */
trackColor?: Color | undefined

/**
 * Define if the value selection should present a stepper control or a
 * slider control in the bottom sheet on mobile. To use the stepper set
 * the type value as `stepper`. Defaults to slider if no option is
 * provided.
 */
type?: "stepper"

/**
 * The current value of the range slider.
 */
value?: number

/**
 * Determines if the `input` number field will render next to the
 * RangeControl. This is overridden to `false` when `step` is set to the
 * special string value `any`.
 */
withInputField?: boolean = true
Imports
import { RangeControl } from '@wordpress/components';
import { fn } from 'storybook/test';
Default story ok
const Default = () => {
    const [ value, setValue ] = useState< number >();

    return (
        <RangeControl
            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
                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
                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
                onBlur={fn()}
                onFocus={fn()}
                onMouseLeave={fn()}
                onMouseMove={fn()}
                marks={[
                    { value: 0, label: '0' },
                    { value: 1, label: '1' },
                    { value: 2, label: '2' },
                    { value: 8, label: '8' },
                    { value: 10, label: '10' },
                ]}
                max={10}
                min={0}
                step={1}
                label="Custom marks"
                onChange={ ( v ) => {
					setCustomValue( v );
					onChange?.( v );
				} }
                value={ customValue } />
        </>
    );
};
With Decimal Step And Marks incomplete example
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
                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
                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 } />
        </>
    );
};
Incomplete snippet: `marksBase` could not be resolved statically.
With Negative Minimum And Marks incomplete example
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
                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
                onBlur={fn()}
                onFocus={fn()}
                onMouseLeave={fn()}
                onMouseMove={fn()}
                marks={[
                    ...marksBase,
                    { value: -1, label: '-1' },
                    { value: -2, label: '-2' },
                    { value: -4, label: '-4' },
                    { value: -8, label: '-8' },
                ]}
                max={10}
                min={-10}
                step={1}
                label="Custom marks"
                onChange={ ( v ) => {
					setCustomValue( v );
					onChange?.( v );
				} }
                value={ customValue } />
        </>
    );
};
Incomplete snippet: `marksBase` could not be resolved statically.
With Negative Range And Marks incomplete example
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
                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
                onBlur={fn()}
                onFocus={fn()}
                onMouseLeave={fn()}
                onMouseMove={fn()}
                marks={[
                    ...marksBase,
                    { value: -1, label: '-1' },
                    { value: -2, label: '-2' },
                    { value: -4, label: '-4' },
                    { value: -8, label: '-8' },
                ]}
                max={-1}
                min={-10}
                step={1}
                label="Custom marks"
                onChange={ ( v ) => {
					setCustomValue( v );
					onChange?.( v );
				} }
                value={ customValue } />
        </>
    );
};
Incomplete snippet: `marksBase` could not be resolved statically.
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
                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
                onBlur={fn()}
                onFocus={fn()}
                onMouseLeave={fn()}
                onMouseMove={fn()}
                marks={[
                    { value: 0, label: '0' },
                    { value: 1, label: '1' },
                    { value: 2, label: '2' },
                    { value: 8, label: '8' },
                    { value: 10, label: '10' },
                ]}
                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
`ResizableBox` wraps content in a container with draggable handles, letting users interactively resize it along one or more edges or corners.
Prop types (react-component-meta) 35 prop types
Component: ../packages/components/src/resizable-box/index.tsx::default
Props:
__experimentalShowTooltip?: boolean = false

__experimentalTooltipProps?: Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { as?: ElementType | undefined; ... 9 more ...; zIndex?: number | undefined; } & RefAttributes<...> = {}

as?: string | ComponentType<any> | undefined

bounds?: HTMLElement | "parent" | "window" | undefined

boundsByDirection?: boolean

children?: ReactNode

className?: string

defaultSize?: Size

enable?: false | Enable | undefined

grid?: [number, number]

gridGap?: [number, number]

handleClasses?: HandleClassName

handleComponent?: HandleComponent

handleStyles?: HandleStyles

handleWrapperClass?: string

handleWrapperStyle?: CSSProperties

key?: Key | null | undefined

lockAspectRatio?: number | boolean | undefined

lockAspectRatioExtraHeight?: number

lockAspectRatioExtraWidth?: number

maxHeight?: string | number | undefined

maxWidth?: string | number | undefined

minHeight?: string | number | undefined

minWidth?: string | number | undefined

onResize?: ResizeCallback

onResizeStart?: ResizeStartCallback

onResizeStop?: ResizeCallback

/**
 * Allows getting a ref to the component instance.
 * Once the component unmounts, React will set `ref.current` to `null`
 * (or call the ref with `null` if you passed a callback ref).
 */
ref?: Ref<Resizable> | undefined

resizeRatio?: number | [number, number] | undefined

scale?: number

showHandle?: boolean = true

size?: Size

snap?: { x?: number[] | undefined; y?: number[] | undefined; }

snapGap?: number

style?: CSSProperties
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,
				} );
			} }
		/>
	);
};
With Resize Tooltip story ok
The resize size label is hidden by default. Enable it with `__experimentalShowTooltip`, or toggle that control in Storybook.
const WithResizeTooltip = ( {
	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,
				} );
			} }
		/>
	);
};

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 (react-component-meta) 10 prop types
Component: ../packages/components/src/sandbox/index.tsx::default
Props:
/**
 * Whether to include `allow-forms` in the iframe's sandbox attribute.
 * When true, content inside the iframe is allowed to submit forms.
 * 
 * Enable this for previews whose content includes forms that should be
 * submittable.
 */
allowForms?: boolean = false

/**
 * Whether to include `allow-popups` in the iframe's sandbox attribute.
 * When true, content inside the iframe is allowed to open new browsing
 * contexts (e.g. links that open in a new tab, or `window.open`).
 * 
 * Enable this for previews whose content includes links that should be
 * followable, such as embeds.
 */
allowPopups?: boolean = false

/**
 * Whether to include `allow-same-origin` in the iframe's sandbox
 * attribute. When true, nested iframes (such as third-party embeds)
 * can access their own origin's cookies and storage.
 * 
 * Only enable this for content that is NOT directly user-controlled,
 * such as server-fetched oEmbed previews.
 */
allowSameOrigin?: boolean = false

/**
 * The HTML to render in the body of the iframe document.
 */
html?: string = ''

/**
 * The `onFocus` callback for the iframe.
 */
onFocus?: FocusEventHandler<HTMLIFrameElement>

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

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

/**
 * The `tabindex` the iframe should receive.
 */
tabIndex?: number = 0

/**
 * The `<title>` of the iframe document.
 */
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';
import { fn } from 'storybook/test';
Default story ok
const Default = () => <SandBox
    onFocus={fn()}
    title="Sandbox preview"
    html="<p>Arbitrary HTML content</p>"
    allowForms={false} />;
With Form story ok
const WithForm = () => <SandBox
    onFocus={fn()}
    title="Sandbox preview with form"
    html="<form action=\"#\"><label for=\"name\">Name</label><input id=\"name\" type=\"text\" /><button type=\"submit\">Submit</button></form>"
    allowForms />;

ScrollLock

no API description
components-scrolllock · ../packages/components/src/scroll-lock/stories/index.story.tsx
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> ); }; ```
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>
	);
};

SearchableChipSelect

design-system-components-form-primitives-searchablechipselect · ../packages/ui/src/form/primitives/searchable-chip-select/stories/index.story.tsx
A low-level primitive for a searchable multi-selection field with chips, with support for a creatable footer action. Prefer `SearchableChipSelectControl` when using with a standard label and description.
Prop types (react-component-meta) 48 prop types
Component: ../packages/ui/src/form/primitives/searchable-chip-select/index.ts::SearchableChipSelect
Props:
/**
 * A ref to imperative actions.
 * - `unmount`: Ends the closing phase of the combobox after an externally controlled closing animation finishes.
 * Call `preventUnmountOnClose()` in `onOpenChange` first, otherwise the combobox completes closing on its own.
 * Whether it leaves the DOM is decided by `keepMounted` on the portal.
 * - `close`: Closes the combobox imperatively when called.
 */
actionsRef?: RefObject<Actions | null>

/**
 * Identifies the element (or elements) that describes the object.
 */
aria-describedby?: string

/**
 * Defines a string value that labels the current element.
 */
aria-label?: string

/**
 * Identifies the element (or elements) that labels the current element.
 */
aria-labelledby?: string

/**
 * Provides a hint to the browser for autofill.
 */
autoComplete?: string

/**
 * Whether the first matching item is highlighted automatically while filtering.
 */
autoHighlight?: boolean = false

/**
 * A render function for custom rendering the list of matching items.
 * Required when `items` contains groups.
 */
children?: (item: any, index: number) => ReactNode

/**
 * A render function for custom rendering the selected chips.
 * 
 * The chip is named from its content. Pass `aria-label` when that
 * content is not a usable name.
 * 
 * ```jsx
 * chipsContent={ ( value ) =>
 *   value.map( ( item ) => (
 *     <SearchableChipSelect.ChipWithRemove key={ item.value }>
 *       <Icon icon={ wordpress } />
 *       { item.label }
 *     </SearchableChipSelect.ChipWithRemove>
 *   ) )
 * }
 * ```
 */
chipsContent?: (value: Item[]) => ReactNode

/**
 * The aria-label for the clear button.
 */
clearButtonLabel?: string = __( 'Clear all' )

/**
 * The uncontrolled input value when initially rendered.
 * 
 * To render a controlled input, use the `inputValue` prop instead.
 */
defaultInputValue?: string | number | readonly string[] | undefined

/**
 * Whether the popup is initially open.
 * 
 * To render a controlled popup, use the `open` prop instead.
 */
defaultOpen?: boolean = false

/**
 * The uncontrolled selected value of the combobox when it's initially rendered.
 * 
 * To render a controlled combobox, use the `value` prop instead.
 */
defaultValue?: readonly Item[] | null | undefined

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

/**
 * The custom content to use instead of the default empty state,
 * which shows whenever there are no matching items.
 */
emptyContent?: ReactNode = __( 'No results found.' )

/**
 * Filter function used to match items vs input query.
 * Receives the source item, which is the derived value's item when `items` is a `createItems()`
 * collection, and the item itself otherwise.
 */
filter?: ((item: Item, query: string, itemToString?: ((item: Item) => string) | undefined) => boolean) | null | undefined

/**
 * Filtered items to display in the list.
 * When provided, the list uses these items instead of filtering the `items` prop internally.
 * When `items` is also provided, this array must preserve its flat or grouped structure.
 * With a `createItems()` collection, pass source items rather than derived values.
 * Nullish entries are not supported, as in `items`.
 * Use when you want to control filtering logic externally with the `useFilter()` hook.
 */
filteredItems?: readonly Item[] | readonly Group<Item>[] | undefined

/**
 * Identifies the form that owns the internal input.
 * Useful when the combobox is rendered outside the form.
 */
form?: string

/**
 * Whether list items are presented in a grid layout.
 * When enabled, arrow keys navigate across rows and columns inferred from DOM rows.
 */
grid?: boolean = false

/**
 * Whether moving the pointer over items should highlight them.
 * Disabling this prop allows CSS `:hover` to be differentiated from the `:focus` (`data-highlighted`) state.
 */
highlightItemOnHover?: boolean = true

/**
 * The id of the component.
 */
id?: string

/**
 * Whether the list is rendered inline without using the component's own popup.
 * 
 * Specify `open` unconditionally in conjunction with this prop so the list is considered
 * visible: `<Combobox.Root inline open>`
 * 
 * In a `Combobox.Root` > `Dialog.Root` composition, bind the Combobox's `open` and
 * `onOpenChange` props to the `Dialog`'s `open` and `onOpenChange` state instead so the
 * component resets its transient state (filter query, highlighted item, and input value) when
 * the dialog closes.
 */
inline?: boolean = false

/**
 * A ref to the hidden input element.
 */
inputRef?: Ref<HTMLInputElement> | undefined

/**
 * The input value of the combobox. Use when controlled.
 */
inputValue?: string | number | readonly string[] | undefined

/**
 * Custom comparison logic used to determine if a combobox item value matches the current selected value. Useful when item values are objects without matching referentially.
 * With a `createItems()` collection, both arguments are derived values.
 * Defaults to `Object.is` comparison.
 */
isItemEqualToValue?: (itemValue: Item, value: Item) => boolean

/**
 * The array of option items.
 * 
 * When using grouped `children`, pass an array of groups instead of a
 * flat list of items. Grouped items require a custom `children` renderer.
 * 
 * Mark a creatable action with `creatable: true`. It renders in the
 * list footer, not the main list, when it is in the filtered items.
 * Handle the creation of the item in `onValueChange`.
 */
items?: Item[] | ItemGroup[] | undefined

/**
 * When the item values are objects (`<Combobox.Item value={object}>`), this function converts the object value to a string representation for display in the input.
 * If the shape of the object is `{ value, label }`, the label will be used automatically without needing to specify this prop.
 * With a `createItems()` collection, this receives the derived value, and the collection's
 * `getLabel` takes precedence for values it can resolve.
 */
itemToStringLabel?: (itemValue: Item) => string

/**
 * When the item values are objects (`<Combobox.Item value={object}>`), this function converts the object value to a string representation for form submission.
 * If the shape of the object is `{ value, label }`, the value will be used automatically without needing to specify this prop.
 * With a `createItems()` collection, this receives the derived value.
 */
itemToStringValue?: (itemValue: Item) => string

key?: Key | null | undefined

/**
 * The maximum number of items to display in the list.
 */
limit?: number = -1

/**
 * The locale to use for string comparison.
 * Defaults to the user's runtime locale.
 */
locale?: LocalesArgument

/**
 * Whether to loop keyboard focus back to the input when the end of the list is reached while using the arrow keys. The first item can then be reached by pressing <kbd>ArrowDown</kbd> again from the input, or the last item can be reached by pressing <kbd>ArrowUp</kbd> from the input.
 * The input is always included in the focus loop per [ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/).
 * When disabled, focus does not move when on the last element and the user presses <kbd>ArrowDown</kbd>, or when on the first element and the user presses <kbd>ArrowUp</kbd>.
 */
loopFocus?: boolean = true

/**
 * Determines if the popup enters a modal state when open.
 * - `true`: user interaction is limited to the popup: document page scroll is locked and pointer interactions on outside elements are disabled.
 * - `false`: user interaction with the rest of the document is allowed.
 * 
 * On touch devices, a `true` modal blocks outside taps but leaves the page scrollable unless the popup spans nearly the full viewport width, matching native iOS behavior.
 */
modal?: boolean = false

/**
 * Identifies the field when a form is submitted.
 */
name?: string

/**
 * Event handler called when the input value changes.
 */
onInputValueChange?: (inputValue: string, eventDetails: ChangeEventDetails) => void

/**
 * Callback fired when an item is highlighted or unhighlighted.
 * Receives the highlighted item value (or `undefined` if no item is highlighted) and event details with a `reason` property describing why the highlight changed.
 * The `reason` can be:
 * - `'keyboard'`: the highlight changed due to keyboard navigation.
 * - `'pointer'`: the highlight changed due to pointer hovering. The event may be a `MouseEvent`
 *   rather than a `PointerEvent`.
 * - `'none'`: the highlight changed for another reason, such as typing, `autoHighlight`, the
 *   item list changing, or the popup opening or closing.
 */
onItemHighlighted?: (highlightedValue: Item | undefined, eventDetails: HighlightEventDetails) => void

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

/**
 * Event handler called after any animations complete when the popup is opened or closed.
 */
onOpenChangeComplete?: (open: boolean) => void

/**
 * Event handler called when the selected value of the combobox changes.
 */
onValueChange?: (value: Item[], eventDetails: ChangeEventDetails) => void

/**
 * Whether the popup is currently open. Use when controlled.
 */
open?: boolean

/**
 * Whether the popup opens when clicking the input.
 */
openOnInputClick?: boolean = true

/**
 * Controls how the popup width is constrained relative to its anchor.
 * 
 * For all presets, the popup is never narrower than its anchor.
 * 
 * - `'anchor'`: Fixed width matching the anchor width.
 * - `'content'`: Width grows with item labels between the anchor and available
 *   viewport bounds.
 * - `'sm'`: Fixed width at the small surface width token (`--wpds-dimension-surface-width-sm`).
 * - `'md'`: Fixed width at the medium surface width token (`--wpds-dimension-surface-width-md`).
 * - `'lg'`: Fixed width at the large surface width token (`--wpds-dimension-surface-width-lg`).
 * - `'available'`: Fixed width at the available viewport width (`--available-width`).
 */
popupWidth?: "anchor" | "content" | "sm" | "md" | "lg" | "available" = 'anchor'

/**
 * Allows getting a ref to the component instance.
 * Once the component unmounts, React will set `ref.current` to `null`
 * (or call the ref with `null` if you passed a callback ref).
 */
ref?: Ref<HTMLInputElement> | undefined

/**
 * Whether the user must choose a value before submitting a form.
 */
required?: boolean = false

/**
 * The placeholder text to use for the search input.
 */
searchPlaceholder?: string = __( 'Search' )

/**
 * Whether to show the clear button to remove all selected items.
 */
showClearButton?: boolean = true

/**
 * Content for the list status live region. The region stays mounted.
 */
statusContent?: ReactNode

/**
 * The selected value of the combobox. Use when controlled.
 */
value?: readonly Item[] | null | undefined

/**
 * Whether the items are being externally virtualized.
 */
virtualized?: boolean = false
Imports
import { Fragment } from '@wordpress/element';
import { SearchableChipSelect } from '@wordpress/ui';
import { ITEMS } from './fixtures';
import { SearchableChipSelect } from '../';
import { GROUPED_ITEMS } from '../../combobox/stories/fixtures';
import { longLabelPopupItems } from '../../../stories/shared';
Default story ok
const Default = () => <SearchableChipSelect
    defaultValue={[ ITEMS[ 0 ], ITEMS[ 1 ] ]}
    items={ITEMS}
    aria-label="Fruit" />;
With Item Descriptions story ok
Item descriptions supplement each popup item and are not copied to chips.
const WithItemDescriptions = () => <SearchableChipSelect
    defaultValue={[]}
    items={[
        { value: 'apple', label: 'Apple', description: 'A crisp fruit.' },
        { value: 'banana', label: 'Banana', description: 'A soft fruit.' },
    ]}
    aria-label="Fruit" />;
With Custom Chips And Items story ok
To customize what is rendered inside the chips, pass a render function to the `chipsContent` prop that returns an array of `ChipWithRemove` subcomponents. The chip is named from its content. Pass `aria-label` when that content is not a usable name. The item list can be customized by passing a render function as `children`, returning an `Item` subcomponent for each item.
const WithCustomChipsAndItems = () => <SearchableChipSelect
    defaultValue={[ ITEMS[ 0 ], ITEMS[ 1 ] ]}
    items={ITEMS}
    aria-label="Fruit"
    chipsContent={( value: typeof ITEMS ) =>
        value.map( ( item ) => (
            <SearchableChipSelect.ChipWithRemove
                key={ item.value }
                prefix={
                    <img
                        src={ `https://gravatar.com/avatar/?d=initials&initials=${ item.label }` }
                        alt=""
                        style={ { width: '100%' } }
                    />
                }
            >
                { item.label }
            </SearchableChipSelect.ChipWithRemove>
        ) )}>{( item: ( typeof ITEMS )[ 0 ] ) => (
        <SearchableChipSelect.Item key={ item.value } value={ item }>
            <SearchableChipSelect.ItemLabel>
                😋 { item.label }
            </SearchableChipSelect.ItemLabel>
        </SearchableChipSelect.Item>
    )}</SearchableChipSelect>;
With Custom Empty Content story ok
Use the `emptyContent` prop to customize the empty state, which shows whenever there are no matching items.
const WithCustomEmptyContent = () => <SearchableChipSelect
    defaultValue={[ ITEMS[ 0 ], ITEMS[ 1 ] ]}
    items={ITEMS}
    aria-label="Fruit"
    emptyContent="No fruit found 🥺" />;
Grouped incomplete example
To render grouped items, pass an array of groups to `items` (each with `label` and `items` properties) and provide `children` that renders each group using `SearchableChipSelect.Group`, `SearchableChipSelect.GroupLabel`, and `SearchableChipSelect.Collection`. Grouped items have no default renderer, so `children` is required.
const Grouped = () => <SearchableChipSelect aria-label="Fruit" items={GROUPED_ITEMS}>{( group: FixtureGroup ) => (
        <SearchableChipSelect.Group
            key={ group.label }
            items={ group.items }
        >
            <SearchableChipSelect.GroupLabel>
                { group.label }
            </SearchableChipSelect.GroupLabel>
            <SearchableChipSelect.Collection>
                { ( item: FixtureItem ) => (
                    <SearchableChipSelect.Item
                        key={ item.value }
                        value={ item }
                    >
                        <SearchableChipSelect.ItemLabel>
                            { item.label }
                        </SearchableChipSelect.ItemLabel>
                    </SearchableChipSelect.Item>
                ) }
            </SearchableChipSelect.Collection>
        </SearchableChipSelect.Group>
    )}</SearchableChipSelect>;
Incomplete snippet: `FixtureGroup`, `FixtureItem` could not be resolved statically.
With Separator incomplete example
Use `SearchableChipSelect.Separator` to set choices apart from each other.
const WithSeparator = () => <SearchableChipSelect
    defaultValue={[ ITEMS[ 0 ], ITEMS[ 1 ] ]}
    items={[ ...ITEMS.slice( 0, 3 ), { value: 'other', label: 'Other' } ]}
    aria-label="Fruit">{( item: FixtureItem, index: number ) => (
        <Fragment key={ item.value }>
            { item.value === 'other' && index > 0 && (
                <SearchableChipSelect.Separator />
            ) }
            <SearchableChipSelect.Item value={ item }>
                <SearchableChipSelect.ItemLabel>
                    { item.label }
                </SearchableChipSelect.ItemLabel>
            </SearchableChipSelect.Item>
        </Fragment>
    )}</SearchableChipSelect>;
Incomplete snippet: `FixtureItem` could not be resolved statically.
Without Clear Button story ok
Use the `showClearButton` prop to hide the clear button.
const WithoutClearButton = () => <SearchableChipSelect
    defaultValue={[ ITEMS[ 0 ], ITEMS[ 1 ] ]}
    items={ITEMS}
    aria-label="Fruit"
    showClearButton={false} />;
Popup Width story ok
Use `popupWidth` to constrain the popup relative to a narrow anchor.
const PopupWidth = () => <SearchableChipSelect aria-label="Tags" items={longLabelPopupItems} popupWidth="sm" />;
SearchableChipSelect.Group 5 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/searchable-chip-select/index.ts
Groups related items together with an associated label rendered by `Combobox.GroupLabel`. When `items` is provided, child `Combobox.Collection` components iterate over them.
import { SearchableChipSelect } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/searchable-chip-select/index.ts::SearchableChipSelect (react-component-meta)
children?: ReactNode

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

/**
 * Items to be rendered within this group.
 * When provided, child `Collection` components will use these items.
 */
items?: readonly any[]

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SearchableChipSelect.GroupLabel 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/searchable-chip-select/index.ts
Renders a label for a `Combobox.Group`, describing the group of items it is associated with.
import { SearchableChipSelect } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/searchable-chip-select/index.ts::SearchableChipSelect (react-component-meta)
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SearchableChipSelect.Separator 3 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/searchable-chip-select/index.ts
Renders a visual separator between combobox items or groups.
import { SearchableChipSelect } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/searchable-chip-select/index.ts::SearchableChipSelect (react-component-meta)
/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SearchableChipSelect.Item 10 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/searchable-chip-select/index.ts
import { SearchableChipSelect } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/searchable-chip-select/index.ts::SearchableChipSelect (react-component-meta)
/**
 * One direct ItemLabel, followed by zero or more ItemDescription components.
 */
children: ComboboxItemChildren

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

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

/**
 * The index of the item in the list. Improves performance when specified by avoiding the need to calculate the index automatically from the DOM.
 */
index?: number

/**
 * Whether the component renders a native `<button>` element when replacing it
 * via the `render` prop.
 * Set to `true` if the rendered element is a native button.
 */
nativeButton?: boolean = false

/**
 * An optional click handler for the item when selected.
 * It fires when clicking the item with the pointer, as well as when pressing `Enter` with the keyboard if the item is highlighted when the `Input` or `List` element has focus.
 */
onClick?: (event: BaseUIEvent<MouseEvent<HTMLDivElement, MouseEvent>>) => void

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * A unique value that identifies this item.
 */
value?: any = null

/**
 * The variant of the item.
 * 
 * - `'default'`: A standard item.
 * - `'creatable'`: An item that triggers the creation of a new item.
 */
variant?: "default" | "creatable" = 'default'
SearchableChipSelect.ItemLabel 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/searchable-chip-select/index.ts
The primary label of a combobox item. Use it as the first direct child of every item. Its content is the item's accessible name. The selected value still uses the item's `label` or the content of `Combobox.Value`.
import { SearchableChipSelect } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/searchable-chip-select/index.ts::SearchableChipSelect (react-component-meta)
/**
 * The primary label and accessible name of a combobox item.
 */
children: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SearchableChipSelect.ItemDescription 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/searchable-chip-select/index.ts
Supplementary content for a combobox item. Its text contributes to the item's accessible description. Use it as a direct child after `Combobox.ItemLabel`. Content should be text or non-interactive inline markup.
import { SearchableChipSelect } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/searchable-chip-select/index.ts::SearchableChipSelect (react-component-meta)
/**
 * Content that contributes to the combobox item's accessible description.
 */
children: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SearchableChipSelect.ChipWithRemove 6 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/searchable-chip-select/index.ts
A utility component that combines a chip and a remove button, with standard styling.
import { SearchableChipSelect } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/searchable-chip-select/index.ts::SearchableChipSelect (react-component-meta)
children?: ReactNode

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

/**
 * Circular element to render before the chip content.
 */
prefix?: ReactNode

/**
 * Accessible label for the remove button.
 * Keep this to the action (for example `Remove`). The chip label describes
 * the button.
 */
removeLabel?: string = __( 'Remove' )

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SearchableChipSelect.Collection 1 prop type
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/searchable-chip-select/index.ts
import { SearchableChipSelect } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/searchable-chip-select/index.ts::SearchableChipSelect (react-component-meta)
children: (item: any, index: number) => ReactNode

SearchableChipSelectControl

design-system-components-form-searchablechipselectcontrol · ../packages/ui/src/form/searchable-chip-select-control/stories/index.story.tsx
A complete searchable multi-select field with chips, integrated label, and description.
Prop types (react-component-meta) 53 prop types
Component: ../packages/ui/src/form/searchable-chip-select-control/index.ts::SearchableChipSelectControl
Props:
/**
 * A ref to imperative actions.
 * - `unmount`: Ends the closing phase of the combobox after an externally controlled closing animation finishes.
 * Call `preventUnmountOnClose()` in `onOpenChange` first, otherwise the combobox completes closing on its own.
 * Whether it leaves the DOM is decided by `keepMounted` on the portal.
 * - `close`: Closes the combobox imperatively when called.
 */
actionsRef?: RefObject<Actions | null>

/**
 * Identifies the element (or elements) that describes the object.
 */
aria-describedby?: string

/**
 * Defines a string value that labels the current element.
 */
aria-label?: string

/**
 * Identifies the element (or elements) that labels the current element.
 */
aria-labelledby?: string

/**
 * Provides a hint to the browser for autofill.
 */
autoComplete?: string

/**
 * Whether the first matching item is highlighted automatically while filtering.
 */
autoHighlight?: boolean = false

/**
 * A render function for custom rendering the list of matching items.
 * Required when `items` contains groups.
 */
children?: (item: any, index: number) => ReactNode

/**
 * A render function for custom rendering the selected chips.
 * 
 * The chip is named from its content. Pass `aria-label` when that
 * content is not a usable name.
 * 
 * ```jsx
 * chipsContent={ ( value ) =>
 *   value.map( ( item ) => (
 *     <SearchableChipSelect.ChipWithRemove key={ item.value }>
 *       <Icon icon={ wordpress } />
 *       { item.label }
 *     </SearchableChipSelect.ChipWithRemove>
 *   ) )
 * }
 * ```
 */
chipsContent?: (value: Item[]) => ReactNode

/**
 * CSS class to apply.
 */
className?: string

/**
 * The aria-label for the clear button.
 */
clearButtonLabel?: string

/**
 * The uncontrolled input value when initially rendered.
 * 
 * To render a controlled input, use the `inputValue` prop instead.
 */
defaultInputValue?: string | number | readonly string[] | undefined

/**
 * Whether the popup is initially open.
 * 
 * To render a controlled popup, use the `open` prop instead.
 */
defaultOpen?: boolean = false

/**
 * The uncontrolled selected value of the combobox when it's initially rendered.
 * 
 * To render a controlled combobox, use the `value` prop instead.
 */
defaultValue?: readonly Item[] | null | undefined

/**
 * The accessible description, associated using `aria-describedby`.
 * 
 * For screen reader accessibility, this should only contain plain text,
 * and no semantics such as links.
 */
description?: string

/**
 * 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?: ReactNode

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

/**
 * The custom content to use instead of the default empty state,
 * which shows whenever there are no matching items.
 */
emptyContent?: ReactNode

/**
 * Filter function used to match items vs input query.
 * Receives the source item, which is the derived value's item when `items` is a `createItems()`
 * collection, and the item itself otherwise.
 */
filter?: ((item: Item, query: string, itemToString?: ((item: Item) => string) | undefined) => boolean) | null | undefined

/**
 * Filtered items to display in the list.
 * When provided, the list uses these items instead of filtering the `items` prop internally.
 * When `items` is also provided, this array must preserve its flat or grouped structure.
 * With a `createItems()` collection, pass source items rather than derived values.
 * Nullish entries are not supported, as in `items`.
 * Use when you want to control filtering logic externally with the `useFilter()` hook.
 */
filteredItems?: readonly Item[] | readonly Group<Item>[] | undefined

/**
 * Identifies the form that owns the internal input.
 * Useful when the combobox is rendered outside the form.
 */
form?: string

/**
 * Whether list items are presented in a grid layout.
 * When enabled, arrow keys navigate across rows and columns inferred from DOM rows.
 */
grid?: boolean = false

/**
 * Whether to visually hide the label while keeping it accessible
 * to screen readers.
 */
hideLabelFromVision?: boolean = false

/**
 * Whether moving the pointer over items should highlight them.
 * Disabling this prop allows CSS `:hover` to be differentiated from the `:focus` (`data-highlighted`) state.
 */
highlightItemOnHover?: boolean = true

/**
 * The id of the component.
 */
id?: string

/**
 * Whether the list is rendered inline without using the component's own popup.
 * 
 * Specify `open` unconditionally in conjunction with this prop so the list is considered
 * visible: `<Combobox.Root inline open>`
 * 
 * In a `Combobox.Root` > `Dialog.Root` composition, bind the Combobox's `open` and
 * `onOpenChange` props to the `Dialog`'s `open` and `onOpenChange` state instead so the
 * component resets its transient state (filter query, highlighted item, and input value) when
 * the dialog closes.
 */
inline?: boolean = false

/**
 * A ref to the hidden input element.
 */
inputRef?: Ref<HTMLInputElement> | undefined

/**
 * The input value of the combobox. Use when controlled.
 */
inputValue?: string | number | readonly string[] | undefined

/**
 * Custom comparison logic used to determine if a combobox item value matches the current selected value. Useful when item values are objects without matching referentially.
 * With a `createItems()` collection, both arguments are derived values.
 * Defaults to `Object.is` comparison.
 */
isItemEqualToValue?: (itemValue: Item, value: Item) => boolean

/**
 * The array of option items.
 * 
 * When using grouped `children`, pass an array of groups instead of a
 * flat list of items. Grouped items require a custom `children` renderer.
 * 
 * Mark a creatable action with `creatable: true`. It renders in the
 * list footer, not the main list, when it is in the filtered items.
 * Handle the creation of the item in `onValueChange`.
 */
items?: Item[] | ItemGroup[] | undefined

/**
 * When the item values are objects (`<Combobox.Item value={object}>`), this function converts the object value to a string representation for display in the input.
 * If the shape of the object is `{ value, label }`, the label will be used automatically without needing to specify this prop.
 * With a `createItems()` collection, this receives the derived value, and the collection's
 * `getLabel` takes precedence for values it can resolve.
 */
itemToStringLabel?: (itemValue: Item) => string

/**
 * When the item values are objects (`<Combobox.Item value={object}>`), this function converts the object value to a string representation for form submission.
 * If the shape of the object is `{ value, label }`, the value will be used automatically without needing to specify this prop.
 * With a `createItems()` collection, this receives the derived value.
 */
itemToStringValue?: (itemValue: Item) => string

key?: Key | null | undefined

/**
 * The accessible label. All controls must be labeled.
 */
label: string

/**
 * The maximum number of items to display in the list.
 */
limit?: number = -1

/**
 * The locale to use for string comparison.
 * Defaults to the user's runtime locale.
 */
locale?: LocalesArgument

/**
 * Whether to loop keyboard focus back to the input when the end of the list is reached while using the arrow keys. The first item can then be reached by pressing <kbd>ArrowDown</kbd> again from the input, or the last item can be reached by pressing <kbd>ArrowUp</kbd> from the input.
 * The input is always included in the focus loop per [ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/).
 * When disabled, focus does not move when on the last element and the user presses <kbd>ArrowDown</kbd>, or when on the first element and the user presses <kbd>ArrowUp</kbd>.
 */
loopFocus?: boolean = true

/**
 * Determines if the popup enters a modal state when open.
 * - `true`: user interaction is limited to the popup: document page scroll is locked and pointer interactions on outside elements are disabled.
 * - `false`: user interaction with the rest of the document is allowed.
 * 
 * On touch devices, a `true` modal blocks outside taps but leaves the page scrollable unless the popup spans nearly the full viewport width, matching native iOS behavior.
 */
modal?: boolean = false

/**
 * Identifies the field when a form is submitted.
 */
name?: string

/**
 * Event handler called when the input value changes.
 */
onInputValueChange?: (inputValue: string, eventDetails: ChangeEventDetails) => void

/**
 * Callback fired when an item is highlighted or unhighlighted.
 * Receives the highlighted item value (or `undefined` if no item is highlighted) and event details with a `reason` property describing why the highlight changed.
 * The `reason` can be:
 * - `'keyboard'`: the highlight changed due to keyboard navigation.
 * - `'pointer'`: the highlight changed due to pointer hovering. The event may be a `MouseEvent`
 *   rather than a `PointerEvent`.
 * - `'none'`: the highlight changed for another reason, such as typing, `autoHighlight`, the
 *   item list changing, or the popup opening or closing.
 */
onItemHighlighted?: (highlightedValue: Item | undefined, eventDetails: HighlightEventDetails) => void

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

/**
 * Event handler called after any animations complete when the popup is opened or closed.
 */
onOpenChangeComplete?: (open: boolean) => void

/**
 * Event handler called when the selected value of the combobox changes.
 */
onValueChange?: (value: Item[], eventDetails: ChangeEventDetails) => void

/**
 * Whether the popup is currently open. Use when controlled.
 */
open?: boolean

/**
 * Whether the popup opens when clicking the input.
 */
openOnInputClick?: boolean = true

/**
 * Controls how the popup width is constrained relative to its anchor.
 * 
 * For all presets, the popup is never narrower than its anchor.
 * 
 * - `'anchor'`: Fixed width matching the anchor width.
 * - `'content'`: Width grows with item labels between the anchor and available
 *   viewport bounds.
 * - `'sm'`: Fixed width at the small surface width token (`--wpds-dimension-surface-width-sm`).
 * - `'md'`: Fixed width at the medium surface width token (`--wpds-dimension-surface-width-md`).
 * - `'lg'`: Fixed width at the large surface width token (`--wpds-dimension-surface-width-lg`).
 * - `'available'`: Fixed width at the available viewport width (`--available-width`).
 */
popupWidth?: "anchor" | "content" | "sm" | "md" | "lg" | "available" = 'anchor'

/**
 * Allows getting a ref to the component instance.
 * Once the component unmounts, React will set `ref.current` to `null`
 * (or call the ref with `null` if you passed a callback ref).
 */
ref?: Ref<HTMLInputElement> | undefined

/**
 * Whether the user must choose a value before submitting a form.
 */
required?: boolean = false

/**
 * The placeholder text to use for the search input.
 */
searchPlaceholder?: string

/**
 * Whether to show the clear button to remove all selected items.
 */
showClearButton?: boolean = true

/**
 * Content for the list status live region. The region stays mounted.
 */
statusContent?: ReactNode

/**
 * The selected value of the combobox. Use when controlled.
 */
value?: readonly Item[] | null | undefined

/**
 * Whether the items are being externally virtualized.
 */
virtualized?: boolean = false
Imports
import { SearchableChipSelectControl, Spinner, Stack, VisuallyHidden } from '@wordpress/ui';
import { DETAILS_EXAMPLE, longLabelPopupItems } from '../../stories/shared';
import { ITEMS } from '../../primitives/searchable-chip-select/stories/fixtures';
import { GROUPED_ITEMS } from '../../primitives/combobox/stories/fixtures';
Default incomplete example
const Default = () => <SearchableChipSelectControl label="Label" description="This is a description." />;
Incomplete snippet: `...SearchableChipSelectStories.Default`, `...SearchableChipSelectStories.Default.args` could not be resolved statically.
With Item Descriptions incomplete example
const WithItemDescriptions = () => <SearchableChipSelectControl
    defaultValue={[]}
    items={[
        { value: 'apple', label: 'Apple', description: 'A crisp fruit.' },
        { value: 'banana', label: 'Banana', description: 'A soft fruit.' },
    ]}
    aria-label="Fruit"
    label="Fruit" />;
Incomplete snippet: `...SearchableChipSelectStories.WithItemDescriptions` could not be resolved statically.
Visually Hidden Label incomplete example
const VisuallyHiddenLabel = () => <SearchableChipSelectControl hideLabelFromVision />;
Incomplete snippet: `...Default.args` could not be resolved statically.
With Details incomplete example
const WithDetails = () => <SearchableChipSelectControl description={undefined} details={DETAILS_EXAMPLE} />;
Incomplete snippet: `...Default.args` could not be resolved statically.
With Custom Search Placeholder incomplete example
Use the `searchPlaceholder` prop to customize the search input placeholder text. Prefer a concise label without a trailing ellipsis.
const WithCustomSearchPlaceholder = () => <SearchableChipSelectControl searchPlaceholder="Search fruit" />;
Incomplete snippet: `...Default.args` could not be resolved statically.
With Disabled Option incomplete example
const WithDisabledOption = () => <SearchableChipSelectControl
    items={[
        {
            value: 'apple',
            label: 'Apple',
        },
        {
            value: 'banana',
            label: 'Banana',
            disabled: true,
        },
        {
            value: 'cherry',
            label: 'Cherry',
        },
    ]}
    defaultValue={[ disabledOptionItems[ 0 ] ]} />;
Incomplete snippet: `...Default.args`, `disabledOptionItems` could not be resolved statically.
Creatable incomplete example
Mark a creatable action with `creatable: true` on an item in `items`. It renders in the list footer, not the main list, when it is in the filtered items. Handle the creation of the item in `onValueChange`.
const Creatable = function Template( args ) {
    const {
        items = ITEMS,
        value: initialValue = [ ITEMS[ 0 ], ITEMS[ 1 ] ],
        ...restArgs
    } = args;
    const [ inputValue, setInputValue ] = useState( '' );
    const [ value, setValue ] = useState( initialValue );
    const creatableItem = {
        value: '__create__',
        label:
            'Create new item' + ( inputValue ? `: ${ inputValue }` : '' ),
        creatable: true,
    };

    return (
        <SearchableChipSelectControl
            { ...restArgs }
            items={ [ ...( items as FixtureItem[] ), creatableItem ] }
            inputValue={ inputValue }
            onInputValueChange={ setInputValue }
            value={ value }
            onValueChange={ ( values, event ) => {
                if (
                    values.some(
                        ( item ) => item.value === creatableItem.value
                    )
                ) {
                    // eslint-disable-next-line no-alert
                    alert( `Create new item: '${ inputValue }'` );
                    setValue(
                        values.filter(
                            ( item ) => item.value !== creatableItem.value
                        )
                    );
                } else {
                    setValue( values );
                }
                args.onValueChange?.( values, event );
            } }
        />
    );
};
Incomplete snippet: `...Default.args` could not be resolved statically.
With Custom Chips And Items incomplete example
const WithCustomChipsAndItems = () => <SearchableChipSelectControl />;
Incomplete snippet: `...SearchableChipSelectStories.WithCustomChipsAndItems`, `...Default.args`, `...SearchableChipSelectStories.WithCustomChipsAndItems.args` could not be resolved statically.
With Custom Empty Content incomplete example
const WithCustomEmptyContent = () => <SearchableChipSelectControl />;
Incomplete snippet: `...SearchableChipSelectStories.WithCustomEmptyContent`, `...Default.args`, `...SearchableChipSelectStories.WithCustomEmptyContent.args` could not be resolved statically.
Async Items story ok
Loads the item list asynchronously. `statusContent` shows loading, then a visually hidden result count. Pass `emptyContent={ null }` while loading so Empty does not claim there are no results.
const AsyncItems = () => {
    const [ loading, setLoading ] = useState( false );
    const [ items, setItems ] = useState< typeof ITEMS >( [] );
    const timeoutRef = useRef< ReturnType< typeof setTimeout > >( null );

    return (
        <SearchableChipSelectControl
            label="Label"
            description="This is a description."
            items={ items }
            statusContent={
                loading ? (
                    <Stack direction="row" gap="sm" align="center">
                        <Spinner />
                        Loading…
                    </Stack>
                ) : (
                    <HiddenResultCount />
                )
            }
            emptyContent={ loading ? null : undefined }
            onOpenChange={ ( open ) => {
                if ( timeoutRef.current ) {
                    clearTimeout( timeoutRef.current );
                }
                if ( ! open ) {
                    return;
                }
                setLoading( true );
                setItems( [] );
                timeoutRef.current = setTimeout( () => {
                    setItems( ITEMS );
                    setLoading( false );
                }, 500 );
            } } />
    );
};
Without Clear Button incomplete example
const WithoutClearButton = () => <SearchableChipSelectControl />;
Incomplete snippet: `...SearchableChipSelectStories.WithoutClearButton`, `...Default.args`, `...SearchableChipSelectStories.WithoutClearButton.args` could not be resolved statically.
Grouped incomplete example
Options can be organized into labeled groups with `SearchableChipSelectControl.Group`, `SearchableChipSelectControl.GroupLabel`, and `SearchableChipSelectControl.Collection`. Pass an array of groups to `items` (each with `label` and `items` properties), and use `children` to render each group.
const Grouped = () => <SearchableChipSelectControl
    defaultValue={[
        GROUPED_ITEMS[ 0 ].items[ 0 ],
        GROUPED_ITEMS[ 1 ].items[ 0 ],
    ]}
    label="Fruit"
    description="Choose your favorite fruits." />;
Incomplete snippet: `...SearchableChipSelectStories.Grouped`, `...SearchableChipSelectStories.Grouped.args` could not be resolved statically.
With Separator incomplete example
Use `SearchableChipSelectControl.Separator` to set choices apart from each other.
const WithSeparator = () => <SearchableChipSelectControl label="Fruit" description="Choose your favorite fruits." />;
Incomplete snippet: `...SearchableChipSelectStories.WithSeparator`, `...SearchableChipSelectStories.WithSeparator.args` could not be resolved statically.
Grouped Creatable incomplete example
Grouped items with a creatable footer item. Include the creatable item in `items` as a creatable-only group. Handle the creation of the item in `onValueChange`.
const GroupedCreatable = args => {
    const [ inputValue, setInputValue ] = useState( '' );
    const [ value, setValue ] = useState< FixtureItem[] >( [
        GROUPED_ITEMS[ 0 ].items[ 0 ],
        GROUPED_ITEMS[ 1 ].items[ 0 ],
    ] );
    const creatableItem = {
        value: '__create__',
        label:
            'Create new item' + ( inputValue ? `: ${ inputValue }` : '' ),
        creatable: true,
    };
    const items = [
        ...GROUPED_ITEMS,
        { label: '', items: [ creatableItem ] },
    ];

    return (
        <SearchableChipSelectControl
            label="Fruit"
            description="Choose your favorite fruits."
            items={ items }
            inputValue={ inputValue }
            onInputValueChange={ setInputValue }
            value={ value }
            onValueChange={ ( values: FixtureItem[], event ) => {
                if (
                    values.some(
                        ( item ) => item.value === creatableItem.value
                    )
                ) {
                    // eslint-disable-next-line no-alert
                    alert( `Create new item: '${ inputValue }'` );
                    setValue(
                        values.filter(
                            ( item ) => item.value !== creatableItem.value
                        )
                    );
                } else {
                    setValue( values );
                }
                args.onValueChange?.( values, event );
            } }
            children={ ( group: FixtureGroup ) => (
                <SearchableChipSelectControl.Group
                    key={ group.label }
                    items={ group.items }
                >
                    <SearchableChipSelectControl.GroupLabel>
                        { group.label }
                    </SearchableChipSelectControl.GroupLabel>
                    <SearchableChipSelectControl.Collection>
                        { ( item: FixtureItem ) => (
                            <SearchableChipSelectControl.Item
                                key={ item.value }
                                value={ item }
                            >
                                <SearchableChipSelectControl.ItemLabel>
                                    { item.label }
                                </SearchableChipSelectControl.ItemLabel>
                            </SearchableChipSelectControl.Item>
                        ) }
                    </SearchableChipSelectControl.Collection>
                </SearchableChipSelectControl.Group>
            ) } />
    );
};
Incomplete snippet: `...Default.args` could not be resolved statically.
Popup Width incomplete example
Use `popupWidth` to control how the popup width is constrained relative to its anchor. This example uses `sm`, allowing the popup to extend beyond the narrow anchor width.
const PopupWidth = function Template( args ) {
    const {
        items = ITEMS,
        value: initialValue = [ ITEMS[ 0 ], ITEMS[ 1 ] ],
        ...restArgs
    } = args;
    const [ inputValue, setInputValue ] = useState( '' );
    const [ value, setValue ] = useState( initialValue );
    const creatableItem = {
        value: '__create__',
        label:
            'Create new item' + ( inputValue ? `: ${ inputValue }` : '' ),
        creatable: true,
    };

    return (
        <SearchableChipSelectControl
            { ...restArgs }
            items={ [ ...( items as FixtureItem[] ), creatableItem ] }
            inputValue={ inputValue }
            onInputValueChange={ setInputValue }
            value={ value }
            onValueChange={ ( values, event ) => {
                if (
                    values.some(
                        ( item ) => item.value === creatableItem.value
                    )
                ) {
                    // eslint-disable-next-line no-alert
                    alert( `Create new item: '${ inputValue }'` );
                    setValue(
                        values.filter(
                            ( item ) => item.value !== creatableItem.value
                        )
                    );
                } else {
                    setValue( values );
                }
                args.onValueChange?.( values, event );
            } }
        />
    );
};
Incomplete snippet: `...Creatable.args` could not be resolved statically.
SearchableChipSelectControl.Group 5 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/searchable-chip-select-control/index.ts
Groups related items together with an associated label rendered by `Combobox.GroupLabel`. When `items` is provided, child `Combobox.Collection` components iterate over them.
import { SearchableChipSelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/searchable-chip-select-control/index.ts::SearchableChipSelectControl (react-component-meta)
children?: ReactNode

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

/**
 * Items to be rendered within this group.
 * When provided, child `Collection` components will use these items.
 */
items?: readonly any[]

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SearchableChipSelectControl.GroupLabel 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/searchable-chip-select-control/index.ts
Renders a label for a `Combobox.Group`, describing the group of items it is associated with.
import { SearchableChipSelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/searchable-chip-select-control/index.ts::SearchableChipSelectControl (react-component-meta)
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SearchableChipSelectControl.Separator 3 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/searchable-chip-select-control/index.ts
Renders a visual separator between combobox items or groups.
import { SearchableChipSelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/searchable-chip-select-control/index.ts::SearchableChipSelectControl (react-component-meta)
/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SearchableChipSelectControl.Item 10 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/searchable-chip-select-control/index.ts
import { SearchableChipSelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/searchable-chip-select-control/index.ts::SearchableChipSelectControl (react-component-meta)
/**
 * One direct ItemLabel, followed by zero or more ItemDescription components.
 */
children: ComboboxItemChildren

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

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

/**
 * The index of the item in the list. Improves performance when specified by avoiding the need to calculate the index automatically from the DOM.
 */
index?: number

/**
 * Whether the component renders a native `<button>` element when replacing it
 * via the `render` prop.
 * Set to `true` if the rendered element is a native button.
 */
nativeButton?: boolean = false

/**
 * An optional click handler for the item when selected.
 * It fires when clicking the item with the pointer, as well as when pressing `Enter` with the keyboard if the item is highlighted when the `Input` or `List` element has focus.
 */
onClick?: (event: BaseUIEvent<MouseEvent<HTMLDivElement, MouseEvent>>) => void

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * A unique value that identifies this item.
 */
value?: any = null

/**
 * The variant of the item.
 * 
 * - `'default'`: A standard item.
 * - `'creatable'`: An item that triggers the creation of a new item.
 */
variant?: "default" | "creatable" = 'default'
SearchableChipSelectControl.ItemLabel 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/searchable-chip-select-control/index.ts
The primary label of a combobox item. Use it as the first direct child of every item. Its content is the item's accessible name. The selected value still uses the item's `label` or the content of `Combobox.Value`.
import { SearchableChipSelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/searchable-chip-select-control/index.ts::SearchableChipSelectControl (react-component-meta)
/**
 * The primary label and accessible name of a combobox item.
 */
children: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SearchableChipSelectControl.ItemDescription 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/searchable-chip-select-control/index.ts
Supplementary content for a combobox item. Its text contributes to the item's accessible description. Use it as a direct child after `Combobox.ItemLabel`. Content should be text or non-interactive inline markup.
import { SearchableChipSelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/searchable-chip-select-control/index.ts::SearchableChipSelectControl (react-component-meta)
/**
 * Content that contributes to the combobox item's accessible description.
 */
children: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SearchableChipSelectControl.ChipWithRemove 6 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/searchable-chip-select-control/index.ts
A utility component that combines a chip and a remove button, with standard styling.
import { SearchableChipSelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/searchable-chip-select-control/index.ts::SearchableChipSelectControl (react-component-meta)
children?: ReactNode

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

/**
 * Circular element to render before the chip content.
 */
prefix?: ReactNode

/**
 * Accessible label for the remove button.
 * Keep this to the action (for example `Remove`). The chip label describes
 * the button.
 */
removeLabel?: string = __( 'Remove' )

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SearchableChipSelectControl.Collection 1 prop type
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/searchable-chip-select-control/index.ts
import { SearchableChipSelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/searchable-chip-select-control/index.ts::SearchableChipSelectControl (react-component-meta)
children: (item: any, index: number) => ReactNode

SearchableSelectControl

design-system-components-form-searchableselectcontrol · ../packages/ui/src/form/searchable-select-control/stories/index.story.tsx
A complete searchable select field with integrated label and description.
Prop types (react-component-meta) 52 prop types
Component: ../packages/ui/src/form/searchable-select-control/index.ts::SearchableSelectControl
Props:
/**
 * A ref to imperative actions.
 * - `unmount`: Ends the closing phase of the combobox after an externally controlled closing animation finishes.
 * Call `preventUnmountOnClose()` in `onOpenChange` first, otherwise the combobox completes closing on its own.
 * Whether it leaves the DOM is decided by `keepMounted` on the portal.
 * - `close`: Closes the combobox imperatively when called.
 */
actionsRef?: RefObject<Actions | null>

/**
 * Identifies the element (or elements) that describes the object.
 */
aria-describedby?: string

/**
 * Defines a string value that labels the current element.
 */
aria-label?: string

/**
 * Identifies the element (or elements) that labels the current element.
 */
aria-labelledby?: string

/**
 * Provides a hint to the browser for autofill.
 */
autoComplete?: string

/**
 * Whether the first matching item is highlighted automatically while filtering.
 */
autoHighlight?: boolean = false

/**
 * A render function for custom rendering the list of matching items.
 * Required when `items` contains groups.
 */
children?: (item: any, index: number) => ReactNode

/**
 * CSS class to apply.
 */
className?: string

/**
 * The uncontrolled input value when initially rendered.
 * 
 * To render a controlled input, use the `inputValue` prop instead.
 */
defaultInputValue?: string | number | readonly string[] | undefined

/**
 * Whether the popup is initially open.
 * 
 * To render a controlled popup, use the `open` prop instead.
 */
defaultOpen?: boolean = false

/**
 * The uncontrolled selected value of the combobox when it's initially rendered.
 * 
 * To render a controlled combobox, use the `value` prop instead.
 */
defaultValue?: Item | null | undefined

/**
 * The accessible description, associated using `aria-describedby`.
 * 
 * For screen reader accessibility, this should only contain plain text,
 * and no semantics such as links.
 */
description?: string

/**
 * 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?: ReactNode

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

/**
 * The custom content to use instead of the default empty state,
 * which shows whenever there are no matching items.
 */
emptyContent?: ReactNode

/**
 * Filter function used to match items vs input query.
 * Receives the source item, which is the derived value's item when `items` is a `createItems()`
 * collection, and the item itself otherwise.
 */
filter?: ((item: Item, query: string, itemToString?: ((item: Item) => string) | undefined) => boolean) | null | undefined

/**
 * Filtered items to display in the list.
 * When provided, the list uses these items instead of filtering the `items` prop internally.
 * When `items` is also provided, this array must preserve its flat or grouped structure.
 * With a `createItems()` collection, pass source items rather than derived values.
 * Nullish entries are not supported, as in `items`.
 * Use when you want to control filtering logic externally with the `useFilter()` hook.
 */
filteredItems?: readonly Item[] | readonly Group<Item>[] | undefined

/**
 * Identifies the form that owns the internal input.
 * Useful when the combobox is rendered outside the form.
 */
form?: string

/**
 * Whether to visually hide the label while keeping it accessible
 * to screen readers.
 */
hideLabelFromVision?: boolean = false

/**
 * Whether moving the pointer over items should highlight them.
 * Disabling this prop allows CSS `:hover` to be differentiated from the `:focus` (`data-highlighted`) state.
 */
highlightItemOnHover?: boolean = true

/**
 * The id of the component.
 */
id?: string

/**
 * Whether the list is rendered inline without using the component's own popup.
 * 
 * Specify `open` unconditionally in conjunction with this prop so the list is considered
 * visible: `<Combobox.Root inline open>`
 * 
 * In a `Combobox.Root` > `Dialog.Root` composition, bind the Combobox's `open` and
 * `onOpenChange` props to the `Dialog`'s `open` and `onOpenChange` state instead so the
 * component resets its transient state (filter query, highlighted item, and input value) when
 * the dialog closes.
 */
inline?: boolean = false

/**
 * A ref to the hidden input element.
 */
inputRef?: Ref<HTMLInputElement> | undefined

/**
 * The input value of the combobox. Use when controlled.
 */
inputValue?: string | number | readonly string[] | undefined

/**
 * Custom comparison logic used to determine if a combobox item value matches the current selected value. Useful when item values are objects without matching referentially.
 * With a `createItems()` collection, both arguments are derived values.
 * Defaults to `Object.is` comparison.
 */
isItemEqualToValue?: (itemValue: Item, value: Item) => boolean

/**
 * The array of option items.
 * 
 * When using grouped `children`, pass an array of groups instead of a
 * flat list of items. Grouped items require a custom `children` renderer.
 * 
 * Mark a creatable action with `creatable: true`. It renders in the
 * list footer, not the main list, when it is in the filtered items.
 * Handle the creation of the item in `onValueChange`.
 */
items?: Item[] | ItemGroup[] | undefined

/**
 * When the item values are objects (`<Combobox.Item value={object}>`), this function converts the object value to a string representation for display in the input.
 * If the shape of the object is `{ value, label }`, the label will be used automatically without needing to specify this prop.
 * With a `createItems()` collection, this receives the derived value, and the collection's
 * `getLabel` takes precedence for values it can resolve.
 */
itemToStringLabel?: (itemValue: Item) => string

/**
 * When the item values are objects (`<Combobox.Item value={object}>`), this function converts the object value to a string representation for form submission.
 * If the shape of the object is `{ value, label }`, the value will be used automatically without needing to specify this prop.
 * With a `createItems()` collection, this receives the derived value.
 */
itemToStringValue?: (itemValue: Item) => string

key?: Key | null | undefined

/**
 * The accessible label. All controls must be labeled.
 */
label: string

/**
 * The maximum number of items to display in the list.
 */
limit?: number = -1

/**
 * The locale to use for string comparison.
 * Defaults to the user's runtime locale.
 */
locale?: LocalesArgument

/**
 * Whether to loop keyboard focus back to the input when the end of the list is reached while using the arrow keys. The first item can then be reached by pressing <kbd>ArrowDown</kbd> again from the input, or the last item can be reached by pressing <kbd>ArrowUp</kbd> from the input.
 * The input is always included in the focus loop per [ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/).
 * When disabled, focus does not move when on the last element and the user presses <kbd>ArrowDown</kbd>, or when on the first element and the user presses <kbd>ArrowUp</kbd>.
 */
loopFocus?: boolean = true

/**
 * Determines if the popup enters a modal state when open.
 * - `true`: user interaction is limited to the popup: document page scroll is locked and pointer interactions on outside elements are disabled.
 * - `false`: user interaction with the rest of the document is allowed.
 * 
 * On touch devices, a `true` modal blocks outside taps but leaves the page scrollable unless the popup spans nearly the full viewport width, matching native iOS behavior.
 */
modal?: boolean = false

/**
 * Identifies the field when a form is submitted.
 */
name?: string

/**
 * Event handler called when the input value changes.
 */
onInputValueChange?: (inputValue: string, eventDetails: ChangeEventDetails) => void

/**
 * Callback fired when an item is highlighted or unhighlighted.
 * Receives the highlighted item value (or `undefined` if no item is highlighted) and event details with a `reason` property describing why the highlight changed.
 * The `reason` can be:
 * - `'keyboard'`: the highlight changed due to keyboard navigation.
 * - `'pointer'`: the highlight changed due to pointer hovering. The event may be a `MouseEvent`
 *   rather than a `PointerEvent`.
 * - `'none'`: the highlight changed for another reason, such as typing, `autoHighlight`, the
 *   item list changing, or the popup opening or closing.
 */
onItemHighlighted?: (highlightedValue: Item | undefined, eventDetails: HighlightEventDetails) => void

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

/**
 * Event handler called after any animations complete when the popup is opened or closed.
 */
onOpenChangeComplete?: (open: boolean) => void

/**
 * Event handler called when the selected value of the combobox changes.
 */
onValueChange?: (value: Item | null, eventDetails: ChangeEventDetails) => void

/**
 * Whether the popup is currently open. Use when controlled.
 */
open?: boolean

/**
 * Whether the popup opens when clicking the input.
 */
openOnInputClick?: boolean = true

/**
 * Text to show when no value is selected. This is overridden by `triggerContent`
 * if specified, or by a null item's label in `items`.
 */
placeholder?: ReactNode = __( 'Select' )

/**
 * Controls how the popup width is constrained relative to its anchor.
 * 
 * For all presets, the popup is never narrower than its anchor.
 * 
 * - `'anchor'`: Fixed width matching the anchor width.
 * - `'content'`: Width grows with item labels between the anchor and available
 *   viewport bounds.
 * - `'sm'`: Fixed width at the small surface width token (`--wpds-dimension-surface-width-sm`).
 * - `'md'`: Fixed width at the medium surface width token (`--wpds-dimension-surface-width-md`).
 * - `'lg'`: Fixed width at the large surface width token (`--wpds-dimension-surface-width-lg`).
 * - `'available'`: Fixed width at the available viewport width (`--available-width`).
 */
popupWidth?: "anchor" | "content" | "sm" | "md" | "lg" | "available" = 'anchor'

/**
 * Whether the user should be unable to choose a different option from the popup.
 */
readOnly?: boolean = false

/**
 * Allows getting a ref to the component instance.
 * Once the component unmounts, React will set `ref.current` to `null`
 * (or call the ref with `null` if you passed a callback ref).
 */
ref?: Ref<HTMLButtonElement> | undefined

/**
 * Whether the user must choose a value before submitting a form.
 */
required?: boolean = false

/**
 * The placeholder text to use for the search input.
 */
searchPlaceholder?: string

/**
 * Content for the list status live region. The region stays mounted.
 */
statusContent?: ReactNode

/**
 * The custom trigger content to use instead of the default.
 * 
 * The callback receives `null` when nothing is selected.
 * 
 * ```jsx
 * triggerContent={ ( value ) =>
 *   value ? (
 *     <span>
 *       <Icon icon={ wordpress } />
 *       { value.label }
 *     </span>
 *   ) : null
 * }
 * ```
 */
triggerContent?: ReactNode | ((value: Item | null) => ReactNode)

/**
 * The selected value of the combobox. Use when controlled.
 */
value?: Item | null | undefined

/**
 * Whether the items are being externally virtualized.
 */
virtualized?: boolean = false
Imports
import { SearchableSelectControl, Spinner, Stack, VisuallyHidden } from '@wordpress/ui';
import { DETAILS_EXAMPLE, longLabelPopupItems } from '../../stories/shared';
import { ITEMS } from '../../primitives/searchable-select/stories/fixtures';
import { GROUPED_ITEMS } from '../../primitives/combobox/stories/fixtures';
Default incomplete example
const Default = () => <SearchableSelectControl label="Label" description="This is a description." />;
Incomplete snippet: `...SearchableSelectStories.Default`, `...SearchableSelectStories.Default.args` could not be resolved statically.
With Item Descriptions incomplete example
const WithItemDescriptions = () => <SearchableSelectControl
    aria-label="Fruit"
    items={[
        { value: 'apple', label: 'Apple', description: 'A crisp fruit.' },
        { value: 'banana', label: 'Banana', description: 'A soft fruit.' },
    ]}
    label="Fruit" />;
Incomplete snippet: `...SearchableSelectStories.WithItemDescriptions` could not be resolved statically.
With Custom Placeholder incomplete example
When no value is selected, the trigger shows the default placeholder text. Use the `placeholder` prop to customize text shown. Prefer a concise label without a trailing ellipsis.
const WithCustomPlaceholder = () => <SearchableSelectControl label="Label" description="This is a description." />;
Incomplete snippet: `...SearchableSelectStories.WithCustomPlaceholder`, `...SearchableSelectStories.WithCustomPlaceholder.args` could not be resolved statically.
Visually Hidden Label incomplete example
const VisuallyHiddenLabel = () => <SearchableSelectControl hideLabelFromVision />;
Incomplete snippet: `...Default.args` could not be resolved statically.
With Details incomplete example
const WithDetails = () => <SearchableSelectControl description={undefined} details={DETAILS_EXAMPLE} />;
Incomplete snippet: `...Default.args` could not be resolved statically.
With Custom Search Placeholder incomplete example
Use the `searchPlaceholder` prop to customize the search input placeholder text. Prefer a concise label without a trailing ellipsis.
const WithCustomSearchPlaceholder = () => <SearchableSelectControl searchPlaceholder="Search fruit" />;
Incomplete snippet: `...Default.args` could not be resolved statically.
With Disabled Option incomplete example
const WithDisabledOption = () => <SearchableSelectControl
    items={[
        {
            value: 'apple',
            label: 'Apple',
        },
        {
            value: 'banana',
            label: 'Banana',
            disabled: true,
        },
        {
            value: 'cherry',
            label: 'Cherry',
        },
    ]}
    defaultValue={disabledOptionItems[ 0 ]} />;
Incomplete snippet: `...Default.args`, `disabledOptionItems` could not be resolved statically.
Creatable incomplete example
Mark a creatable action with `creatable: true` on an item in `items`. It renders in the list footer, not the main list, when it is in the filtered items. Handle the creation of the item in `onValueChange`.
const Creatable = function Template( args ) {
    const { items = ITEMS, ...restArgs } = args;
    const [ inputValue, setInputValue ] = useState( '' );
    const [ value, setValue ] = useState<
        React.ComponentProps< typeof SearchableSelectControl >[ 'value' ]
    >( ITEMS[ 0 ] );
    const creatableItem = {
        value: '__create__',
        label:
            'Create new item' + ( inputValue ? `: ${ inputValue }` : '' ),
        creatable: true,
    };

    return (
        <SearchableSelectControl
            { ...restArgs }
            items={ [ ...( items as FixtureItem[] ), creatableItem ] }
            inputValue={ inputValue }
            onInputValueChange={ setInputValue }
            value={ value }
            onValueChange={ ( newValue, event ) => {
                if ( ! newValue ) {
                    return;
                }

                if ( newValue.value === creatableItem.value ) {
                    // eslint-disable-next-line no-alert
                    alert( `Create new item: '${ inputValue }'` );
                } else {
                    setValue( newValue );
                }
                args.onValueChange?.( newValue, event );
            } }
        />
    );
};
Incomplete snippet: `...Default.args` could not be resolved statically.
With Custom Trigger And Items incomplete example
const WithCustomTriggerAndItems = () => <SearchableSelectControl />;
Incomplete snippet: `...SearchableSelectStories.WithCustomTriggerAndItems`, `...Default.args`, `...SearchableSelectStories.WithCustomTriggerAndItems.args` could not be resolved statically.
With Custom Empty Content incomplete example
const WithCustomEmptyContent = () => <SearchableSelectControl />;
Incomplete snippet: `...SearchableSelectStories.WithCustomEmptyContent`, `...Default.args`, `...SearchableSelectStories.WithCustomEmptyContent.args` could not be resolved statically.
Async Items story ok
Loads the item list asynchronously. `statusContent` shows loading, then a visually hidden result count. Pass `emptyContent={ null }` while loading so Empty does not claim there are no results.
const AsyncItems = () => {
    const [ loading, setLoading ] = useState( false );
    const [ items, setItems ] = useState< typeof ITEMS >( [] );
    const timeoutRef = useRef< ReturnType< typeof setTimeout > >( null );

    return (
        <SearchableSelectControl
            label="Label"
            description="This is a description."
            items={ items }
            statusContent={
                loading ? (
                    <Stack direction="row" gap="sm" align="center">
                        <Spinner />
                        Loading…
                    </Stack>
                ) : (
                    <HiddenResultCount />
                )
            }
            emptyContent={ loading ? null : undefined }
            onOpenChange={ ( open ) => {
                if ( timeoutRef.current ) {
                    clearTimeout( timeoutRef.current );
                }
                if ( ! open ) {
                    return;
                }
                setLoading( true );
                setItems( [] );
                timeoutRef.current = setTimeout( () => {
                    setItems( ITEMS );
                    setLoading( false );
                }, 500 );
            } } />
    );
};
Grouped incomplete example
Options can be organized into labeled groups with `SearchableSelectControl.Group`, `SearchableSelectControl.GroupLabel`, and `SearchableSelectControl.Collection`. Pass an array of groups to `items` (each with `label` and `items` properties), and use `children` to render each group.
const Grouped = () => <SearchableSelectControl
    defaultValue={GROUPED_ITEMS[ 0 ].items[ 0 ]}
    label="Fruit"
    description="Choose your favorite fruit." />;
Incomplete snippet: `...SearchableSelectStories.Grouped`, `...SearchableSelectStories.Grouped.args` could not be resolved statically.
With Separator incomplete example
Use `SearchableSelectControl.Separator` to set choices apart from each other.
const WithSeparator = () => <SearchableSelectControl
    defaultValue={ITEMS[ 0 ]}
    label="Fruit"
    description="Choose your favorite fruit." />;
Incomplete snippet: `...SearchableSelectStories.WithSeparator`, `...SearchableSelectStories.WithSeparator.args` could not be resolved statically.
Grouped Creatable incomplete example
Grouped items with a creatable footer item. Include the creatable item in `items` as a creatable-only group. Handle the creation of the item in `onValueChange`.
const GroupedCreatable = args => {
    const [ inputValue, setInputValue ] = useState( '' );
    const [ value, setValue ] = useState< FixtureItem >(
        GROUPED_ITEMS[ 0 ].items[ 0 ]
    );
    const creatableItem = {
        value: '__create__',
        label:
            'Create new item' + ( inputValue ? `: ${ inputValue }` : '' ),
        creatable: true,
    };
    const items = [
        ...GROUPED_ITEMS,
        { label: '', items: [ creatableItem ] },
    ];

    return (
        <SearchableSelectControl
            label="Fruit"
            description="Choose your favorite fruit."
            items={ items }
            inputValue={ inputValue }
            onInputValueChange={ setInputValue }
            value={ value }
            onValueChange={ ( newValue: FixtureItem | null, event ) => {
                if ( ! newValue ) {
                    return;
                }

                if ( newValue.value === creatableItem.value ) {
                    // eslint-disable-next-line no-alert
                    alert( `Create new item: '${ inputValue }'` );
                } else {
                    setValue( newValue );
                }
                args.onValueChange?.( newValue, event );
            } }
            children={ ( group: FixtureGroup ) => (
                <SearchableSelectControl.Group
                    key={ group.label }
                    items={ group.items }
                >
                    <SearchableSelectControl.GroupLabel>
                        { group.label }
                    </SearchableSelectControl.GroupLabel>
                    <SearchableSelectControl.Collection>
                        { ( item: FixtureItem ) => (
                            <SearchableSelectControl.Item
                                key={ item.value }
                                value={ item }
                            >
                                <SearchableSelectControl.ItemLabel>
                                    { item.label }
                                </SearchableSelectControl.ItemLabel>
                            </SearchableSelectControl.Item>
                        ) }
                    </SearchableSelectControl.Collection>
                </SearchableSelectControl.Group>
            ) } />
    );
};
Incomplete snippet: `...Default.args` could not be resolved statically.
Popup Width incomplete example
Use `popupWidth` to control how the popup width is constrained relative to its anchor. This example uses `sm`, allowing the popup to extend beyond the narrow anchor width.
const PopupWidth = function Template( args ) {
    const { items = ITEMS, ...restArgs } = args;
    const [ inputValue, setInputValue ] = useState( '' );
    const [ value, setValue ] = useState<
        React.ComponentProps< typeof SearchableSelectControl >[ 'value' ]
    >( ITEMS[ 0 ] );
    const creatableItem = {
        value: '__create__',
        label:
            'Create new item' + ( inputValue ? `: ${ inputValue }` : '' ),
        creatable: true,
    };

    return (
        <SearchableSelectControl
            { ...restArgs }
            items={ [ ...( items as FixtureItem[] ), creatableItem ] }
            inputValue={ inputValue }
            onInputValueChange={ setInputValue }
            value={ value }
            onValueChange={ ( newValue, event ) => {
                if ( ! newValue ) {
                    return;
                }

                if ( newValue.value === creatableItem.value ) {
                    // eslint-disable-next-line no-alert
                    alert( `Create new item: '${ inputValue }'` );
                } else {
                    setValue( newValue );
                }
                args.onValueChange?.( newValue, event );
            } }
        />
    );
};
Incomplete snippet: `...Creatable.args` could not be resolved statically.
SearchableSelectControl.Group 5 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/searchable-select-control/index.ts
Groups related items together with an associated label rendered by `Combobox.GroupLabel`. When `items` is provided, child `Combobox.Collection` components iterate over them.
import { SearchableSelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/searchable-select-control/index.ts::SearchableSelectControl (react-component-meta)
children?: ReactNode

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

/**
 * Items to be rendered within this group.
 * When provided, child `Collection` components will use these items.
 */
items?: readonly any[]

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SearchableSelectControl.GroupLabel 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/searchable-select-control/index.ts
Renders a label for a `Combobox.Group`, describing the group of items it is associated with.
import { SearchableSelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/searchable-select-control/index.ts::SearchableSelectControl (react-component-meta)
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SearchableSelectControl.Separator 3 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/searchable-select-control/index.ts
Renders a visual separator between combobox items or groups.
import { SearchableSelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/searchable-select-control/index.ts::SearchableSelectControl (react-component-meta)
/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SearchableSelectControl.Item 10 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/searchable-select-control/index.ts
import { SearchableSelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/searchable-select-control/index.ts::SearchableSelectControl (react-component-meta)
/**
 * One direct ItemLabel, followed by zero or more ItemDescription components.
 */
children: ComboboxItemChildren

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

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

/**
 * The index of the item in the list. Improves performance when specified by avoiding the need to calculate the index automatically from the DOM.
 */
index?: number

/**
 * Whether the component renders a native `<button>` element when replacing it
 * via the `render` prop.
 * Set to `true` if the rendered element is a native button.
 */
nativeButton?: boolean = false

/**
 * An optional click handler for the item when selected.
 * It fires when clicking the item with the pointer, as well as when pressing `Enter` with the keyboard if the item is highlighted when the `Input` or `List` element has focus.
 */
onClick?: (event: BaseUIEvent<MouseEvent<HTMLDivElement, MouseEvent>>) => void

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The option item this list item represents.
 */
value: Item

/**
 * The variant of the item.
 * 
 * - `'default'`: A standard item.
 * - `'creatable'`: An item that triggers the creation of a new item.
 */
variant?: "default" | "creatable" = 'default'
SearchableSelectControl.ItemLabel 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/searchable-select-control/index.ts
The primary label of a combobox item. Use it as the first direct child of every item. Its content is the item's accessible name. The selected value still uses the item's `label` or the content of `Combobox.Value`.
import { SearchableSelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/searchable-select-control/index.ts::SearchableSelectControl (react-component-meta)
/**
 * The primary label and accessible name of a combobox item.
 */
children: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SearchableSelectControl.ItemDescription 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/searchable-select-control/index.ts
Supplementary content for a combobox item. Its text contributes to the item's accessible description. Use it as a direct child after `Combobox.ItemLabel`. Content should be text or non-interactive inline markup.
import { SearchableSelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/searchable-select-control/index.ts::SearchableSelectControl (react-component-meta)
/**
 * Content that contributes to the combobox item's accessible description.
 */
children: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SearchableSelectControl.Collection 1 prop type
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/searchable-select-control/index.ts
import { SearchableSelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/searchable-select-control/index.ts::SearchableSelectControl (react-component-meta)
children: (item: any, index: number) => ReactNode

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 (react-component-meta) 13 prop types
Component: ../packages/components/src/search-control/index.tsx::default
Props:
__next40pxDefaultSize?: boolean

/**
 * Start opting into the new margin-free styles that will become the default in a future version.
 */
__nextHasNoMarginBottom?: boolean = false

/**
 * Additional description for the control.
 * 
 * Only use for meaningful description or instructions for the control. An element containing the description will be programmatically associated to the BaseControl by the means of an `aria-describedby` attribute.
 */
help?: ReactNode

/**
 * If true, the label will only be visible to screen readers.
 */
hideLabelFromVision?: boolean = true

/**
 * The accessible label for the input.
 * 
 * A label should always be provided as an accessibility best practice,
 * even when a placeholder is defined and `hideLabelFromVision` is `true`.
 */
label?: string = __( 'Search' )

/**
 * A function that receives the value of the input when the value is changed.
 */
onChange: (value: string) => void

/**
 * When an `onClose` callback is provided, the search control will render a close button
 * that will trigger the given callback.
 * 
 * Use this if you want the button to trigger your own logic to close the search field entirely,
 * rather than just clearing the input value.
 */
onClose?: () => void

onDrag?: (dragProps: Omit<FullGestureState<"drag">, "event"> & { event: unknown; }) => void

onDragEnd?: (dragProps: Omit<FullGestureState<"drag">, "event"> & { event: unknown; }) => void

onDragStart?: (dragProps: Omit<FullGestureState<"drag">, "event"> & { event: unknown; }) => void

/**
 * A placeholder for the input.
 */
placeholder?: string = __( 'Search' )

/**
 * The size of the component
 */
size?: "default" | "compact" = 'default'

/**
 * The current value of the input.
 */
value?: string
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 component that lets users choose one option from a list. Prefer `SelectControl` when using with a standard label and description. When using object values, pass an `items` array so `Select.Trigger` can auto-resolve the selected item's label. By default, items should use a `{ value, label }` shape, or provide `itemToStringLabel` for a custom shape. Object values are compared with `Object.is` by default, so use the same object references for `value` / `defaultValue` and `Select.Item` values, or provide `isItemEqualToValue`.
Prop types (react-component-meta) 23 prop types
Component: ../packages/ui/src/form/primitives/select/index.ts::Root
Props:
/**
 * A ref to imperative actions.
 * - `unmount`: Ends the closing phase of the select after an externally controlled closing animation finishes.
 * Call `preventUnmountOnClose()` in `onOpenChange` first, otherwise the select completes closing on its own.
 * Whether it leaves the DOM is decided by `keepMounted` on the portal.
 * - `close`: Closes the select imperatively when called.
 */
actionsRef?: RefObject<SelectRootActions | null>

/**
 * Provides a hint to the browser for autofill.
 */
autoComplete?: string

children?: ReactNode

/**
 * Whether the select popup is initially open.
 * 
 * To render a controlled select popup, use the `open` prop instead.
 */
defaultOpen?: boolean = false

/**
 * The uncontrolled value of the select when it's initially rendered.
 * 
 * To render a controlled select, use the `value` prop instead.
 */
defaultValue?: unknown

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

/**
 * Identifies the form that owns the hidden input.
 * Useful when the select is rendered outside the form.
 */
form?: string

/**
 * Whether moving the pointer over items should highlight them.
 * Disabling this prop allows CSS `:hover` to be differentiated from the `:focus` (`data-highlighted`) state.
 */
highlightItemOnHover?: boolean = true

/**
 * The id of the Select.
 */
id?: string

/**
 * A ref to access the hidden input element.
 */
inputRef?: Ref<HTMLInputElement> | undefined

/**
 * Custom comparison logic used to determine if a select item value matches the current selected value. Useful when item values are objects without matching referentially.
 * Defaults to `Object.is` comparison.
 */
isItemEqualToValue?: (itemValue: unknown, value: unknown) => boolean

/**
 * Data structure of the items rendered in the select popup.
 * When specified, `<Select.Value>` renders the label of the selected item instead of the raw value.
 */
items?: readonly Group<any>[] | Record<string, ReactNode> | readonly { label: ReactNode; value: any; }[] | undefined

/**
 * When the item values are objects (`<Select.Item value={object}>`), this function converts the object value to a string representation for display in the trigger.
 * If the shape of the object is `{ value, label }`, the label will be used automatically without needing to specify this prop.
 */
itemToStringLabel?: (itemValue: unknown) => string

/**
 * When the item values are objects (`<Select.Item value={object}>`), this function converts the object value to a string representation for form submission.
 * If the shape of the object is `{ value, label }`, the value will be used automatically without needing to specify this prop.
 */
itemToStringValue?: (itemValue: unknown) => string

/**
 * Determines if the select enters a modal state when open.
 * - `true`: user interaction is limited to the select: document page scroll is locked and pointer interactions on outside elements are disabled.
 * - `false`: user interaction with the rest of the document is allowed.
 * 
 * On touch devices, a `true` modal blocks outside taps but leaves the page scrollable unless the popup spans nearly the full viewport width, matching native iOS behavior.
 */
modal?: boolean = true

/**
 * Identifies the field when a form is submitted.
 */
name?: string

/**
 * Event handler called when the select popup is opened or closed.
 */
onOpenChange?: (open: boolean, eventDetails: SelectRootOpenChangeEventDetails) => void

/**
 * Event handler called after any animations complete when the select popup is opened or closed.
 */
onOpenChangeComplete?: (open: boolean) => void

/**
 * Event handler called when the value of the select changes.
 */
onValueChange?: (value: unknown, eventDetails: SelectRootChangeEventDetails) => void

/**
 * Whether the select popup is currently open.
 */
open?: boolean

/**
 * Whether the user should be unable to choose a different option from the select popup.
 */
readOnly?: boolean = false

/**
 * Whether the user must choose a value before submitting a form.
 */
required?: boolean = false

/**
 * The value of the select. Use when controlled.
 */
value?: unknown
Imports
import {
  Group,
  GroupLabel,
  Item,
  ItemDescription,
  ItemLabel,
  Popup,
  Portal,
  Positioner,
  Root,
  Separator,
  Trigger,
} from '@wordpress/ui';
import * as Select from '../';
import { longLabelPopupItems } from '../../../stories/shared';
Default incomplete example
const Default = () => <Select.Root
    items={Array.from( { length: 6 }, ( _, index ) => ( {
        value: `item-${ index + 1 }`,
        label: `Item ${ index + 1 }`,
    } ) )}>{[
        <Select.Trigger aria-label="Item" key="trigger" />,
        <Select.Popup key="popup">
            { defaultItems.map( ( item ) => (
                <Select.Item key={ item.value } value={ item }>
                    <Select.ItemLabel>{ item.label }</Select.ItemLabel>
                </Select.Item>
            ) ) }
        </Select.Popup>,
    ]}</Select.Root>;
Incomplete snippet: `defaultItems` could not be resolved statically.
Compact incomplete example
const Compact = () => <Select.Root
    items={Array.from( { length: 6 }, ( _, index ) => ( {
        value: `item-${ index + 1 }`,
        label: `Item ${ index + 1 }`,
    } ) )}>{[
        <Select.Trigger size="compact" aria-label="Item" key="trigger" />,
        <Select.Popup key="popup">
            { defaultItems.map( ( item ) => (
                <Select.Item key={ item.value } value={ item }>
                    <Select.ItemLabel>{ item.label }</Select.ItemLabel>
                </Select.Item>
            ) ) }
        </Select.Popup>,
    ]}</Select.Root>;
Incomplete snippet: `defaultItems` could not be resolved statically.
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"
            aria-label="Item"
            key="trigger"
        />,
        <Select.Popup width="content" key="popup">
            { Array.from( { length: 6 }, ( _, index ) => (
                <Select.Item
                    key={ index }
                    value={ `${ index + 1 }` }
                    size="small"
                >
                    <Select.ItemLabel>{ `${
                        index + 1
                    }` }</Select.ItemLabel>
                </Select.Item>
            ) ) }
        </Select.Popup>,
    ]}</Select.Root>;
Grouped incomplete example
Options can be organized into labeled groups with `Select.Group` and `Select.GroupLabel`.
const Grouped = () => <Select.Root items={groupedItems.flatMap( ( group ) => group.items )}>{[
        <Select.Trigger aria-label="Item" key="trigger" />,
        <Select.Popup key="popup">
            { groupedItems.map( ( group ) => (
                <Select.Group key={ group.label }>
                    <Select.GroupLabel>{ group.label }</Select.GroupLabel>
                    { group.items.map( ( item ) => (
                        <Select.Item key={ item.value } value={ item }>
                            <Select.ItemLabel>
                                { item.label }
                            </Select.ItemLabel>
                        </Select.Item>
                    ) ) }
                </Select.Group>
            ) ) }
        </Select.Popup>,
    ]}</Select.Root>;
Incomplete snippet: `groupedItems` could not be resolved statically.
With Separator incomplete example
Use `Select.Separator` to set choices apart from each other.
const WithSeparator = () => <Select.Root
    items={[
        { value: 'apple', label: 'Apple' },
        { value: 'banana', label: 'Banana' },
        { value: 'other', label: 'Other' },
    ]}>{[
        <Select.Trigger aria-label="Fruit" key="trigger" />,
        <Select.Popup key="popup">
            { separatorItems.slice( 0, 2 ).map( ( item ) => (
                <Select.Item key={ item.value } value={ item }>
                    <Select.ItemLabel>{ item.label }</Select.ItemLabel>
                </Select.Item>
            ) ) }
            <Select.Separator />
            <Select.Item value={ separatorItems[ 2 ] }>
                <Select.ItemLabel>Other</Select.ItemLabel>
            </Select.Item>
        </Select.Popup>,
    ]}</Select.Root>;
Incomplete snippet: `separatorItems` could not be resolved statically.
With Custom Placeholder incomplete example
Use the `placeholder` prop on `Select.Trigger` to show text when no value is selected. The default placeholder is `"Select"`.
const WithCustomPlaceholder = () => <Select.Root
    items={Array.from( { length: 6 }, ( _, index ) => ( {
        value: `item-${ index + 1 }`,
        label: `Item ${ index + 1 }`,
    } ) )}>{[
        <Select.Trigger
            placeholder="Choose an item"
            aria-label="Item"
            key="trigger"
        />,
        <Select.Popup key="popup">
            { defaultItems.map( ( item ) => (
                <Select.Item key={ item.value } value={ item }>
                    <Select.ItemLabel>{ item.label }</Select.ItemLabel>
                </Select.Item>
            ) ) }
        </Select.Popup>,
    ]}</Select.Root>;
Incomplete snippet: `defaultItems` could not be resolved statically.
With Null Value Option incomplete example
Use a `null` item when users should be able to clear the selected value from the popup. When `items` includes a `null` item, its label is used as the placeholder text.
const WithNullValueOption = () => <Select.Root
    items={[
        { value: null, label: 'Select theme' },
        { value: 'system', label: 'System default' },
        { value: 'light', label: 'Light' },
        { value: 'dark', label: 'Dark' },
    ]}>{[
        <Select.Trigger aria-label="Item" key="trigger" />,
        <Select.Popup key="popup">
            { nullValueOptionItems.map( ( item ) => (
                <Select.Item
                    key={ item.value ?? 'null' }
                    value={ item.value }
                >
                    <Select.ItemLabel>{ item.label }</Select.ItemLabel>
                </Select.Item>
            ) ) }
        </Select.Popup>,
    ]}</Select.Root>;
Incomplete snippet: `nullValueOptionItems` could not be resolved statically.
Labeling incomplete example
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
    items={Array.from( { length: 6 }, ( _, index ) => ( {
        value: `item-${ index + 1 }`,
        label: `Item ${ index + 1 }`,
    } ) )}>{[
        <Select.Trigger aria-label="User role" key="trigger" />,
        <Select.Popup key="popup">
            { defaultItems.map( ( item ) => (
                <Select.Item key={ item.value } value={ item }>
                    <Select.ItemLabel>{ item.label }</Select.ItemLabel>
                </Select.Item>
            ) ) }
        </Select.Popup>,
    ]}</Select.Root>;
Incomplete snippet: `defaultItems` could not be resolved statically.
With Overflow incomplete example
const WithOverflow = () => <Select.Root
    items={[
        {
            value: 'long-item',
            label: longItemValue,
        },
        {
            value: 'item-2',
            label: 'Item 2',
        },
    ]}
    defaultValue={overflowItems[ 0 ]}>{[
        <Select.Trigger aria-label="Item" key="trigger" />,
        <Select.Popup key="popup">
            { overflowItems.map( ( item ) => (
                <Select.Item key={ item.value } value={ item }>
                    <Select.ItemLabel>{ item.label }</Select.ItemLabel>
                </Select.Item>
            ) ) }
        </Select.Popup>,
    ]}</Select.Root>;
Incomplete snippet: `longItemValue`, `overflowItems` could not be resolved statically.
With Long List incomplete example
const WithLongList = () => <Select.Root
    items={Array.from( { length: 30 }, ( _, index ) => ( {
        value: `item-${ index + 1 }`,
        label: `Item ${ index + 1 }`,
    } ) )}
    defaultValue={longListItems[ 17 ]}>{[
        <Select.Trigger aria-label="Item" key="trigger" />,
        <Select.Popup key="popup">
            { longListItems.map( ( item ) => (
                <Select.Item key={ item.value } value={ item }>
                    <Select.ItemLabel>{ item.label }</Select.ItemLabel>
                </Select.Item>
            ) ) }
        </Select.Popup>,
    ]}</Select.Root>;
Incomplete snippet: `longListItems` could not be resolved statically.
Disabled incomplete example
const Disabled = () => <Select.Root
    items={Array.from( { length: 6 }, ( _, index ) => ( {
        value: `item-${ index + 1 }`,
        label: `Item ${ index + 1 }`,
    } ) )}
    defaultValue={defaultItems[ 0 ]}
    disabled>{[
        <Select.Trigger aria-label="Item" key="trigger" />,
        <Select.Popup key="popup">
            { defaultItems.map( ( item ) => (
                <Select.Item key={ item.value } value={ item }>
                    <Select.ItemLabel>{ item.label }</Select.ItemLabel>
                </Select.Item>
            ) ) }
        </Select.Popup>,
    ]}</Select.Root>;
Incomplete snippet: `defaultItems` could not be resolved statically.
With Disabled Item incomplete example
const WithDisabledItem = () => <Select.Root
    items={[
        {
            value: 'item-1',
            label: 'Item 1',
        },
        {
            value: 'item-2',
            label: 'Item 2',
            disabled: true,
        },
    ]}
    defaultValue={disabledItemItems[ 0 ]}>{[
        <Select.Trigger aria-label="Item" key="trigger" />,
        <Select.Popup key="popup">
            { disabledItemItems.map( ( item ) => (
                <Select.Item
                    key={ item.value }
                    value={ item }
                    disabled={ item.disabled }
                >
                    <Select.ItemLabel>{ item.label }</Select.ItemLabel>
                </Select.Item>
            ) ) }
        </Select.Popup>,
    ]}</Select.Root>;
Incomplete snippet: `disabledItemItems` could not be resolved statically.
With Custom Trigger And Item incomplete example
For custom needs, a `Select.Trigger` can take a custom render function as its children. Put custom item content inside `Select.ItemLabel`.
const WithCustomTriggerAndItem = () => <Select.Root
    items={[
        {
            value: 'user-1',
            label: 'User 1 (Admin)',
        },
        {
            value: 'user-2',
            label: 'User 2 (Editor)',
        },
    ]}
    defaultValue={customOptions[ 0 ]}>{[
        <Select.Trigger aria-label="Item" key="trigger">
            { ( item ) => (
                <span
                    style={ {
                        display: 'flex',
                        alignItems: 'center',
                        gap: 8,
                    } }
                >
                    <img
                        src={ `https://gravatar.com/avatar/?d=initials&name=${ item.value }` }
                        alt=""
                        width="20"
                        style={ {
                            borderRadius: '50%',
                        } }
                    />

                    { item.label }
                </span>
            ) }
        </Select.Trigger>,
        <Select.Popup key="popup">
            { customOptions.map( ( item ) => (
                <Select.Item key={ item.value } value={ item }>
                    <Select.ItemLabel>{ item.label }</Select.ItemLabel>
                </Select.Item>
            ) ) }
        </Select.Popup>,
    ]}</Select.Root>;
Incomplete snippet: `customOptions` could not be resolved statically.
With Item Description incomplete example
Use `Select.ItemDescription` for supplementary text that should be announced as a description rather than part of the item name.
const WithItemDescription = () => <Select.Root
    items={[
        {
            value: 'apple',
            label: 'Apple',
            description: '99 in stock. Ships in two to three business days.',
        },
        {
            value: 'banana',
            label: 'Banana',
            description: '12 in stock. Restock expected next week.',
        },
    ]}>{[
        <Select.Trigger aria-label="Item" key="trigger" />,
        <Select.Popup key="popup">
            { stockItems.map( ( item ) => (
                <Select.Item key={ item.value } value={ item }>
                    <Select.ItemLabel>{ item.label }</Select.ItemLabel>
                    <Select.ItemDescription>
                        { item.description }
                    </Select.ItemDescription>
                </Select.Item>
            ) ) }
        </Select.Popup>,
    ]}</Select.Root>;
Incomplete snippet: `stockItems` could not be resolved statically.
With Custom z-index incomplete example
Popovers in Gutenberg are managed with explicit z-index values, which can create situations where a select popup renders below another popover when you want it above. The `--wp-ui-select-z-index` CSS variable controls the z-index of the `Select` positioner. Override it either: - **Globally**, by setting the variable on `:root` or `body` (raises every `Select` popover in the page), or - **Per instance**, by passing a `Select.Portal` with a `style` (or `className`) to `Select.Popup`'s `portal` prop. The variable cascades from the portal wrapper to everything rendered inside it. This story demonstrates the per-instance approach.
const WithCustomZIndex = () => <Select.Root
    items={Array.from( { length: 6 }, ( _, index ) => ( {
        value: `item-${ index + 1 }`,
        label: `Item ${ index + 1 }`,
    } ) )}>{[
        <Select.Trigger aria-label="Item" key="trigger" />,
        <Select.Popup
            portal={
                <Select.Portal
                    style={ { '--wp-ui-select-z-index': '9999' } }
                />
            }
            key="popup"
        >
            { defaultItems.map( ( item ) => (
                <Select.Item key={ item.value } value={ item }>
                    <Select.ItemLabel>{ item.label }</Select.ItemLabel>
                </Select.Item>
            ) ) }
        </Select.Popup>,
    ]}</Select.Root>;
Incomplete snippet: `defaultItems` could not be resolved statically.
Popup Width story ok
Use `width` on `Select.Popup` to constrain the popup relative to a narrow anchor.
const PopupWidth = () => <Select.Root items={longLabelPopupItems}>
    <Select.Trigger aria-label="Label" />
    <Select.Popup width="sm">
        { longLabelPopupItems.map( ( item ) => (
            <Select.Item key={ item.value } value={ item }>
                <Select.ItemLabel>{ item.label }</Select.ItemLabel>
            </Select.Item>
        ) ) }
    </Select.Popup>
</Select.Root>;
Select.Trigger 9 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/select/index.ts
import { Trigger } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/select/index.ts::Trigger (react-component-meta)
/**
 * A function that gets called with the current value as an argument.
 * Use this to customize the trigger content.
 * 
 * When no value is selected, the rendered content inherits the
 * placeholder text color.
 */
children?: ReactNode | ((value: any) => ReactNode)

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

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

/**
 * Whether the component renders a native `<button>` element when replacing it
 * via the `render` prop.
 * Set to `false` if the rendered element is not a button (for example, `<div>`).
 */
nativeButton?: boolean = true

/**
 * Text to show when no value is selected.
 * This is overridden by `children` if specified, or by a null item's label in `items`.
 */
placeholder?: ReactNode = __( 'Select' )

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * The size of the trigger.
 */
size?: "small" | "default" | "compact" = 'default'

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The style variant of the trigger.
 */
variant?: "default" | "minimal" = 'default'
Select.Portal 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/select/index.ts
Used to apply custom portal behavior to `Select`'s listbox content. `container` defaults to the `@wordpress/ui` compat overlay slot.
import { Portal } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/select/index.ts::Portal (react-component-meta)
/**
 * CSS class name to apply to the element.
 */
className?: string

/**
 * A parent element to render the portal element into.
 */
container?: HTMLElement | ShadowRoot | RefObject<HTMLElement | ShadowRoot | null> | null | undefined

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Select.Positioner 16 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/select/index.ts
Used to apply custom positioning to `Select`'s listbox content.
import { Positioner } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/select/index.ts::Positioner (react-component-meta)
/**
 * How to align the popup relative to the specified side.
 */
align?: "center" | "end" | "start" = 'center'

/**
 * Whether the positioner overlaps the trigger so the selected item's text is aligned with the trigger's value text. This only applies to mouse input and is automatically disabled if there is not enough space.
 */
alignItemWithTrigger?: boolean = true

/**
 * Additional offset along the alignment axis in pixels.
 * Also accepts a function that returns the offset to read the dimensions of the anchor
 * and positioner elements, along with its side and alignment.
 * 
 * The function takes a `data` object parameter with the following properties:
 * - `data.anchor`: the dimensions of the anchor element with properties `width` and `height`.
 * - `data.positioner`: the dimensions of the positioner element with properties `width` and `height`.
 * - `data.side`: which side of the anchor element the positioner is aligned against.
 * - `data.align`: how the positioner is aligned relative to the specified side.
 */
alignOffset?: number | OffsetFunction | undefined = 0

/**
 * An element to position the popup against.
 * By default, the popup will be positioned against the trigger.
 */
anchor?: Element | VirtualElement | RefObject<Element | null> | (() => Element | VirtualElement | null) | null | undefined

/**
 * Minimum distance to maintain between the arrow and the edges of the popup.
 * 
 * Use it to prevent the arrow element from hanging out of the rounded corners of a popup.
 */
arrowPadding?: number = 5

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

/**
 * Determines how to handle collisions when positioning the popup.
 * 
 * `side` controls overflow on the preferred placement axis (`top`/`bottom` or `left`/`right`):
 * - `'flip'`: keep the requested side when it fits; otherwise try the opposite side
 *   (`top` and `bottom`, or `left` and `right`).
 * - `'shift'`: never change side; keep the requested side and move the popup within
 *   the clipping boundary so it stays visible.
 * - `'none'`: do not correct side-axis overflow.
 * 
 * `align` controls overflow on the alignment axis (`start`/`center`/`end`):
 * - `'flip'`: keep side, but swap `start` and `end` when the requested alignment overflows.
 * - `'shift'`: keep side and requested alignment, then nudge the popup along the
 *   alignment axis to fit.
 * - `'none'`: do not correct alignment-axis overflow.
 * 
 * `fallbackAxisSide` controls fallback behavior on the perpendicular axis when the
 * preferred axis cannot fit:
 * - `'start'`: allow perpendicular fallback and try the logical start side first
 *   (`top` before `bottom`, or `left` before `right` in LTR).
 * - `'end'`: allow perpendicular fallback and try the logical end side first
 *   (`bottom` before `top`, or `right` before `left` in LTR).
 * - `'none'`: do not fallback to the perpendicular axis.
 * 
 * When `side` is `'shift'`, explicitly setting `align` only supports `'shift'` or `'none'`.
 * If `align` is omitted, it defaults to `'flip'`.
 */
collisionAvoidance?: CollisionAvoidance | undefined

/**
 * An element or a rectangle that delimits the area that the popup is confined to.
 */
collisionBoundary?: Boundary | undefined = 'clipping-ancestors'

/**
 * Additional space to maintain from the edge of the collision boundary.
 */
collisionPadding?: Padding | undefined = 5

/**
 * Whether to disable the popup from tracking any layout shift of its positioning anchor.
 */
disableAnchorTracking?: boolean = false

/**
 * Determines which CSS `position` property to use.
 */
positionMethod?: "fixed" | "absolute" = 'absolute'

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * Which side of the anchor element to align the popup against.
 * May automatically change to avoid collisions.
 */
side?: "left" | "right" | "bottom" | "top" | "inline-end" | "inline-start" = 'bottom'

/**
 * Distance between the anchor and the popup in pixels.
 * Also accepts a function that returns the distance to read the dimensions of the anchor
 * and positioner elements, along with its side and alignment.
 * 
 * The function takes a `data` object parameter with the following properties:
 * - `data.anchor`: the dimensions of the anchor element with properties `width` and `height`.
 * - `data.positioner`: the dimensions of the positioner element with properties `width` and `height`.
 * - `data.side`: which side of the anchor element the positioner is aligned against.
 * - `data.align`: how the positioner is aligned relative to the specified side.
 */
sideOffset?: number | OffsetFunction | undefined = 0

/**
 * Whether to maintain the popup in the viewport after
 * the anchor element was scrolled out of view.
 */
sticky?: boolean = false

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Select.Popup 8 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/select/index.ts
import { Popup } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/select/index.ts::Popup (react-component-meta)
/**
 * The content to be rendered inside the popup.
 */
children?: ReactNode

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

/**
 * Determines the element to focus when the select popup is closed.
 * 
 * - `false`: Do not move focus.
 * - `true`: Move focus based on the default behavior (trigger or previously focused element).
 * - `RefObject`: Move focus to the ref element.
 * - `function`: Called with the interaction type (`mouse`, `touch`, `pen`, or `keyboard`).
 *   Return an element to focus, `true` to use the default behavior, or `false`/`undefined` to do nothing.
 */
finalFocus?: boolean | RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | void | HTMLElement | null) | undefined

/**
 * Optional portal element, typically `<Select.Portal />` with custom
 * `container`. When omitted, `Select.Popup` uses `Select.Portal` with
 * default props. Do not pass `children` on the portal element; they would
 * be ignored.
 */
portal?: ReactElement<Omit<PortalProps, "children">, string | JSXElementConstructor<any>>

/**
 * Optional positioner element, typically `<Select.Positioner />` with
 * custom positioning props (`side`, `align`, `sideOffset`, collision
 * settings, etc.). When omitted, `Select.Popup` uses `Select.Positioner`
 * with default props. Do not pass `children` on the positioner element;
 * they would be ignored.
 */
positioner?: ReactElement<Omit<PositionerProps, "children">, string | JSXElementConstructor<any>>

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * Controls how the popup width is constrained relative to its anchor.
 * 
 * For all presets, the popup is never narrower than its anchor.
 * 
 * - `'anchor'`: Fixed width matching the anchor width.
 * - `'content'`: Width grows with item labels between the anchor and available
 *   viewport bounds.
 * - `'sm'`: Fixed width at the small surface width token (`--wpds-dimension-surface-width-sm`).
 * - `'md'`: Fixed width at the medium surface width token (`--wpds-dimension-surface-width-md`).
 * - `'lg'`: Fixed width at the large surface width token (`--wpds-dimension-surface-width-lg`).
 * - `'available'`: Fixed width at the available viewport width (`--available-width`).
 */
width?: "anchor" | "content" | "sm" | "md" | "lg" | "available" = 'anchor'
Select.Group 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/select/index.ts
Groups related items together with an associated label rendered by `Select.GroupLabel`.
import { Group } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/select/index.ts::Group (react-component-meta)
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Select.GroupLabel 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/select/index.ts
Renders a label for a `Select.Group`, describing the group of items it is associated with.
import { GroupLabel } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/select/index.ts::GroupLabel (react-component-meta)
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Select.Item 9 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/select/index.ts
import { Item } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/select/index.ts::Item (react-component-meta)
/**
 * One direct `Select.ItemLabel`, followed by zero or more direct
 * `Select.ItemDescription` components.
 */
children: SelectItemChildren

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

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

/**
 * Specifies the text label to use when the item is matched during keyboard text navigation.
 * 
 * Defaults to the item text content if not provided.
 */
label?: string

/**
 * Whether the component renders a native `<button>` element when replacing it
 * via the `render` prop.
 * Set to `true` if the rendered element is a native button.
 */
nativeButton?: boolean = false

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * The size of the item.
 */
size?: "small" | "default" = 'default'

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * A unique value that identifies this select item.
 */
value?: unknown
Select.ItemLabel 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/select/index.ts
The primary label of a select item. Use it as the first direct child of every item. Its content is the item's accessible name. The trigger label still comes from the selected item's `label` (via `items` or an object value) or from `Select.Trigger` children.
import { ItemLabel } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/select/index.ts::ItemLabel (react-component-meta)
/**
 * The primary label for a select item. Use as the first direct child of
 * every select item. The trigger label still comes from the selected
 * item's `label` or from `Select.Trigger` children.
 */
children: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Select.ItemDescription 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/select/index.ts
Supplementary content for a select item. Its text contributes to the item's accessible description. Use it as a direct child after `Select.ItemLabel`. Content should be text or non-interactive inline markup.
import { ItemDescription } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/select/index.ts::ItemDescription (react-component-meta)
/**
 * Content that contributes to the select item's accessible description.
 * Use as a direct child after `Select.ItemLabel`. Content should be text
 * or non-interactive inline markup.
 */
children: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Select.Separator 3 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/primitives/select/index.ts
Renders a visual separator between select items or groups.
import { Separator } from '@wordpress/ui';
Component: ../packages/ui/src/form/primitives/select/index.ts::Separator (react-component-meta)
/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

SelectControl

design-system-components-form-selectcontrol · ../packages/ui/src/form/select-control/stories/index.story.tsx
A complete select field with integrated label and description.
Prop types (react-component-meta) 33 prop types
Component: ../packages/ui/src/form/select-control/index.ts::SelectControl
Props:
/**
 * A ref to imperative actions.
 * - `unmount`: Ends the closing phase of the select after an externally controlled closing animation finishes.
 * Call `preventUnmountOnClose()` in `onOpenChange` first, otherwise the select completes closing on its own.
 * Whether it leaves the DOM is decided by `keepMounted` on the portal.
 * - `close`: Closes the select imperatively when called.
 */
actionsRef?: RefObject<SelectRootActions | null>

/**
 * Provides a hint to the browser for autofill.
 */
autoComplete?: string

children?: ReactNode

/**
 * CSS class to apply.
 */
className?: string

/**
 * Whether the select popup is initially open.
 * 
 * To render a controlled select popup, use the `open` prop instead.
 */
defaultOpen?: boolean = false

/**
 * The uncontrolled value of the select when it's initially rendered.
 * 
 * To render a controlled select, use the `value` prop instead.
 */
defaultValue?: SelectItem | null | undefined

/**
 * The accessible description, associated using `aria-describedby`.
 * 
 * For screen reader accessibility, this should only contain plain text,
 * and no semantics such as links.
 */
description?: string

/**
 * 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?: ReactNode

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

/**
 * Identifies the form that owns the hidden input.
 * Useful when the select is rendered outside the form.
 */
form?: string

/**
 * Whether to visually hide the label while keeping it accessible
 * to screen readers.
 */
hideLabelFromVision?: boolean = false

/**
 * Whether moving the pointer over items should highlight them.
 * Disabling this prop allows CSS `:hover` to be differentiated from the `:focus` (`data-highlighted`) state.
 */
highlightItemOnHover?: boolean = true

/**
 * The id of the Select.
 */
id?: string

/**
 * Custom comparison logic used to determine if a select item value matches the current selected value. Useful when item values are objects without matching referentially.
 * Defaults to `Object.is` comparison.
 */
isItemEqualToValue?: (itemValue: SelectItem, value: SelectItem) => boolean

/**
 * The array of option items to render in the select.
 */
items?: SelectItem[]

/**
 * When the item values are objects (`<Select.Item value={object}>`), this function converts the object value to a string representation for display in the trigger.
 * If the shape of the object is `{ value, label }`, the label will be used automatically without needing to specify this prop.
 */
itemToStringLabel?: (itemValue: SelectItem) => string

/**
 * When the item values are objects (`<Select.Item value={object}>`), this function converts the object value to a string representation for form submission.
 * If the shape of the object is `{ value, label }`, the value will be used automatically without needing to specify this prop.
 */
itemToStringValue?: (itemValue: SelectItem) => string

key?: Key | null | undefined

/**
 * The accessible label. All controls must be labeled.
 */
label: string

/**
 * Determines if the select enters a modal state when open.
 * - `true`: user interaction is limited to the select: document page scroll is locked and pointer interactions on outside elements are disabled.
 * - `false`: user interaction with the rest of the document is allowed.
 * 
 * On touch devices, a `true` modal blocks outside taps but leaves the page scrollable unless the popup spans nearly the full viewport width, matching native iOS behavior.
 */
modal?: boolean = true

/**
 * Identifies the field when a form is submitted.
 */
name?: string

/**
 * Event handler called when the select popup is opened or closed.
 */
onOpenChange?: (open: boolean, eventDetails: SelectRootOpenChangeEventDetails) => void

/**
 * Event handler called after any animations complete when the select popup is opened or closed.
 */
onOpenChangeComplete?: (open: boolean) => void

/**
 * Event handler called when the value of the select changes.
 */
onValueChange?: (value: SelectItem | null, eventDetails: SelectRootChangeEventDetails) => void

/**
 * Whether the select popup is currently open.
 */
open?: boolean

/**
 * Text to show when no value is selected. This is overridden by `triggerContent`
 * if specified, or by a null item's label in `items`.
 */
placeholder?: ReactNode = __( 'Select' )

/**
 * Controls how the popup width is constrained relative to its anchor.
 * 
 * For all presets, the popup is never narrower than its anchor.
 * 
 * - `'anchor'`: Fixed width matching the anchor width.
 * - `'content'`: Width grows with item labels between the anchor and available
 *   viewport bounds.
 * - `'sm'`: Fixed width at the small surface width token (`--wpds-dimension-surface-width-sm`).
 * - `'md'`: Fixed width at the medium surface width token (`--wpds-dimension-surface-width-md`).
 * - `'lg'`: Fixed width at the large surface width token (`--wpds-dimension-surface-width-lg`).
 * - `'available'`: Fixed width at the available viewport width (`--available-width`).
 */
popupWidth?: "anchor" | "content" | "sm" | "md" | "lg" | "available" = 'content'

/**
 * Whether the user should be unable to choose a different option from the select popup.
 */
readOnly?: boolean = false

/**
 * Allows getting a ref to the component instance.
 * Once the component unmounts, React will set `ref.current` to `null`
 * (or call the ref with `null` if you passed a callback ref).
 */
ref?: Ref<HTMLButtonElement> | undefined

/**
 * Whether the user must choose a value before submitting a form.
 */
required?: boolean = false

/**
 * The size of the control.
 */
size?: "default" | "compact" = 'default'

/**
 * The custom trigger content to use instead of the default.
 * 
 * ```jsx
 * triggerContent={ ( item ) => item.label }
 * ```
 */
triggerContent?: ReactNode | ((item: SelectItem) => ReactNode)

/**
 * The value of the select. Use when controlled.
 */
value?: SelectItem | null | undefined
Imports
import { SelectControl } from '@wordpress/ui';
import { DETAILS_EXAMPLE, longLabelPopupItems } from '../../stories/shared';
import { SelectControl } from '../';
Default story ok
const Default = () => <SelectControl
    items={[
        {
            value: '1',
            label: 'Item 1',
        },
        {
            value: '2',
            label: 'Item 2',
        },
    ]}
    label="Label"
    description="This is the description." />;
With Custom Placeholder story ok
When no value is selected, the trigger shows the default placeholder text. Use the `placeholder` prop to customize text shown. Prefer a concise label without a trailing ellipsis.
const WithCustomPlaceholder = () => <SelectControl
    items={[
        {
            value: '1',
            label: 'Item 1',
        },
        {
            value: '2',
            label: 'Item 2',
        },
    ]}
    label="Label"
    description="This is the description."
    placeholder="Choose an item" />;
With Null Value Option incomplete example
Use a `null` item value when users should be able to clear the selected value from the popup.
const WithNullValueOption = () => <SelectControl
    items={[
        {
            value: null,
            label: 'Select theme',
        },
        {
            value: 'system',
            label: 'System default',
        },
        {
            value: 'light',
            label: 'Light',
        },
        {
            value: 'dark',
            label: 'Dark',
        },
    ]}
    label="Theme"
    description="Choose a theme preference."
    defaultValue={nullValueOptionItems[ 0 ]} />;
Incomplete snippet: `nullValueOptionItems` could not be resolved statically.
Visually Hidden Label story ok
const VisuallyHiddenLabel = () => <SelectControl
    items={[
        {
            value: '1',
            label: 'Item 1',
        },
        {
            value: '2',
            label: 'Item 2',
        },
    ]}
    label="Label"
    description="This is the description."
    hideLabelFromVision />;
With Details story ok
const WithDetails = () => <SelectControl
    items={[
        {
            value: '1',
            label: 'Item 1',
        },
        {
            value: '2',
            label: 'Item 2',
        },
    ]}
    label="Label"
    description={undefined}
    details={DETAILS_EXAMPLE} />;
With Disabled Option incomplete example
const WithDisabledOption = () => <SelectControl
    items={[
        {
            value: '1',
            label: 'Item 1',
        },
        {
            value: '2',
            label: 'Item 2',
            disabled: true,
        },
    ]}
    label="Label"
    description="This is the description."
    defaultValue={disabledOptionItems[ 0 ]} />;
Incomplete snippet: `disabledOptionItems` could not be resolved statically.
Grouped incomplete example
Options can be organized into labeled groups with `SelectControl.Group` and `SelectControl.GroupLabel`. Pass a flat `items` array for trigger label resolution, and use `children` to render the grouped popup content.
const Grouped = () => <SelectControl
    label="Fruit"
    description="Choose a fruit."
    items={groupedItems.flatMap( ( group ) => group.items )}>{[
        groupedItems.map( ( group ) => (
            <SelectControl.Group key={ group.label }>
                <SelectControl.GroupLabel>
                    { group.label }
                </SelectControl.GroupLabel>
                { group.items.map( ( item ) => (
                    <SelectControl.Item
                        key={ item.value }
                        value={ item }
                        label={ item.label }
                    >
                        <SelectControl.ItemLabel>
                            { item.label }
                        </SelectControl.ItemLabel>
                    </SelectControl.Item>
                ) ) }
            </SelectControl.Group>
        ) ),
    ]}</SelectControl>;
Incomplete snippet: `groupedItems` could not be resolved statically.
With Separator incomplete example
Use `SelectControl.Separator` to set choices apart from each other.
const WithSeparator = () => <SelectControl
    label="Fruit"
    items={[
        { value: 'apple', label: 'Apple' },
        { value: 'banana', label: 'Banana' },
        { value: 'other', label: 'Other' },
    ]}>{[
        ...separatorItems.slice( 0, 2 ).map( ( item ) => (
            <SelectControl.Item
                key={ item.value }
                value={ item }
                label={ item.label }
            >
                <SelectControl.ItemLabel>
                    { item.label }
                </SelectControl.ItemLabel>
            </SelectControl.Item>
        ) ),
        <SelectControl.Separator key="separator" />,
        <SelectControl.Item
            key="other"
            value={ separatorItems[ 2 ] }
            label="Other"
        >
            <SelectControl.ItemLabel>Other</SelectControl.ItemLabel>
        </SelectControl.Item>,
    ]}</SelectControl>;
Incomplete snippet: `separatorItems` could not be resolved statically.
With Custom Trigger And Items incomplete example
To customize what is rendered inside the trigger element, pass a render function to the `triggerContent` prop. The item list can be customized by passing an array of `SelectControl.Item` as children. Note that the `label` prop of a `SelectControl.Item` is used as the string to match against in the typeahead functionality, while the item content is determined by `children`.
const WithCustomTriggerAndItems = () => <SelectControl
    items={[
        {
            value: '1',
            label: 'User 1 (Admin)',
        },
        {
            value: '2',
            label: 'User 2 (Editor)',
        },
        {
            value: '3',
            label: 'User 3 (Author)',
        },
    ]}
    label="Label"
    description="This is the description."
    triggerContent={( item ) => <User user={ item } />}
    defaultValue={userOptions[ 0 ]}>{[
        userOptions.map( ( item ) => (
            <SelectControl.Item
                key={ item.value }
                value={ item }
                label={ item.label }
            >
                <SelectControl.ItemLabel>
                    <User user={ item } />
                </SelectControl.ItemLabel>
            </SelectControl.Item>
        ) ),
    ]}</SelectControl>;
Incomplete snippet: `User`, `userOptions` could not be resolved statically.
With Items Array And Partial Customization incomplete example
By default, the `items` array is used to render both the Trigger and the Item list. Passing a custom `triggerContent` or `children` in addition to `items` will override that particular aspect of the behavior. In other words, if you pass both an `items` array and a custom `triggerContent`, the Item list in the popover will still be rendered based on the `items` array.
const WithItemsArrayAndPartialCustomization = () => <SelectControl
    items={[
        {
            value: '1',
            label: 'Item 1',
        },
        {
            value: '2',
            label: 'Item 2',
        },
    ]}
    label="Label"
    description="This is the description.">{[
        Default.args?.items?.map( ( item ) => (
            <SelectControl.Item
                key={ item.value ?? 'null' }
                value={ item }
                label={ item.label }
                disabled={ item.disabled }
            >
                <SelectControl.ItemLabel>
                    ✨ { item.label }
                </SelectControl.ItemLabel>
            </SelectControl.Item>
        ) ),
    ]}</SelectControl>;
Incomplete snippet: `Default` could not be resolved statically.
With Item Description story ok
Pass `description` on an `items` entry for supplementary text. It is announced as a description rather than part of the item name. Compose `SelectControl.Item` children when you need multiple descriptions or custom markup.
const WithItemDescription = () => <SelectControl
    label="Fruit"
    items={[
        {
            value: 'apple',
            label: 'Apple',
            description:
                '99 in stock. Ships in two to three business days.',
        },
        {
            value: 'banana',
            label: 'Banana',
            description: '12 in stock. Restock expected next week.',
        },
    ]} />;
Popup Width story ok
Use `popupWidth` to control how the popup width is constrained relative to its anchor. Defaults to `content` so static option lists can grow with their labels.
const PopupWidth = () => <SelectControl label="Label" items={longLabelPopupItems} popupWidth="content" />;
SelectControl.Group 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/select-control/index.ts
Groups related items together with an associated label rendered by `Select.GroupLabel`.
import { SelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/select-control/index.ts::SelectControl (react-component-meta)
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SelectControl.GroupLabel 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/select-control/index.ts
Renders a label for a `Select.Group`, describing the group of items it is associated with.
import { SelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/select-control/index.ts::SelectControl (react-component-meta)
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SelectControl.Item 8 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/select-control/index.ts
import { SelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/select-control/index.ts::SelectControl (react-component-meta)
/**
 * One direct `Select.ItemLabel`, followed by zero or more direct
 * `Select.ItemDescription` components.
 */
children: SelectItemChildren

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

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

/**
 * Specifies the text label to use when the item is matched during keyboard text navigation.
 * 
 * Defaults to the item text content if not provided.
 */
label?: string

/**
 * Whether the component renders a native `<button>` element when replacing it
 * via the `render` prop.
 * Set to `true` if the rendered element is a native button.
 */
nativeButton?: boolean = false

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * A unique value that identifies this select item.
 */
value?: unknown
SelectControl.ItemLabel 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/select-control/index.ts
The primary label of a select item. Use it as the first direct child of every item. Its content is the item's accessible name. The trigger label still comes from the selected item's `label` (via `items` or an object value) or from `Select.Trigger` children.
import { SelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/select-control/index.ts::SelectControl (react-component-meta)
/**
 * The primary label for a select item. Use as the first direct child of
 * every select item. The trigger label still comes from the selected
 * item's `label` or from `Select.Trigger` children.
 */
children: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SelectControl.ItemDescription 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/select-control/index.ts
Supplementary content for a select item. Its text contributes to the item's accessible description. Use it as a direct child after `Select.ItemLabel`. Content should be text or non-interactive inline markup.
import { SelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/select-control/index.ts::SelectControl (react-component-meta)
/**
 * Content that contributes to the select item's accessible description.
 * Use as a direct child after `Select.ItemLabel`. Content should be text
 * or non-interactive inline markup.
 */
children: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
SelectControl.Separator 3 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/form/select-control/index.ts
Renders a visual separator between select items or groups.
import { SelectControl } from '@wordpress/ui';
Component: ../packages/ui/src/form/select-control/index.ts::SelectControl (react-component-meta)
/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

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 (react-component-meta) 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; } | undefined
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 } />;
};

Skeleton

design-system-components-skeleton · ../packages/ui/src/skeleton/stories/index.story.tsx
A placeholder shown while content is loading. Size and corner radius are controlled via standard `div` props such as `style` and `className`.
Prop types (react-component-meta) 3 prop types
Component: ../packages/ui/src/skeleton/index.ts::Skeleton
Props:
/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Imports
import { Skeleton } from '@wordpress/ui';
Default incomplete example
const Default = () => <Skeleton
    style={{
        width: 'var(--wpds-dimension-surface-width-xs)',
        height: textLineHeight,
        borderRadius: 'var(--wpds-border-radius-md)',
    }} />;
Incomplete snippet: `textLineHeight` could not be resolved statically.
Circle story ok
const Circle = () => <Skeleton
    style={{
        width: 'var(--wpds-dimension-size-lg)',
        height: 'var(--wpds-dimension-size-lg)',
        borderRadius: '50%',
    }} />;
Text Lines story ok
const TextLines = () => <div
    style={ {
        display: 'flex',
        flexDirection: 'column',
        gap: '0.5rem',
    } }>
    <Skeleton
        style={ {
            width: '100%',
            height: textLineHeight,
            borderRadius: 'var(--wpds-border-radius-md)',
        } } />
    <Skeleton
        style={ {
            width: '100%',
            height: textLineHeight,
            borderRadius: 'var(--wpds-border-radius-md)',
        } } />
    <Skeleton
        style={ {
            width: '60%',
            height: textLineHeight,
            borderRadius: 'var(--wpds-border-radius-md)',
        } } />
</div>;
Card Placeholder story ok
const CardPlaceholder = () => <div
    style={ {
        display: 'flex',
        gap: '1rem',
        alignItems: 'center',
        maxWidth: 320,
    } }>
    <Skeleton
        style={ {
            width: 'var(--wpds-dimension-size-lg)',
            height: 'var(--wpds-dimension-size-lg)',
            borderRadius: '50%',
        } } />
    <div
        style={ {
            display: 'flex',
            flexDirection: 'column',
            gap: '0.5rem',
            flex: 1,
        } }>
        <Skeleton
            style={ {
                width: '80%',
                height: textLineHeight,
                borderRadius: 'var(--wpds-border-radius-md)',
            } } />
        <Skeleton
            style={ {
                width: '50%',
                height: textLineHeight,
                borderRadius: 'var(--wpds-border-radius-md)',
            } } />
    </div>
</div>;

Slot

components-slotfill · ../packages/components/src/slot-fill/stories/index.story.tsx
`Slot` marks a location where content rendered by matching `Fill` components elsewhere will appear. Use it to allow a component to define UI areas that can be extended from other parts of the application.
Prop types (react-component-meta) 7 prop types
Component: ../packages/components/src/slot-fill/index.tsx::Slot
Props:
/**
 * The HTML element or React component to render the component as.
 */
as?: JSXElementConstructor<any> | keyof IntrinsicElements | undefined

/**
 * By default, events will bubble to their parents on the DOM hierarchy (native event bubbling).
 * If set to true, events will bubble to their virtual parent in the React elements hierarchy instead,
 * also accept an optional `className`, `id`, etc.  to add to the slot container.
 */
bubblesVirtually?: boolean

/**
 * A function that returns nodes to be rendered.
 * Supported only when `bubblesVirtually` is `false`.
 */
children?: (fills: ReactNode) => ReactNode

/**
 * Additional className for the `Slot` component.
 * Supported only when `bubblesVirtually` is `true`.
 */
className?: string

/**
 * props to pass from `Slot` to `Fill`.
 */
fillProps?: FillProps = {}

/**
 * Slot name.
 */
name: SlotKey

/**
 * Additional styles for the `Slot` component.
 * Supported only when `bubblesVirtually` is `true`.
 */
style?: CSSProperties
Imports
import { Fill, Slot, Provider as SlotFillProvider, Spacer } 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>
	);
};
Cross Document Styles story ok
const CrossDocumentStyles = () => {
	return (
		<SlotFillProvider>
			<p>
				The content below should have 32px of padding inside its
				outline.
			</p>
			<IframePortal>
				<Slot name="cross-document-styles" bubblesVirtually />
			</IframePortal>
			<Fill name="cross-document-styles">
				<Spacer
					padding={ 8 }
					style={ {
						display: 'inline-block',
						outline: '2px solid currentColor',
					} }
				>
					SCSS module styles rendered in another document
				</Spacer>
			</Fill>
		</SlotFillProvider>
	);
};
Fill 2 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/slot-fill/index.tsx
import { Fill } from '@wordpress/components';
Component: ../packages/components/src/slot-fill/index.tsx::Fill (react-component-meta)
/**
 * Children elements or render function.
 */
children?: FillChildren

/**
 * The name of the slot to fill into.
 */
name: SlotKey
SlotFillProvider 2 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/slot-fill/index.tsx
import { Provider as SlotFillProvider } from '@wordpress/components';
Component: ../packages/components/src/slot-fill/index.tsx::Provider (react-component-meta)
/**
 * The children elements.
 */
children: ReactNode

/**
 * Whether to pass slots to the parent provider if existent.
 */
passthrough?: boolean = false

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 (react-component-meta) 11 prop types
Component: ../packages/components/src/snackbar/index.tsx::default
Props:
/**
 * 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.
 * 
 * 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.
 */
actions?: (Pick<NoticeAction, "url" | "label" | "onClick"> & { openInNewTab?: boolean | undefined; })[] = []

/**
 * The HTML element or React component to render the component as.
 */
as?: JSXElementConstructor<any> | keyof IntrinsicElements | undefined

/**
 * 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 to require user action to dismiss the snackbar.
 * By default, this is dismissed on a timeout, without user interaction.
 */
explicitDismiss?: boolean = false

/**
 * The icon to render in the snackbar.
 */
icon?: ReactNode = null

/**
 * A ref to the list that contains the snackbar.
 */
listRef?: RefObject<HTMLDivElement | null>

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

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

/**
 * 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.
 */
politeness?: "assertive" | "polite" = 'polite'

/**
 * Used to provide a custom spoken message in place of the `children` default.
 */
spokenMessage?: ReactNode = children
Imports
import { Icon, Snackbar } from '@wordpress/components';
import Icon from '../../icon';
import { wordpress } from '@wordpress/icons';
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>;
};

Spinner

design-system-components-spinner · ../packages/ui/src/spinner/stories/index.story.tsx
A component used to notify users that their action is being processed.
Prop types (react-component-meta) 1 prop type
Component: ../packages/ui/src/spinner/index.ts::Spinner
Props:
/**
 * The spinner color. Accepts any CSS color value, including `currentColor`
 * to inherit the surrounding text color.
 */
color?: string = 'var(--wpds-color-foreground-content-neutral-weak)'
Imports
import { Spinner, Stack } from '@wordpress/ui';
Default story ok
const Default = () => <Spinner />;
Custom Size story ok
const CustomSize = () => <Spinner
    style={{
        width: 'var(--wpds-dimension-size-lg)',
        height: 'var(--wpds-dimension-size-lg)',
    }} />;
Custom Color story ok
const CustomColor = () => <Spinner color="#d92d20" />;
Current Color story ok
const CurrentColor = () => <Stack direction="row" gap="sm" align="center" style={ { color: '#7f32c9' } }>
    <Spinner color="currentColor" />
    <span>Loading…</span>
</Stack>;

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 (react-component-meta) 9 prop types
Component: ../packages/ui/src/stack/index.ts::Stack
Props:
/**
 * The alignment of the stack items along the cross axis.
 */
align?: AlignItems | undefined = 'initial'

/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

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

/**
 * The direction of the stack.
 */
direction?: "-moz-initial" | "inherit" | "initial" | "revert" | "revert-layer" | "unset" | "row" | "column"

/**
 * The amount of space between each child element using design system tokens.
 */
gap?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" = undefined

/**
 * The alignment of the stack items along the main axis.
 */
justify?: JustifyContent | undefined = 'initial'

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * Whether the stack items should wrap to the next line.
 */
wrap?: "-moz-initial" | "inherit" | "initial" | "revert" | "revert-layer" | "unset" | "wrap" | "nowrap"
Imports
import { Stack } from '@wordpress/ui';
import { Stack } from '../index';
Default incomplete example
const Default = () => <Stack gap="md">{[
        <DemoBox key="demoBox" />,
        <DemoBox variant="lg" key="demoBox-2" />,
        <DemoBox key="demoBox-3" />,
        <DemoBox key="demoBox-4" />,
        <DemoBox variant="lg" key="demoBox-5" />,
        <DemoBox key="demoBox-6" />,
    ]}</Stack>;
Incomplete snippet: `DemoBox` could not be resolved statically.
Nested incomplete example
const Nested = () => <Stack gap="md" align="center" justify="center">{[
        <DemoBox variant="lg" key="demoBox" />,
        <Stack gap="lg" key="stack">
            <DemoBox />
            <DemoBox />
        </Stack>,
        <DemoBox variant="lg" key="demoBox-2" />,
        <Stack direction="column" key="stack-2">
            <DemoBox />
            <DemoBox />
        </Stack>,
        <DemoBox variant="lg" key="demoBox-3" />,
    ]}</Stack>;
Incomplete snippet: `DemoBox` could not be resolved statically.

Switch

design-system-components-form-primitives-switch · ../packages/ui/src/form/primitives/switch/stories/index.story.tsx
A low-level switch primitive. Use `Field` to associate an accessible label. Prefer `SwitchControl` for labeled items.
Prop types (react-component-meta) 16 prop types
Component: ../packages/ui/src/form/primitives/switch/index.ts::Switch
Props:
/**
 * Whether the switch is currently active.
 * 
 * To render an uncontrolled switch, use the `defaultChecked` prop instead.
 */
checked?: boolean

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

/**
 * Whether the switch is initially active.
 * 
 * To render a controlled switch, use the `checked` prop instead.
 */
defaultChecked?: boolean = false

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

/**
 * Identifies the form that owns the hidden input.
 * Useful when the switch is rendered outside the form.
 */
form?: string

/**
 * The id of the hidden input element.
 * 
 * When `nativeButton` is `true`, the id is applied to the root element.
 */
id?: string

/**
 * A ref to access the hidden `<input>` element.
 */
inputRef?: Ref<HTMLInputElement> | undefined

/**
 * Identifies the field when a form is submitted.
 */
name?: string

/**
 * Whether the component renders a native `<button>` element when replacing it
 * via the `render` prop.
 * Set to `true` if the rendered element is a native button.
 */
nativeButton?: boolean = false

/**
 * Event handler called when the switch is activated or deactivated.
 */
onCheckedChange?: (checked: boolean, eventDetails: { reason: "none"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void

/**
 * Whether the user should be unable to activate or deactivate the switch.
 */
readOnly?: boolean = false

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * Whether the user must activate the switch before submitting a form.
 */
required?: boolean = false

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The value submitted with the form when the switch is off.
 * By default, unchecked switches do not submit any value, matching native checkbox behavior.
 */
uncheckedValue?: string

/**
 * The value submitted with the form when the switch is on.
 * By default, switch submits the "on" value, matching native checkbox behavior.
 */
value?: string
Imports
import { Switch } from '@wordpress/ui';
Default story ok
const Default = () => <Switch aria-label="Option" />;
Checked story ok
const Checked = () => <Switch aria-label="Option" defaultChecked />;
Disabled story ok
const Disabled = () => <Switch aria-label="Option" disabled />;
Disabled Checked story ok
const DisabledChecked = () => <Switch aria-label="Option" disabled defaultChecked />;

SwitchControl

design-system-components-form-switchcontrol · ../packages/ui/src/form/switch-control/stories/index.story.tsx
A complete switch field with integrated label and description.
Prop types (react-component-meta) 20 prop types
Component: ../packages/ui/src/form/switch-control/index.ts::SwitchControl
Props:
/**
 * Whether the switch is currently active.
 * 
 * To render an uncontrolled switch, use the `defaultChecked` prop instead.
 */
checked?: boolean

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

/**
 * Whether the switch is initially active.
 * 
 * To render a controlled switch, use the `checked` prop instead.
 */
defaultChecked?: boolean = false

/**
 * The accessible description, associated using `aria-describedby`.
 * 
 * For screen reader accessibility, this should only contain plain text,
 * and no semantics such as links.
 */
description?: string

/**
 * 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?: ReactNode

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

/**
 * Identifies the form that owns the hidden input.
 * Useful when the switch is rendered outside the form.
 */
form?: string

/**
 * Whether to visually hide the label while keeping it accessible
 * to screen readers.
 */
hideLabelFromVision?: boolean = false

/**
 * The id of the hidden input element.
 * 
 * When `nativeButton` is `true`, the id is applied to the root element.
 */
id?: string

/**
 * A ref to access the hidden `<input>` element.
 */
inputRef?: Ref<HTMLInputElement> | undefined

/**
 * The accessible label. All controls must be labeled.
 */
label: string

/**
 * Identifies the field when a form is submitted.
 */
name?: string

/**
 * Whether the component renders a native `<button>` element when replacing it
 * via the `render` prop.
 * Set to `true` if the rendered element is a native button.
 */
nativeButton?: boolean = false

/**
 * Event handler called when the switch is activated or deactivated.
 */
onCheckedChange?: (checked: boolean, eventDetails: { reason: "none"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void

/**
 * Whether the user should be unable to activate or deactivate the switch.
 */
readOnly?: boolean = false

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * Whether the user must activate the switch before submitting a form.
 */
required?: boolean = false

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The value submitted with the form when the switch is off.
 * By default, unchecked switches do not submit any value, matching native checkbox behavior.
 */
uncheckedValue?: string

/**
 * The value submitted with the form when the switch is on.
 * By default, switch submits the "on" value, matching native checkbox behavior.
 */
value?: string
Imports
import { SwitchControl } from '@wordpress/ui';
import { DETAILS_EXAMPLE } from '../../stories/shared';
Default story ok
const Default = () => <SwitchControl label="Label" />;
With Description story ok
const WithDescription = () => <SwitchControl label="Label" description="This is the description." />;
With Long Label story ok
const WithLongLabel = () => <SwitchControl
    label="This is a long label that should wrap to the next line. This is a long label that should wrap to the next line. This is a long label that should wrap to the next line." />;
Visually Hidden Label story ok
const VisuallyHiddenLabel = () => <SwitchControl label="Label" hideLabelFromVision />;
With Details story ok
const WithDetails = () => <SwitchControl label="Label" details={DETAILS_EXAMPLE} />;
Disabled story ok
const Disabled = () => <SwitchControl label="Label" disabled />;
Disabled Checked story ok
const DisabledChecked = () => <SwitchControl label="Label" disabled defaultChecked />;

Tabs.Root

design-system-components-tabs · ../packages/ui/src/tabs/stories/index.story.tsx
Groups the tabs and the corresponding panels. `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/).
Prop types (react-component-meta) 8 prop types
Component: ../packages/ui/src/tabs/index.ts::Root
Props:
/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

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

/**
 * The default value. Use when the component is not controlled.
 * When the value is `null`, no Tab will be active.
 */
defaultValue?: any = 0

/**
 * Callback invoked when new value is being set.
 * 
 * The event `reason` is `'none'` for user-initiated changes, such as a click
 * or keyboard navigation; `'initial'` for the first automatic selection or
 * fallback in uncontrolled roots when `defaultValue` is omitted or
 * `undefined`, including when the implicit initial value is disabled or
 * missing; `'disabled'` for automatic fallback when the selected tab becomes
 * disabled in uncontrolled roots; or `'missing'` for automatic fallback when
 * the selected tab is removed, or when an explicit `defaultValue` never
 * matches a mounted tab in uncontrolled roots.
 * 
 * For automatic changes, the selected value can be `null` when no enabled Tab
 * is available as a fallback.
 * 
 * Automatic changes cannot be canceled; calling `eventDetails.cancel()` for
 * `'initial'`, `'disabled'`, or `'missing'` has no effect.
 */
onValueChange?: (value: any, eventDetails: TabsRootChangeEventDetails) => void

/**
 * The component orientation (layout flow direction).
 */
orientation?: "horizontal" | "vertical" = 'horizontal'

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The value of the currently active `Tab`. Use when the component is controlled.
 * When the value is `null`, no Tab will be active.
 */
value?: any
Imports
import { Icon, List, Panel, Root, Tab, Popup, Positioner, Trigger } from '@wordpress/ui';
import * as Tabs from '../';
import * as Tooltip from '../../tooltip';
import { Icon } from '../../icon';
Default incomplete example
const Default = () => <Tabs.Root defaultValue="tab1">{[
        <Tabs.List key="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" key="panel-tab1">
            <ThemedParagraph>Selected tab: Tab 1</ThemedParagraph>
        </Tabs.Panel>,
        <Tabs.Panel value="tab2" key="panel-tab2">
            <ThemedParagraph>Selected tab: Tab 2</ThemedParagraph>
        </Tabs.Panel>,
        <Tabs.Panel value="tab3" key="panel-tab3">
            <ThemedParagraph>Selected tab: Tab 3</ThemedParagraph>
        </Tabs.Panel>,
    ]}</Tabs.Root>;
Incomplete snippet: `ThemedParagraph` could not be resolved statically.
Minimal incomplete example
const Minimal = () => <Tabs.Root defaultValue="tab1">{[
        <Tabs.List variant="minimal" key="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" key="panel-tab1">
            <ThemedParagraph>Selected tab: Tab 1</ThemedParagraph>
        </Tabs.Panel>,
        <Tabs.Panel value="tab2" key="panel-tab2">
            <ThemedParagraph>Selected tab: Tab 2</ThemedParagraph>
        </Tabs.Panel>,
        <Tabs.Panel value="tab3" key="panel-tab3">
            <ThemedParagraph>Selected tab: Tab 3</ThemedParagraph>
        </Tabs.Panel>,
    ]}</Tabs.Root>;
Incomplete snippet: `ThemedParagraph` could not be resolved statically.
Size And Overflow Playground incomplete example
const SizeAndOverflowPlayground = function SizeAndOverflowPlaygroundRender( props ) {
    const [ fullWidth, setFullWidth ] = useState( false );
    return (
        <div>
            <div
                style={ {
                    maxWidth: '40rem',
                    marginBottom: '1rem',
                    color: 'var( --wpds-color-foreground-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>
    );
};
Incomplete snippet: `ThemedParagraph` could not be resolved statically.
Vertical incomplete example
const Vertical = () => <Tabs.Root
    defaultValue="tab1"
    orientation="vertical"
    style={{
        minWidth: '320px',
        display: 'grid',
        gridTemplateColumns: '120px 1fr',
        gap: '24px',
    }}>{[
        <Tabs.List key="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" key="panel-tab1">
            <ThemedParagraph>Selected tab: Tab 1</ThemedParagraph>
        </Tabs.Panel>,
        <Tabs.Panel value="tab2" key="panel-tab2">
            <ThemedParagraph>Selected tab: Tab 2</ThemedParagraph>
        </Tabs.Panel>,
        <Tabs.Panel value="tab3" key="panel-tab3">
            <ThemedParagraph>Selected tab: Tab 3</ThemedParagraph>
        </Tabs.Panel>,
    ]}</Tabs.Root>;
Incomplete snippet: `ThemedParagraph` could not be resolved statically.
With Disabled Tab incomplete example
const WithDisabledTab = () => <Tabs.Root defaultValue="tab3">{[
        <Tabs.List key="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" key="panel-tab1">
            <ThemedParagraph>Selected tab: Tab 1</ThemedParagraph>
        </Tabs.Panel>,
        <Tabs.Panel value="tab2" key="panel-tab2">
            <ThemedParagraph>Selected tab: Tab 2</ThemedParagraph>
        </Tabs.Panel>,
        <Tabs.Panel value="tab3" key="panel-tab3">
            <ThemedParagraph>Selected tab: Tab 3</ThemedParagraph>
        </Tabs.Panel>,
    ]}</Tabs.Root>;
Incomplete snippet: `ThemedParagraph` could not be resolved statically.
With Tab Icons And Tooltips incomplete example
const WithTabIconsAndTooltips = () => <Tabs.Root defaultValue="tab1">{[
        <Tabs.List key="list">
            { tabWithIconsData.map( ( { value, label, icon } ) => (
                <Tooltip.Root key={ value }>
                    <Tooltip.Trigger
                        aria-label={ label }
                        render={ <Tabs.Tab value={ value } /> }
                    >
                        <Icon icon={ icon } size={ 20 } />
                    </Tooltip.Trigger>
                    <Tooltip.Popup
                        positioner={
                            <Tooltip.Positioner 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>;
Incomplete snippet: `tabWithIconsData`, `ThemedParagraph` could not be resolved statically.
With Panels Always Mounted incomplete example
const WithPanelsAlwaysMounted = () => <Tabs.Root defaultValue="tab1">{[
        <Tabs.List key="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 key="panel-tab1">
            <ThemedParagraph>Selected tab: Tab 1</ThemedParagraph>
        </Tabs.Panel>,
        <Tabs.Panel value="tab2" keepMounted key="panel-tab2">
            <ThemedParagraph>Selected tab: Tab 2</ThemedParagraph>
        </Tabs.Panel>,
        <Tabs.Panel value="tab3" keepMounted key="panel-tab3">
            <ThemedParagraph>Selected tab: Tab 3</ThemedParagraph>
        </Tabs.Panel>,
    ]}</Tabs.Root>;
Incomplete snippet: `ThemedParagraph` could not be resolved statically.
With Non Focusable Panels incomplete example
const WithNonFocusablePanels = () => <Tabs.Root defaultValue="tab1">{[
        <Tabs.List key="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 } key="panel-tab1">
            <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 } key="panel-tab2">
            <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 } key="panel-tab3">
            <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>;
Incomplete snippet: `ThemedParagraph` could not be resolved statically.
Tabs.List 7 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/tabs/index.ts
Groups the individual tab buttons. `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/).
import { List } from '@wordpress/ui';
Component: ../packages/ui/src/tabs/index.ts::List (react-component-meta)
/**
 * Whether to automatically change the active tab on arrow key focus.
 * Otherwise, tabs will be activated using <kbd>Enter</kbd> or <kbd>Space</kbd> key press.
 */
activateOnFocus?: boolean = false

/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

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

/**
 * Whether to loop keyboard focus back to the first item
 * when the end of the list is reached while using the arrow keys.
 */
loopFocus?: boolean = true

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The visual variant of the tab list.
 */
variant?: "default" | "minimal" = 'default'
Tabs.Tab 7 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/tabs/index.ts
An individual interactive tab button that toggles the corresponding panel. `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/).
import { Tab } from '@wordpress/ui';
Component: ../packages/ui/src/tabs/index.ts::Tab (react-component-meta)
/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

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

/**
 * Whether the Tab is disabled.
 * 
 * If a first Tab on a `<Tabs.List>` is disabled, it won't initially be selected.
 * Instead, the next enabled Tab will be selected.
 * However, it does not work like this during server-side rendering, as it is not known
 * during pre-rendering which Tabs are disabled.
 * To work around it, ensure that `defaultValue` or `value` on `<Tabs.Root>` is set to an enabled Tab's value.
 */
disabled?: boolean

/**
 * Whether the component renders a native `<button>` element when replacing it
 * via the `render` prop.
 * Set to `false` if the rendered element is not a button (for example, `<div>`).
 */
nativeButton?: boolean = true

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The value of the Tab.
 */
value: any
Tabs.Panel 6 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/tabs/index.ts
A panel displayed when the corresponding tab is active. `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/).
import { Panel } from '@wordpress/ui';
Component: ../packages/ui/src/tabs/index.ts::Panel (react-component-meta)
/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

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

/**
 * Whether to keep the HTML element in the DOM while the panel is hidden.
 */
keepMounted?: boolean = false

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The value of the TabPanel. It will be shown when the Tab with the corresponding value is active.
 */
value: any

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 (react-component-meta) 5 prop types
Component: ../packages/ui/src/text/index.ts::Text
Props:
/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The typographic variant to apply, controlling font family, size,
 * line height, and weight.
 */
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-foreground-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>
);

Textarea

design-system-components-form-primitives-textarea · ../packages/ui/src/form/primitives/textarea/stories/index.story.tsx
A low-level primitive for a textarea field. Prefer `TextareaControl` when using with a standard label and description.
Prop types (react-component-meta) 8 prop types
Component: ../packages/ui/src/form/primitives/textarea/index.ts::Textarea
Props:
/**
 * CSS class name to apply to the element.
 */
className?: string

/**
 * The default value to use in uncontrolled mode.
 */
defaultValue?: string | number | readonly string[] | undefined

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

/**
 * Callback fired when the `value` changes. Use when controlled.
 */
onValueChange?: (value: string, eventDetails: { reason: "none"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * The number of rows the textarea should contain.
 */
rows?: number = 4

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The value to use in controlled mode.
 */
value?: string | number | readonly string[] | undefined
Imports
import { Textarea } from '@wordpress/ui';
Default story ok
const Default = () => <Textarea placeholder="Placeholder" aria-label="Value" />;
Disabled story ok
const Disabled = () => <Textarea placeholder="Placeholder" aria-label="Value" disabled />;
With Overflow story ok
const WithOverflow = () => <Textarea
    placeholder="Placeholder"
    aria-label="Value"
    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 placeholder="Placeholder" aria-label="Value" rows={1} />;

TextareaControl

design-system-components-form-textareacontrol · ../packages/ui/src/form/textarea-control/stories/index.story.tsx
A complete textarea field with integrated label and description.
Prop types (react-component-meta) 12 prop types
Component: ../packages/ui/src/form/textarea-control/index.ts::TextareaControl
Props:
/**
 * CSS class name to apply to the element.
 */
className?: string

/**
 * The default value to use in uncontrolled mode.
 */
defaultValue?: string | number | readonly string[] | undefined

/**
 * The accessible description, associated using `aria-describedby`.
 * 
 * For screen reader accessibility, this should only contain plain text,
 * and no semantics such as links.
 */
description?: string

/**
 * 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?: ReactNode

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

/**
 * Whether to visually hide the label while keeping it accessible
 * to screen readers.
 */
hideLabelFromVision?: boolean = false

/**
 * The accessible label. All controls must be labeled.
 */
label: string

/**
 * Callback fired when the `value` changes. Use when controlled.
 */
onValueChange?: (value: string, eventDetails: { reason: "none"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * The number of rows the textarea should contain.
 */
rows?: number = 4

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

/**
 * The value to use in controlled mode.
 */
value?: string | number | readonly string[] | undefined
Imports
import { TextareaControl } from '@wordpress/ui';
import { DETAILS_EXAMPLE } from '../../stories/shared';
Default story ok
const Default = () => <TextareaControl
    label="Label"
    description="This is the description."
    placeholder="Placeholder" />;
Visually Hidden Label story ok
const VisuallyHiddenLabel = () => <TextareaControl
    label="Label"
    description="This is the description."
    placeholder="Placeholder"
    hideLabelFromVision />;
With Details story ok
const WithDetails = () => <TextareaControl
    label="Label"
    description={undefined}
    placeholder="Placeholder"
    details={DETAILS_EXAMPLE} />;
Resize story ok
By default, the textarea is resizable in the vertical direction, using the `resize` handle at the bottom right. Although it is possible to modify or disable this [resize behavior through CSS](https://developer.mozilla.org/en-US/docs/Web/CSS/resize), we generally do not recommend it, as the default behavior is best for usability in most cases.
const Resize = () => <TextareaControl
    label="Label"
    description="This is the description."
    placeholder="Placeholder" />;
With Overflow story ok
const WithOverflow = () => <TextareaControl
    label="Label"
    description="This is the description."
    placeholder="Placeholder"
    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.`} />;
Disabled story ok
const Disabled = () => <TextareaControl
    label="Label"
    description="This is the description."
    placeholder="Placeholder"
    disabled />;

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 (react-component-meta) 2 prop types
Component: ../packages/components/src/text-highlight/index.tsx::default
Props:
/**
 * The string to search for and highlight within the `text`. Case
 * insensitive. Multiple matches.
 */
highlight: string = ''

/**
 * The string of text to be tested for occurrences of then given
 * `highlight`.
 */
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" />
    );
};

ToggleGroupControl

components-togglegroupcontrol · ../packages/components/src/toggle-group-control/stories/index.story.tsx
`ToggleGroupControl` is a form component that lets users choose options represented in horizontal segments. To render options for this control use `ToggleGroupControlOption` component. This component is intended for selecting a single persistent value from a set of options, similar to a how a radio button group would work. If you simply want a toggle to switch between views, use `Tabs` from `@wordpress/ui` instead. Only use this control when you know for sure the labels of items inside won't wrap. For items with longer labels, you can consider a `SelectControl` or a `CustomSelectControl` component instead. ```jsx import { __experimentalToggleGroupControl as ToggleGroupControl, __experimentalToggleGroupControlOption as ToggleGroupControlOption, } from '@wordpress/components'; function Example() { return ( <ToggleGroupControl label="my label" value="vertical" isBlock > <ToggleGroupControlOption value="horizontal" label="Horizontal" /> <ToggleGroupControlOption value="vertical" label="Vertical" /> </ToggleGroupControl> ); } ```
Prop types (react-component-meta) 13 prop types
Component: ../packages/components/src/toggle-group-control/index.ts::ToggleGroupControl
Props:
/**
 * Start opting into the larger default height that will become the default size in a future version.
 */
__next40pxDefaultSize?: boolean

/**
 * Start opting into the new margin-free styles that will become the default in a future version.
 */
__nextHasNoMarginBottom?: boolean

/**
 * The options to render in the `ToggleGroupControl`, using either the `ToggleGroupControlOption` or
 * `ToggleGroupControlOptionIcon` components.
 */
children: ReactNode

/**
 * Whether the control is disabled.
 */
disabled?: boolean = false

/**
 * Additional description for the control.
 * 
 * Only use for meaningful description or instructions for the control. An element containing the description will be programmatically associated to the BaseControl by the means of an `aria-describedby` attribute.
 */
help?: ReactNode

/**
 * If true, the label will only be visible to screen readers.
 */
hideLabelFromVision?: boolean = false

/**
 * Determines if segments should be rendered with equal widths.
 */
isAdaptiveWidth?: boolean = false

/**
 * Renders `ToggleGroupControl` as a (CSS) block element, spanning the entire width of
 * the available space. This is the recommended style when the options are text-based and not icons.
 */
isBlock?: boolean = false

/**
 * Whether an option can be deselected by clicking it again.
 */
isDeselectable?: boolean = false

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

/**
 * Callback when a segment is selected.
 */
onChange?: (value: string | number | undefined) => void

/**
 * The size variant of the control.
 */
size?: "default" | "__unstable-large"

/**
 * The selected value.
 */
value?: string | number | undefined
Imports
import { ToggleGroupControl, ToggleGroupControlOption, ToggleGroupControlOptionIcon } from '@wordpress/components';
import { formatUppercase, formatLowercase } from '@wordpress/icons';
Default incomplete example
const Default = ( {
	onChange,
	...props
} ) => {
	const [ value, setValue ] = useState< ToggleGroupControlProps[ 'value' ] >(
		props.value
	);

	return (
		<ToggleGroupControl
			{ ...props }
			onChange={ ( ...changeArgs ) => {
				setValue( ...changeArgs );
				onChange?.( ...changeArgs );
			} }
			value={ value }
		/>
	);
};
Incomplete snippet: `mapPropsToOptionComponent` could not be resolved statically.
With Tooltip incomplete example
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' ] >(
		props.value
	);

	return (
		<ToggleGroupControl
			{ ...props }
			onChange={ ( ...changeArgs ) => {
				setValue( ...changeArgs );
				onChange?.( ...changeArgs );
			} }
			value={ value }
		/>
	);
};
Incomplete snippet: `mapPropsToOptionComponent` could not be resolved statically.
With Icons incomplete example
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' ] >(
		props.value
	);

	return (
		<ToggleGroupControl
			{ ...props }
			onChange={ ( ...changeArgs ) => {
				setValue( ...changeArgs );
				onChange?.( ...changeArgs );
			} }
			value={ value }
		/>
	);
};
Incomplete snippet: `mapPropsToOptionIconComponent` could not be resolved statically.
Deselectable incomplete example
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' ] >(
		props.value
	);

	return (
		<ToggleGroupControl
			{ ...props }
			onChange={ ( ...changeArgs ) => {
				setValue( ...changeArgs );
				onChange?.( ...changeArgs );
			} }
			value={ value }
		/>
	);
};
Incomplete snippet: `mapPropsToOptionIconComponent` could not be resolved statically.
Disabled incomplete example
When the `disabled` prop is true, the control is unselectable.
const Disabled = ( {
	onChange,
	...props
} ) => {
	const [ value, setValue ] = useState< ToggleGroupControlProps[ 'value' ] >(
		props.value
	);

	return (
		<ToggleGroupControl
			{ ...props }
			onChange={ ( ...changeArgs ) => {
				setValue( ...changeArgs );
				onChange?.( ...changeArgs );
			} }
			value={ value }
		/>
	);
};
Incomplete snippet: `mapPropsToOptionComponent` could not be resolved statically.
ToggleGroupControlOption 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/toggle-group-control/index.ts
`ToggleGroupControlOption` is a form component and is meant to be used as a child of `ToggleGroupControl`. ```jsx import { __experimentalToggleGroupControl as ToggleGroupControl, __experimentalToggleGroupControlOption as ToggleGroupControlOption, } from '@wordpress/components'; function Example() { return ( <ToggleGroupControl label="my label" value="vertical" isBlock > <ToggleGroupControlOption value="horizontal" label="Horizontal" /> <ToggleGroupControlOption value="vertical" label="Vertical" /> </ToggleGroupControl> ); } ```
import { ToggleGroupControlOption } from '@wordpress/components';
Component: ../packages/components/src/toggle-group-control/index.ts::ToggleGroupControlOption (react-component-meta)
/**
 * Whether this option is unselectable.
 */
disabled?: boolean = false

/**
 * Label for the option. If needed, the `aria-label` prop can be used in addition
 * to specify a different label for assistive technologies.
 */
label: string

/**
 * Whether to display a Tooltip for the control option. If set to `true`, the tooltip will
 * show the aria-label or the label prop text.
 */
showTooltip?: boolean = false

value: string | number
ToggleGroupControlOptionIcon 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/toggle-group-control/index.ts
`ToggleGroupControlOptionIcon` is a form component which is meant to be used as a child of `ToggleGroupControl` and displays an icon. ```jsx import { __experimentalToggleGroupControl as ToggleGroupControl, __experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon, from '@wordpress/components'; import { formatLowercase, formatUppercase } from '@wordpress/icons'; function Example() { return ( <ToggleGroupControl> <ToggleGroupControlOptionIcon value="uppercase" label="Uppercase" icon={ formatUppercase } /> <ToggleGroupControlOptionIcon value="lowercase" label="Lowercase" icon={ formatLowercase } /> </ToggleGroupControl> ); } ```
import { ToggleGroupControlOptionIcon } from '@wordpress/components';
Component: ../packages/components/src/toggle-group-control/index.ts::ToggleGroupControlOptionIcon (react-component-meta)
/**
 * Whether this option is unselectable.
 */
disabled?: boolean = false

/**
 * Icon displayed as the content of the option. Usually one of the icons from
 * the `@wordpress/icons` package, or a custom React `<svg>` icon.
 */
icon: Element

/**
 * The text to accessibly label the icon option. Will also be shown in a tooltip.
 */
label: string

value: string | number

Tooltip.Root

design-system-components-tooltip · ../packages/ui/src/tooltip/stories/index.story.tsx
`Tooltip` is used to visually show the label of an icon button, or other such interactive controls that don't have a visual text label. Tooltip popups are visual-only and not exposed to assistive technologies. The trigger's accessible name (e.g. `aria-label`) is the source of truth for screen reader users. Tooltips are not available on touch devices, and thus should not be used for infotips, descriptions, or dynamic status messages.
see: {@link https://wordpress.github.io/gutenberg/?path=/docs/design-system-components-tooltip-usage-guidelines--docs Usage Guidelines}see: {@link https://wordpress.github.io/gutenberg/?path=/docs/design-system-components-iconbutton--docs IconButton}
Prop types (react-component-meta) 2 prop types
Component: ../packages/ui/src/tooltip/index.ts::Root
Props:
/**
 * The content of the tooltip.
 * This can be a regular React node or a render function that receives the `payload` of the active trigger.
 */
children?: ReactNode | PayloadChildRenderFunction<unknown>

/**
 * Whether the tooltip is disabled.
 */
disabled?: boolean = false
Imports
import { Icon, Popup, Portal, Positioner, Provider, Root, Trigger } from '@wordpress/ui';
import * as Tooltip from '../';
Default story ok
const Default = () => <Tooltip.Root>{[
        <Tooltip.Trigger aria-label="Save" key="trigger">
            💾
        </Tooltip.Trigger>,
        <Tooltip.Popup key="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>{[
        <Tooltip.Trigger aria-label="Save" key="trigger">
            💾
        </Tooltip.Trigger>,
        <Tooltip.Popup key="popup">Save</Tooltip.Popup>,
    ]}</Tooltip.Root>;
Positioning story ok
Customize where the tooltip appears relative to the trigger by passing a `<Tooltip.Positioner />` element to `Tooltip.Popup`'s `positioner` prop. `Tooltip.Positioner` accepts `side`, `align`, `sideOffset`, and collision settings; when `positioner` is omitted, the tooltip uses the defaults (`side="top"`, `align="center"`, `sideOffset={ 4 }`).
const Positioning = () => (
    <div
        style={ {
            display: 'flex',
            gap: '2rem',
            padding: '4rem',
            justifyContent: 'center',
        } }
    >
        <Tooltip.Root>
            <Tooltip.Trigger aria-label="Up">⬆️</Tooltip.Trigger>
            <Tooltip.Popup positioner={ <Tooltip.Positioner side="top" /> }>
                Up
            </Tooltip.Popup>
        </Tooltip.Root>

        <Tooltip.Root>
            <Tooltip.Trigger aria-label="Forward">➡️</Tooltip.Trigger>
            <Tooltip.Popup
                positioner={ <Tooltip.Positioner side="right" /> }
            >
                Forward
            </Tooltip.Popup>
        </Tooltip.Root>

        <Tooltip.Root>
            <Tooltip.Trigger aria-label="Down">⬇️</Tooltip.Trigger>
            <Tooltip.Popup
                positioner={ <Tooltip.Positioner side="bottom" /> }
            >
                Down
            </Tooltip.Popup>
        </Tooltip.Root>

        <Tooltip.Root>
            <Tooltip.Trigger aria-label="Back">⬅️</Tooltip.Trigger>
            <Tooltip.Popup
                positioner={ <Tooltip.Positioner side="left" /> }
            >
                Back
            </Tooltip.Popup>
        </Tooltip.Root>
    </div>
);
With Custom Positioner story ok
Beyond `side`, `Tooltip.Positioner` accepts the rest of the positioner surface — `align`, `alignOffset`, `sideOffset`, collision settings, and more — for fine-grained placement.
const WithCustomPositioner = () => <Tooltip.Root>{[
        <Tooltip.Trigger aria-label="Save" key="trigger">
            💾
        </Tooltip.Trigger>,
        <Tooltip.Popup
            positioner={
                <Tooltip.Positioner
                    side="right"
                    align="start"
                    sideOffset={ 16 }
                />
            }
            key="popup"
        >
            Save
        </Tooltip.Popup>,
    ]}</Tooltip.Root>;
With Custom z-index story ok
Popovers in Gutenberg are managed with explicit z-index values, which can create situations where a tooltip renders below another popover when you want it above. The `--wp-ui-tooltip-z-index` CSS variable controls the z-index of the tooltip's positioner. Override it either: - **Globally**, by setting the variable on `:root` or `body` (raises every tooltip in the page), or - **Per instance**, by passing a `Tooltip.Portal` with a `style` (or `className`) to `Tooltip.Popup`'s `portal` prop. The variable cascades from the portal wrapper to everything rendered inside it. This story demonstrates the per-instance approach.
const WithCustomZIndex = () => <Tooltip.Root>{[
        <Tooltip.Trigger aria-label="Save" key="trigger">
            💾
        </Tooltip.Trigger>,
        <Tooltip.Popup
            portal={
                <Tooltip.Portal
                    style={ { '--wp-ui-tooltip-z-index': '9999' } }
                />
            }
            key="popup"
        >
            Save
        </Tooltip.Popup>,
    ]}</Tooltip.Root>;
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>
);
Tooltip.Provider 4 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/tooltip/index.ts
import { Provider } from '@wordpress/ui';
Component: ../packages/ui/src/tooltip/index.ts::Provider (react-component-meta)
children?: ReactNode

/**
 * How long to wait before closing a tooltip. Specified in milliseconds.
 */
closeDelay?: number

/**
 * How long to wait before opening the tooltip on hover. Specified in milliseconds.
 */
delay?: number

/**
 * Another tooltip will open instantly if the previous tooltip
 * is closed within this timeout. Specified in milliseconds.
 */
timeout?: number = 400
Tooltip.Trigger 8 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/tooltip/index.ts
import { Trigger } from '@wordpress/ui';
Component: ../packages/ui/src/tooltip/index.ts::Trigger (react-component-meta)
/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

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

/**
 * How long to wait before closing the tooltip. Specified in milliseconds.
 */
closeDelay?: number = 0

/**
 * Whether the tooltip should close when this trigger is clicked.
 */
closeOnClick?: boolean = true

/**
 * How long to wait before opening the tooltip on hover. Specified in milliseconds.
 */
delay?: number = 600

/**
 * If `true`, the tooltip will not open when interacting with this trigger.
 * Note that this doesn't apply the `disabled` attribute to the trigger element.
 * If you want to disable the trigger element itself, you can pass the `disabled` prop to the trigger element via the `render` prop.
 */
disabled?: boolean = false

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Tooltip.Popup 6 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/tooltip/index.ts
import { Popup } from '@wordpress/ui';
Component: ../packages/ui/src/tooltip/index.ts::Popup (react-component-meta)
/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

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

/**
 * Optional portal element, typically `<Tooltip.Portal />` with custom
 * `container`. When omitted, `Tooltip.Popup` uses `Tooltip.Portal` with
 * default props. Do not pass `children` on the portal element; they would
 * be ignored.
 */
portal?: ReactElement<Omit<PortalProps, "children">, string | JSXElementConstructor<any>>

/**
 * Optional positioner element, typically `<Tooltip.Positioner />` with
 * custom positioning props (`side`, `align`, `sideOffset`, collision
 * settings, etc.). When omitted, `Tooltip.Popup` uses `Tooltip.Positioner`
 * with default props. Do not pass `children` on the positioner element;
 * they would be ignored.
 */
positioner?: ReactElement<Omit<PositionerProps, "children">, string | JSXElementConstructor<any>>

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Tooltip.Positioner 15 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/tooltip/index.ts
Used to apply custom positioning to `Tooltip`'s floating content.
import { Positioner } from '@wordpress/ui';
Component: ../packages/ui/src/tooltip/index.ts::Positioner (react-component-meta)
/**
 * How to align the popup relative to the specified side.
 */
align?: "center" | "end" | "start" = 'center'

/**
 * Additional offset along the alignment axis in pixels.
 * Also accepts a function that returns the offset to read the dimensions of the anchor
 * and positioner elements, along with its side and alignment.
 * 
 * The function takes a `data` object parameter with the following properties:
 * - `data.anchor`: the dimensions of the anchor element with properties `width` and `height`.
 * - `data.positioner`: the dimensions of the positioner element with properties `width` and `height`.
 * - `data.side`: which side of the anchor element the positioner is aligned against.
 * - `data.align`: how the positioner is aligned relative to the specified side.
 */
alignOffset?: number | OffsetFunction | undefined = 0

/**
 * An element to position the popup against.
 * By default, the popup will be positioned against the trigger.
 */
anchor?: Element | VirtualElement | RefObject<Element | null> | (() => Element | VirtualElement | null) | null | undefined

/**
 * Minimum distance to maintain between the arrow and the edges of the popup.
 * 
 * Use it to prevent the arrow element from hanging out of the rounded corners of a popup.
 */
arrowPadding?: number = 5

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

/**
 * Determines how to handle collisions when positioning the popup.
 * 
 * `side` controls overflow on the preferred placement axis (`top`/`bottom` or `left`/`right`):
 * - `'flip'`: keep the requested side when it fits; otherwise try the opposite side
 *   (`top` and `bottom`, or `left` and `right`).
 * - `'shift'`: never change side; keep the requested side and move the popup within
 *   the clipping boundary so it stays visible.
 * - `'none'`: do not correct side-axis overflow.
 * 
 * `align` controls overflow on the alignment axis (`start`/`center`/`end`):
 * - `'flip'`: keep side, but swap `start` and `end` when the requested alignment overflows.
 * - `'shift'`: keep side and requested alignment, then nudge the popup along the
 *   alignment axis to fit.
 * - `'none'`: do not correct alignment-axis overflow.
 * 
 * `fallbackAxisSide` controls fallback behavior on the perpendicular axis when the
 * preferred axis cannot fit:
 * - `'start'`: allow perpendicular fallback and try the logical start side first
 *   (`top` before `bottom`, or `left` before `right` in LTR).
 * - `'end'`: allow perpendicular fallback and try the logical end side first
 *   (`bottom` before `top`, or `right` before `left` in LTR).
 * - `'none'`: do not fallback to the perpendicular axis.
 * 
 * When `side` is `'shift'`, explicitly setting `align` only supports `'shift'` or `'none'`.
 * If `align` is omitted, it defaults to `'flip'`.
 */
collisionAvoidance?: CollisionAvoidance | undefined

/**
 * An element or a rectangle that delimits the area that the popup is confined to.
 */
collisionBoundary?: Boundary | undefined = 'clipping-ancestors'

/**
 * Additional space to maintain from the edge of the collision boundary.
 */
collisionPadding?: Padding | undefined = 5

/**
 * Whether to disable the popup from tracking any layout shift of its positioning anchor.
 */
disableAnchorTracking?: boolean = false

/**
 * Determines which CSS `position` property to use.
 */
positionMethod?: "fixed" | "absolute" = 'absolute'

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * Which side of the anchor element to align the popup against.
 * May automatically change to avoid collisions.
 */
side?: "left" | "right" | "bottom" | "top" | "inline-end" | "inline-start" = 'top'

/**
 * Distance between the anchor and the popup in pixels.
 * Also accepts a function that returns the distance to read the dimensions of the anchor
 * and positioner elements, along with its side and alignment.
 * 
 * The function takes a `data` object parameter with the following properties:
 * - `data.anchor`: the dimensions of the anchor element with properties `width` and `height`.
 * - `data.positioner`: the dimensions of the positioner element with properties `width` and `height`.
 * - `data.side`: which side of the anchor element the positioner is aligned against.
 * - `data.align`: how the positioner is aligned relative to the specified side.
 */
sideOffset?: number | OffsetFunction | undefined = 4

/**
 * Whether to maintain the popup in the viewport after
 * the anchor element was scrolled out of view.
 */
sticky?: boolean = false

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
Tooltip.Portal 5 prop types
/home/runner/work/gutenberg/gutenberg/packages/ui/src/tooltip/index.ts
Used to apply custom portal behavior to `Tooltip`'s floating content. `container` defaults to the `@wordpress/ui` compat overlay slot.
import { Portal } from '@wordpress/ui';
Component: ../packages/ui/src/tooltip/index.ts::Portal (react-component-meta)
/**
 * CSS class name to apply to the element.
 */
className?: string

/**
 * A parent element to render the portal element into.
 */
container?: HTMLElement | ShadowRoot | RefObject<HTMLElement | ShadowRoot | null> | null | undefined

/**
 * Whether to keep the portal mounted in the DOM while the popup is hidden.
 */
keepMounted?: boolean = false

/**
 * Replaces the component's default HTML element using a given React
 * element, or a function that returns a React element.
 */
render?: ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties

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 (react-component-meta) 5 prop types
Component: ../packages/components/src/tree-grid/index.tsx::default
Props:
/**
 * Label to use for the element with the `application` role.
 */
applicationAriaLabel?: string

/**
 * The children to be rendered in the tree grid.
 */
children: ReactNode

/**
 * Callback to fire when row is collapsed.
 */
onCollapseRow?: (row: HTMLElement) => void = () => {}

/**
 * Callback to fire when row is expanded.
 */
onExpandRow?: (row: HTMLElement) => void = () => {}

/**
 * Callback that fires when focus is shifted from one row to another via
 * the Up and Down keys. Callback is also fired on Home and End keys which
 * move focus from the beginning row to the end row.
 * 
 * The callback is passed the event, the start row element that the focus was on
 * originally, and the destination row element after the focus has moved.
 */
onFocusRow?: (event: KeyboardEvent<HTMLTableElement>, startRow: HTMLElement, destinationRow: HTMLElement) => void = () => {}
Imports
import { Button, InputControl, TreeGrid, TreeGridCell, TreeGridRow } from '@wordpress/components';
import { Fragment } from '@wordpress/element';
import { fn } from 'storybook/test';
Default incomplete example
const Default = () => <TreeGrid onExpandRow={fn()} onCollapseRow={fn()} onFocusRow={fn()}><Rows items={ groceries } /></TreeGrid>;
Incomplete snippet: `Rows`, `groceries` could not be resolved statically.
TreeGridRow 5 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/tree-grid/index.tsx
`TreeGridRow` 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.
see: {@link https://www.w3.org/TR/wai-aria-practices/examples/treegrid/treegrid-1.html}
import { TreeGridRow } from '@wordpress/components';
Component: ../packages/components/src/tree-grid/index.tsx::TreeGridRow (react-component-meta)
/**
 * The children to be rendered in the row.
 */
children: ReactNode

/**
 * An optional value that designates whether a row is expanded or collapsed.
 * Currently this value only sets the correct aria-expanded property on a row,
 * it has no other built-in behavior.
 * 
 * If there is a need to implement `aria-expanded` elsewhere in the row, cell,
 * or element within a cell, you may pass `isExpanded={ undefined }`.
 * In order for keyboard navigation to continue working, add the
 * `data-expanded` attribute with either `true`/`false`. This allows the
 * `TreeGrid` component to still manage keyboard interactions while allowing
 * the `aria-expanded` attribute to be placed elsewhere.
 */
isExpanded?: boolean

/**
 * An integer value designating the level in the hierarchical tree structure.
 * Counting starts at 1. A value of `1` indicates the root level of the structure.
 */
level: number

/**
 * An integer value that represents the position in the set.
 * A set is the count of elements at a specific level. Counting starts at 1.
 */
positionInSet: number

/**
 * An integer value that represents the total number of items in the set,
 * at this specific level of the hierarchy.
 */
setSize: number
TreeGridCell 2 prop types
/home/runner/work/gutenberg/gutenberg/packages/components/src/tree-grid/index.tsx
`TreeGridCell` 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.
see: {@link https://www.w3.org/TR/wai-aria-practices/examples/treegrid/treegrid-1.html}
import { TreeGridCell } from '@wordpress/components';
Component: ../packages/components/src/tree-grid/index.tsx::TreeGridCell (react-component-meta)
/**
 * A render function that receives the props necessary to make it participate in the
 * roving tabindex. Any extra props will also be passed through to this function.
 * 
 * Props passed as an argument to the render prop must be passed to the child
 * focusable component/element within the cell. If a component is used, it must
 * correctly handle the `onFocus`, `tabIndex`, and `ref` props, passing these to the
 * element it renders. These props are used to handle the roving tabindex functionality
 * of the tree grid.
 * 
 * ```jsx
 * <TreeGridCell>
 * 	{ ( props ) => (
 * 		<Button onClick={ doSomething } { ...props }>
 * 			Do something
 * 		</Button>
 * 	) }
 * </TreeGridCell>
 * ```
 */
children?: ReactNode | ((props: RovingTabIndexItemPassThruProps) => Element)

/**
 * Render `children` without wrapping it in a `TreeGridItem` component.
 * This means that `children` will not participate in the roving tabindex.
 */
withoutGridItem?: boolean = false

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 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 (react-component-meta) 18 prop types
Component: ../packages/components/src/tree-select/index.tsx::default
Props:
/**
 * Deprecated. Use `__next40pxDefaultSize` instead.
 */
__next36pxDefaultSize?: boolean = false

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

/**
 * Start opting into the new margin-free styles that will become the default in a future version.
 */
__nextHasNoMarginBottom?: boolean

/**
 * As an alternative to the `options` prop, `optgroup`s and `options` can be
 * passed in as `children` for more customizability.
 */
children?: ReactNode

/**
 * If true, the `input` will be disabled.
 */
disabled?: boolean = false

/**
 * Additional description for the control.
 * 
 * Only use for meaningful description or instructions for the control. An element containing the description will be programmatically associated to the BaseControl by the means of an `aria-describedby` attribute.
 */
help?: ReactNode

/**
 * If true, the label will only be visible to screen readers.
 */
hideLabelFromVision?: boolean = false

/**
 * If this property is added, a label will be generated using label property as the content.
 */
label?: ReactNode

/**
 * The position of the label.
 */
labelPosition?: "bottom" | "top" | "side" | "edge" = 'top'

/**
 * 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?: (value: string, extra?: { event?: ChangeEvent<HTMLSelectElement, Element> | undefined; } | undefined) => void

/**
 * An array of option property objects to be rendered,
 * each with a `label` and `value` property, as well as any other
 * `<option>` attributes.
 */
options?: readonly ({ label: string; value: string; } & Omit<OptionHTMLAttributes<HTMLOptionElement>, "label" | "value">)[]

/**
 * Renders an element on the left side of 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, wrap the element in
 * the provided `<InputControlPrefixWrapper>` component.
 * 
 * ```jsx
 * import {
 *   __experimentalInputControl as InputControl,
 *   __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper,
 * } from '@wordpress/components';
 * 
 * <InputControl
 *   prefix={<InputControlPrefixWrapper>@</InputControlPrefixWrapper>}
 * />
 * ```
 */
prefix?: ReactNode

/**
 * The id of the currently selected node.
 */
selectedId?: string

/**
 * Adjusts the size of the input.
 */
size?: "small" | "default" | "compact" = 'default'

/**
 * Renders an element on the right side of 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, wrap the element in
 * the provided `<InputControlSuffixWrapper>` component.
 * 
 * ```jsx
 * import {
 *   __experimentalInputControl as InputControl,
 *   __experimentalInputControlSuffixWrapper as InputControlSuffixWrapper,
 * } from '@wordpress/components';
 * 
 * <InputControl
 *   suffix={<InputControlSuffixWrapper>%</InputControlSuffixWrapper>}
 * />
 * ```
 */
suffix?: ReactNode

/**
 * An array containing the tree objects with the possible nodes the user can select.
 */
tree?: Tree[] = []

/**
 * The style variant of the control.
 */
variant?: "default" | "minimal" = 'default'
Imports
import { TreeSelect } from '@wordpress/components';
Default story ok
const Default = ( props ) => {
	const [ selection, setSelection ] =
		useState< ComponentProps< typeof TreeSelect >[ 'selectedId' ] >();

	return (
		<TreeSelect
			{ ...props }
			onChange={ setSelection }
			selectedId={ selection }
		/>
	);
};

Truncate

components-truncate · ../packages/components/src/truncate/stories/index.story.tsx
`Truncate` is a typography primitive that trims text content. For almost all cases, it is recommended that `Text`, `Heading`, or `Subheading` is used to render text content. However,`Truncate` is available for custom implementations. ```jsx import { __experimentalTruncate as Truncate } from `@wordpress/components`; function Example() { return ( <Truncate> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ex neque, vulputate a diam et, luctus convallis lacus. Vestibulum ac mollis mi. Morbi id elementum massa. </Truncate> ); } ```
Prop types (react-component-meta) 6 prop types
Component: ../packages/components/src/truncate/index.ts::Truncate
Props:
/**
 * The HTML element or React component to render the component as.
 */
as?: JSXElementConstructor<any> | keyof IntrinsicElements | undefined

/**
 * The children elements.
 * 
 * Note: text truncation will be attempted only if the `children` are either
 * of type `string` or `number`. In any other scenarios, the component will
 * not attempt to truncate the text, and will pass through the `children`.
 */
children: ReactNode

/**
 * The ellipsis string when truncating the text by the `limit` prop's value.
 */
ellipsis?: string = '…'

/**
 * Determines where to truncate.  For example, we can truncate text right in
 * the middle. To do this, we need to set `ellipsizeMode` to `middle` and a
 * text `limit`.
 * 
 * * `auto`: Trims content at the end automatically without a `limit`.
 * * `head`: Trims content at the beginning. Requires a `limit`.
 * * `middle`: Trims content in the middle. Requires a `limit`.
 * * `tail`: Trims content at the end. Requires a `limit`.
 */
ellipsizeMode?: "head" | "none" | "auto" | "middle" | "tail" = 'auto'

/**
 * Determines the max number of characters to be displayed before the rest
 * of the text gets truncated. Requires `ellipsizeMode` to assume values
 * different from `auto` and `none`.
 */
limit?: number = 0

/**
 * Clamps the text content to the specified `numberOfLines`, adding an
 * ellipsis at the end. Note: this feature ignores the value of the
 * `ellipsis` prop and always displays the default `…` ellipsis.
 */
numberOfLines?: number = 0
Imports
import { Truncate } from '@wordpress/components';
Default story ok
const Default = () => {
    return <Truncate numberOfLines={2}>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut facilisis dictum tortor, eu tincidunt justo scelerisque tincidunt. Duis semper dui id augue malesuada, ut feugiat nisi aliquam. Vestibulum venenatis diam sem, finibus dictum massa semper in. Nulla facilisi. Nunc vulputate faucibus diam, in lobortis arcu ornare vel. In dignissim nunc sed facilisis finibus. Etiam imperdiet mattis arcu, sed rutrum sapien blandit gravida. Aenean sollicitudin neque eget enim blandit, sit amet rutrum leo vehicula. Nunc malesuada ultricies eros ut faucibus. Aliquam erat volutpat. Nulla nec feugiat risus. Vivamus iaculis dui aliquet ante ultricies feugiat. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Vivamus nec pretium velit, sit amet consectetur ante. Praesent porttitor ex eget fermentum mattis.</Truncate>;
};
Truncate by character count story ok
const CharacterCount = () => {
    return <Truncate limit={23} ellipsizeMode="tail" ellipsis="[---]">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut facilisis dictum tortor, eu tincidunt justo scelerisque tincidunt. Duis semper dui id augue malesuada, ut feugiat nisi aliquam. Vestibulum venenatis diam sem, finibus dictum massa semper in. Nulla facilisi. Nunc vulputate faucibus diam, in lobortis arcu ornare vel. In dignissim nunc sed facilisis finibus. Etiam imperdiet mattis arcu, sed rutrum sapien blandit gravida. Aenean sollicitudin neque eget enim blandit, sit amet rutrum leo vehicula. Nunc malesuada ultricies eros ut faucibus. Aliquam erat volutpat. Nulla nec feugiat risus. Vivamus iaculis dui aliquet ante ultricies feugiat. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Vivamus nec pretium velit, sit amet consectetur ante. Praesent porttitor ex eget fermentum mattis.</Truncate>;
};

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 onChange={ setValue } value={ value } />; }; ```
Prop types (react-component-meta) 37 prop types
Component: ../packages/components/src/unit-control/index.tsx::UnitControl
Props:
/**
 * Deprecated. Use `__next40pxDefaultSize` instead.
 */
__next36pxDefaultSize?: boolean = false

__next40pxDefaultSize?: boolean

__unstableInputWidth?: Width<string | number> | undefined

__unstableStateReducer?: StateReducer

/**
 * If true, the `input` will be disabled.
 */
disabled?: boolean = false

/**
 * If `true`, the unit `<select>` is hidden.
 */
disableUnits?: boolean = false

/**
 * Determines the drag axis.
 */
dragDirection?: "s" | "n" | "e" | "w" = 'n'

/**
 * If `isDragEnabled` is true, this controls the amount of `px` to have been dragged before
 * the drag gesture is actually triggered.
 */
dragThreshold?: number = 10

/**
 * Additional description for the control.
 * 
 * Only use for meaningful description or instructions for the control. An element containing the description will be programmatically associated to the BaseControl by the means of an `aria-describedby` attribute.
 */
help?: ReactNode

/**
 * If true, the default `input` HTML arrows will be hidden.
 */
hideHTMLArrows?: boolean = false

/**
 * If true, the label will only be visible to screen readers.
 */
hideLabelFromVision?: boolean = false

/**
 * If true, enables mouse drag gestures.
 */
isDragEnabled?: boolean = true

/**
 * If true, the `ENTER` key press is required in order to trigger an `onChange`.
 * If enabled, a change is also triggered when tabbing away (`onBlur`).
 */
isPressEnterToChange?: boolean = false

/**
 * If `true`, and the selected unit provides a `default` value, this value is set
 * when changing units.
 */
isResetValueOnUnitChange?: boolean = false

/**
 * If true, pressing `UP` or `DOWN` along with the `SHIFT` key will increment the
 * value by the `shiftStep` value.
 */
isShiftStepEnabled?: boolean = true

/**
 * Whether the control can be focused via keyboard navigation.
 */
isUnitSelectTabbable?: boolean = true

/**
 * If this property is added, a label will be generated using label property as the content.
 */
label?: ReactNode

/**
 * The position of the label.
 */
labelPosition?: "bottom" | "top" | "side" | "edge" = 'top'

/**
 * The maximum `value` allowed.
 */
max?: number = Infinity

/**
 * The minimum `value` allowed.
 */
min?: number = -Infinity

/**
 * Callback when either the quantity or the unit inputs lose focus.
 */
onBlur?: FocusEventHandler<HTMLInputElement> & FocusEventHandler<HTMLInputElement | HTMLSelectElement>

/**
 * A callback function invoked when the value is changed.
 * A function that receives the value of the input.
 */
onChange?: UnitControlOnChangeCallback & InputChangeCallback<{}>

onDrag?: (dragProps: Omit<FullGestureState<"drag">, "event"> & { event: unknown; }) => void

onDragEnd?: (dragProps: Omit<FullGestureState<"drag">, "event"> & { event: unknown; }) => void

onDragStart?: (dragProps: Omit<FullGestureState<"drag">, "event"> & { event: unknown; }) => void

/**
 * Callback when either the quantity or the unit inputs gains focus.
 */
onFocus?: FocusEventHandler<HTMLInputElement> & FocusEventHandler<HTMLInputElement | HTMLSelectElement>

/**
 * Callback when the `unit` changes.
 */
onUnitChange?: UnitControlOnChangeCallback

onValidate?: (nextValue: string, event?: SyntheticEvent<HTMLInputElement, Event> | undefined) => void

/**
 * Renders an element on the left side of 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, wrap the element in
 * the provided `<InputControlPrefixWrapper>` component.
 * 
 * ```jsx
 * import {
 *   __experimentalInputControl as InputControl,
 *   __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper,
 * } from '@wordpress/components';
 * 
 * <InputControl
 *   prefix={<InputControlPrefixWrapper>@</InputControlPrefixWrapper>}
 * />
 * ```
 */
prefix?: ReactNode

/**
 * If `true` enforces a valid number within the control's min/max range.
 * If `false` allows an empty string as a valid value.
 */
required?: boolean = false

/**
 * Amount to increment by when the `SHIFT` key is held down. This shift value is
 * a multiplier to the `step` value. For example, if the `step` value is `5`,
 * and `shiftStep` is `10`, each jump would increment/decrement by `50`.
 */
shiftStep?: number = 10

/**
 * Adjusts the size of the input.
 */
size?: "small" | "default" | "compact" = 'default'

/**
 * Optional multiplication factor in spin changes. i.e. A spin changes
 * by `spinFactor * step` (if `step` is "any", 1 is used instead).
 */
spinFactor?: number = 1

/**
 * Amount by which the `value` is changed when incrementing/decrementing.
 * It is also a factor in validation as `value` must be a multiple of `step`
 * (offset by `min`, if specified) to be valid. Accepts the special string value `any`
 * that voids the validation constraint and causes stepping actions to increment/decrement by `1`.
 */
step?: string | number | undefined = 1

/**
 * Current unit. _Note: this prop is deprecated. Instead, provide a unit with a value through the `value` prop._
 */
unit?: string

/**
 * Available units to select from.
 */
units?: WPUnitControlUnit[] = [
	allUnits.px,
	allUnits[ '%' ],
	allUnits.em,
	allUnits.rem,
	allUnits.vw,
	allUnits.vh,
]

/**
 * The value of the input.
 * Current value. If passed as a string, the current unit will be inferred from this value.
 * For example, a `value` of "50%" will set the current unit to `%`.
 */
value?: string | number | undefined
Imports
import { UnitControl } from '@wordpress/components';
import { fn } from 'storybook/test';
import { CSS_UNITS } from '../utils';
Default story ok
const Default = () => {
    const [ value, setValue ] = useState< string | undefined >( '10px' );

    return (
        <UnitControl
            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
            onUnitChange={fn()}
            onFocus={fn()}
            onBlur={fn()}
            label="Label"
            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
            onUnitChange={fn()}
            onFocus={fn()}
            onBlur={fn()}
            label="Custom label"
            min={0}
            max={100}
            step="any"
            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
            onUnitChange={fn()}
            onFocus={fn()}
            onBlur={fn()}
            label="Label"
            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
            onUnitChange={fn()}
            onFocus={fn()}
            onBlur={fn()}
            label="Label"
            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 );
			} } />
    );
};

ValidityIndicator

design-system-components-form-primitives-validityindicator · ../packages/ui/src/form/primitives/validity-indicator/stories/index.story.tsx
Displays a validity message for a form control, with an icon matching the validity state: invalid, valid, or validating (a spinner while an async check is pending). `ControlWithError` renders it automatically; use it directly to give a custom validated control the same presentation.
Prop types (react-component-meta) 3 prop types
Component: ../packages/ui/src/form/primitives/validity-indicator/index.ts::ValidityIndicator
Props:
/**
 * The `id` to apply to the indicator element, so it can be associated
 * with the control via `aria-describedby`.
 */
id?: string

/**
 * The message to display next to the status icon.
 */
message?: string

/**
 * The validation status to indicate.
 */
type: "invalid" | "validating" | "valid"
Imports
import { ValidityIndicator } from '@wordpress/ui';
Invalid story ok
const Invalid = () => <ValidityIndicator type="invalid" message="Please enter a valid URL." />;
Valid story ok
const Valid = () => <ValidityIndicator type="valid" message="This URL is available." />;
Validating story ok
const Validating = () => <ValidityIndicator type="validating" message="Checking availability…" />;

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. Renders a `<div>` by default. Use the `render` prop to swap the underlying element while preserving the visually-hidden behavior. ## Composing with other components When composing with another component that uses the `render` prop pattern, keep `VisuallyHidden` as the **host** (outer component) and pass the other component via `render`. This keeps the other component's HTML element and semantics intact, while `VisuallyHidden` only adds its hiding styles: ```jsx // OtherComponent keeps its semantic element (e.g. <h2>). <VisuallyHidden render={ <OtherComponent /> }> Accessible text </VisuallyHidden> ```
Prop types (react-component-meta) 4 prop types
Component: ../packages/ui/src/visually-hidden/index.ts::VisuallyHidden
Props:
/**
 * The content to be rendered inside the component.
 */
children?: ReactNode

/**
 * CSS class name to apply to the element.
 */
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<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

/**
 * CSS style to apply to the element.
 */
style?: CSSProperties
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>
    </>
);
With Custom Element story ok
Use the `render` prop to change the underlying HTML element. By default, `VisuallyHidden` renders a `<div>`. Here it renders a `<label>` instead, keeping the native label–input association while hiding the label text visually.
const WithCustomElement = function WithCustomElementStory() {
    const inputId = useId();
    return (
        <>
            { /* eslint-disable-next-line jsx-a11y/label-has-associated-control */ }
            <VisuallyHidden render={ <label htmlFor={ inputId } /> }>
                Accessible label
            </VisuallyHidden>
            <input
                id={ inputId }
                placeholder="This input has a visually hidden label"
            />
        </>
    );
};