@antadesign/anta
    Preparing search index...

    Interface SelectCommonProps<V>Unreviewed

    Props shared by both selection modes, intersected into SelectProps. Exported (and kept as an interface intersected — not a union base via extends) so its members read as Select's own props in the generated docs, not inherited.

    interface SelectCommonProps<V extends OptionValue = string> {
        options: SelectItem<V>[];
        placement?:
            | "left"
            | "right"
            | "bottom"
            | "top"
            | "bottom-start"
            | "bottom-end"
            | "top-start"
            | "top-end"
            | "right-start"
            | "right-end"
            | "left-start"
            | "left-end";
        offset?: number;
        indicator?: "none"
        | "check"
        | "radio";
        placeholder?: string;
        icon?: keyof IconShapes;
        leading?: ReactNode;
        label?: string;
        hint?: string;
        size?: "small" | "medium" | "large";
        status?: "neutral" | "brand" | "info" | "success" | "warning" | "critical";
        statusIcon?: string & {} | false | (keyof IconShapes);
        round?: boolean | number | string;
        disabled?: boolean;
        tone?:
            | "neutral"
            | "brand"
            | "info"
            | "success"
            | "warning"
            | "critical"
            | string & {};
        toneScope?: ToneScope;
        filter?: boolean
        | ((option: SelectOption<V>, query: string) => boolean);
        selectAll?: boolean;
        selectAllLabel?: string;
        clearable?: boolean;
        clearLabel?: string;
        renderOption?: (
            option: SelectOption<V>,
            state: OptionState<V>,
        ) => ReactNode;
        renderIndicator?: (state: OptionState<V>) => ReactNode;
        verbose?: boolean;
        renderSummary?: (selected: SelectOption<V>[]) => string | undefined;
        renderTrigger?: (state: TriggerState<V>) => ReactNode;
        renderEmpty?: (state: EmptyState) => ReactNode;
        className?: string;
        style?: CSSProperties;
        id?: string;
        title?: string;
        slot?: string;
        tabIndex?: number;
        key?: string | number | null;
        [key: `data-${string}`]: unknown;
        [key: `aria-${string}`]: unknown;
    }

    Type Parameters

    Hierarchy

    • Omit<BaseProps, "children">
      • SelectCommonProps

    Indexable

    • [key: `data-${string}`]: unknown
    • [key: `aria-${string}`]: unknown
    Index
    options: SelectItem<V>[]

    The options to choose from — bare strings, SelectOption objects, SelectGroups (inline titled sections), or SelectSubmenus (flyout branches). Groups and submenus nest and mix with plain options. Selection stays global (one value, leaf options only); a filter query flattens the tree into grouped results.

    Select infers its value type V from these options: { value: 365 } makes onValueChange report number. A mix of value types widens V to the union.

    Each leaf value is the option's identity and must be unique across the whole tree (selection is value-keyed, so a value repeated in two sections is one logical pick: both rows toggle together, the trigger resolves to the last). Values that stringify alike (365 and "365") also collide as row keys; dev builds console.warn on either.

    placement?:
        | "left"
        | "right"
        | "bottom"
        | "top"
        | "bottom-start"
        | "bottom-end"
        | "top-start"
        | "top-end"
        | "right-start"
        | "right-end"
        | "left-start"
        | "left-end"

    Preferred placement of the options menu relative to the trigger. The menu auto-flips vertically and clamps horizontally when needed.

    bottom-start
    
    offset?: number

    Gap in pixels between the trigger and the options menu.

    4
    
    indicator?: "none" | "check" | "radio"

    The per-row mark for single-select: 'none' (a tint-only highlight), 'check' (a trailing checkmark on the selected row, keeping the tint — the canonical Select look), or 'radio' (a leading radio on every row). Multi-select always uses checkboxes.

    none
    
    placeholder?: string

    Text shown when nothing is selected.

    icon?: keyof IconShapes

    Leading icon shown at the left of the field. With a custom renderTrigger, it's passed through as state.icon instead — the consumer places it.

    leading?: ReactNode

    Content before the default trigger's value, such as a key prefix before the value. It replaces the icon derived from icon. Include an <Icon> in this content when both are needed. Ignored by renderTrigger.

    label?: string

    Field label, above the trigger.

    hint?: string

    Helper text under the field.

    size?: "small" | "medium" | "large"

    Field size.

    medium
    
    status?: "neutral" | "brand" | "info" | "success" | "warning" | "critical"

    Validation/feedback tone for the field.

    neutral
    
    statusIcon?: string & {} | false | (keyof IconShapes)

    Glyph shown before the hint when status is set. Each status has a default; pass a shape to override, or false to drop it.

    round?: boolean | number | string

    Round the field corners — true for fully round, or a number / CSS length.

    disabled?: boolean

    Disable the whole select.

    tone?:
        | "neutral"
        | "brand"
        | "info"
        | "success"
        | "warning"
        | "critical"
        | string & {}

    Default option-row tone. An option's own tone wins. A named tone or a custom CSS color. Most visible with tint-based marks (indicator 'none' / 'check'); with 'radio' / 'checkbox' it also tones the indicator.

    toneScope?: ToneScope

    Apply the default row tone in every state, or only to selected rows. An option's own toneScope wins.

    'all'
    
    filter?: boolean | ((option: SelectOption<V>, query: string) => boolean)

    Add a search field at the top of the menu that filters the options as you type. true uses the built-in matcher — a case-insensitive substring of the option's value / label / hint. Pass a function (option, query) => boolean for custom matching (called per option; return true to keep it).

    selectAll?: boolean

    multiple only: shows a "Select all" row that toggles every enabled option, or only the visible options when a filter query is active. Its checkbox is mixed when some options are selected. It is on by default. Set it to false to remove the row and the Alt/Option-click shortcut that selects only one row.

    true
    
    selectAllLabel?: string

    Label for the selectAll row.

    Select all
    
    clearable?: boolean

    Add a "Clear" row pinned in the menu footer that empties the selection (single → none, multiple → []). Shown only while something is selected, so it never scrolls away in a long or filtered list.

    clearLabel?: string

    Label for the clearable footer row.

    Clear
    
    renderOption?: (option: SelectOption<V>, state: OptionState<V>) => ReactNode

    Replaces the built-in label, hint, and icon layout for each option row. Select still supplies the row container, click handling, ARIA attributes, and selection indicator. Read extra option fields through SelectOption's index signature. state contains value, selected, and disabled. Filtering still matches the option's value, label, and hint, but Select cannot highlight matches within the returned content.

    renderIndicator?: (state: OptionState<V>) => ReactNode

    Replace each row's selection mark with your own node, drawn at the leading edge. The row stays the control (role + aria-checked from indicator / selection); only the drawn mark changes, so pair it with an indicator ('check' / 'radio') or selection="multiple" for the semantics. Composes with renderOption.

    verbose?: boolean

    multiple only: spell the picks out in the count summary — 3 selected: A, B, C (labels comma-joined) in place of the bare 3 selected. Applies to the multi-count case only: All stays All, a single pick stays its own label, and an empty selection stays the placeholder. The list flows into the Button label, so it ellipsizes at the field's width when long (3 selected: Engineering, Des… ). renderSummary overrides this.

    renderSummary?: (selected: SelectOption<V>[]) => string | undefined

    multiple only: build the trigger's selection summary text yourself, replacing the built-in "All / one label / N selected" logic. Receives the resolved selected options (selected.length is the count) and runs only while something is selected — an empty selection still shows the placeholder. Return a string: it flows into the default trigger's Button label, so a long summary ellipsizes at the field's width just like a long value (Engineering, Design, … ). Return undefined to fall back to the default for that case (e.g. customize only the count, keeping the single-label case built-in). For rich content (chips, multiple nodes) use renderTrigger, which replaces the whole field.

    renderTrigger?: (state: TriggerState<V>) => ReactNode

    Replaces the default field with a trigger returned from this function. Receives open, value, selected, disabled, and icon. Return exactly one focusable element, such as an Anta Button. The menu is positioned relative to that element and opens when it is clicked. Do not return a fragment, multiple siblings, or a non-focusable wrapper. Add aria-haspopup={filter ? 'dialog' : 'menu'} and aria-expanded={state.open} to the returned button. An Anta Button already carries the correct role. Field props (label, hint, size, status, placeholder, and round) and className / style apply only to the default field. Add styling and attributes to the returned element instead.

    renderEmpty?: (state: EmptyState) => ReactNode

    Render content in the menu body when the (filtered) option list is empty — a "no results" message, a loading indicator (gated on your own external loading state), or a "create from the query" row. Receives an EmptyState (query, trimmed). There is no built-in empty message: when omitted, an empty list renders nothing. Whatever you return goes where the option rows would — a plain node is inert; return a MenuItem (e.g. a "Create" row) to make it focusable and selectable.

    className?: string

    CSS class on the component's root element (merged with the component's own classes). Use it directly for layout and positioning — grid/flex placement, margins, alignment — rather than wrapping the component in a <div>/<span>.

    style?: CSSProperties

    Inline styles on the component's root element. Set layout/positioning here (or via className) directly on the component instead of adding a wrapper.

    id?: string

    HTML id attribute.

    title?: string

    HTML title attribute — native browser tooltip on hover.

    slot?: string

    Assigns the element to a named <slot> of a parent web component (e.g. slot="header" inside a <Card>, slot="footer" inside a <Dialog>).

    tabIndex?: number

    Tab order. Set to -1 to skip the element when tabbing.

    key?: string | number | null

    React/Preact reconciliation key when rendered inside a list. Consumed by the JSX runtime (not forwarded as a DOM attribute).