# Select

Lets a user choose one option from a list in a popup.

## Installation

```tsx
import {
  Select,
  SelectContent,
  SelectItem,
  SelectLabel,
  SelectList,
  SelectTrigger,
} from "@makeplane/propel/components/select";
```
## Usage

```tsx
import {
  Select,
  SelectContent,
  SelectItem,
  SelectLabel,
  SelectList,
  SelectTrigger,
} from "@makeplane/propel/components/select";
import { SelectField } from "@makeplane/propel/elements/select";

const SERVER_TYPES = [
  { label: "General purpose", value: "general" },
  { label: "Compute optimized", value: "compute" },
  { label: "Memory optimized", value: "memory" },
];

export default function BasicDemo() {
  return (
    <Select items={SERVER_TYPES} defaultValue="general">
      <SelectField>
        <SelectLabel size="lg">Server type</SelectLabel>
        <SelectTrigger size="lg" />
      </SelectField>
      <SelectContent>
        <SelectList>
          {SERVER_TYPES.map(({ label, value }) => (
            <SelectItem key={value} value={value} label={label} />
          ))}
        </SelectList>
      </SelectContent>
    </Select>
  );
}
```
## Examples

### Placeholder

Without a `defaultValue`, the trigger shows its `placeholder` until an option is picked.

```tsx
import {
  Select,
  SelectContent,
  SelectItem,
  SelectLabel,
  SelectList,
  SelectTrigger,
} from "@makeplane/propel/components/select";
import { SelectField } from "@makeplane/propel/elements/select";

const SERVER_TYPES = [
  { label: "General purpose", value: "general" },
  { label: "Compute optimized", value: "compute" },
  { label: "Memory optimized", value: "memory" },
];

export default function PlaceholderDemo() {
  return (
    <Select items={SERVER_TYPES}>
      <SelectField>
        <SelectLabel size="lg">Server type</SelectLabel>
        <SelectTrigger size="lg" placeholder="Choose a server type" />
      </SelectField>
      <SelectContent>
        <SelectList>
          {SERVER_TYPES.map(({ label, value }) => (
            <SelectItem key={value} value={value} label={label} />
          ))}
        </SelectList>
      </SelectContent>
    </Select>
  );
}
```

### Multiple

```tsx
import {
  Select,
  SelectContent,
  SelectItem,
  SelectLabel,
  SelectList,
  SelectTrigger,
} from "@makeplane/propel/components/select";
import { SelectField } from "@makeplane/propel/elements/select";

const SERVER_TYPES = [
  { label: "General purpose", value: "general" },
  { label: "Compute optimized", value: "compute" },
  { label: "Memory optimized", value: "memory" },
];

export default function MultipleDemo() {
  return (
    <Select multiple items={SERVER_TYPES} defaultValue={["general", "compute"]}>
      <SelectField>
        <SelectLabel size="lg">Server types</SelectLabel>
        <SelectTrigger size="lg" />
      </SelectField>
      <SelectContent>
        <SelectList>
          {SERVER_TYPES.map(({ label, value }) => (
            <SelectItem key={value} value={value} label={label} />
          ))}
        </SelectList>
      </SelectContent>
    </Select>
  );
}
```

### Select all and footer

`SelectContent` pins sticky content above and below the scrolling list: `header` and `footer`. For a
`multiple` select, put a `SelectSelectAll` row (and a `SelectSeparator`) in a `SelectStickyList` in
the `header`, wired to the controlled `value`: it shows a dash while only some options are picked.
A `SelectFooter` in the `footer` holds a hint or a count.

```tsx
import {
  Select,
  SelectContent,
  SelectFooter,
  SelectItem,
  SelectLabel,
  SelectList,
  SelectSelectAll,
  SelectSeparator,
  SelectStickyList,
  SelectTrigger,
} from "@makeplane/propel/components/select";
import { SelectField } from "@makeplane/propel/elements/select";
import { useState } from "react";

const SERVER_TYPES = [
  { label: "General purpose", value: "general" },
  { label: "Compute optimized", value: "compute" },
  { label: "Memory optimized", value: "memory" },
];

export default function SelectAllDemo() {
  const [value, setValue] = useState<string[]>(["general"]);
  const allSelected = value.length === SERVER_TYPES.length;
  return (
    <Select multiple items={SERVER_TYPES} value={value} onValueChange={setValue}>
      <SelectField>
        <SelectLabel size="lg">Server types</SelectLabel>
        <SelectTrigger size="lg" placeholder="Choose server types" />
      </SelectField>
      <SelectContent
        header={
          <SelectStickyList>
            <SelectSelectAll
              checked={allSelected}
              indeterminate={value.length > 0 && !allSelected}
              onClick={() => setValue(allSelected ? [] : SERVER_TYPES.map((type) => type.value))}
            />
            <SelectSeparator />
          </SelectStickyList>
        }
        footer={
          <SelectFooter>
            {value.length} of {SERVER_TYPES.length} selected
          </SelectFooter>
        }
      >
        <SelectList>
          {SERVER_TYPES.map((type) => (
            <SelectItem key={type.value} value={type.value} label={type.label} />
          ))}
        </SelectList>
      </SelectContent>
    </Select>
  );
}
```

### Grouped

Group related options under a `SelectGroup` with a `SelectGroupLabel`, and divide the groups with a
`SelectSeparator`. The label's `meta` pins content at its end, such as a count; it is left out of
the group's accessible name.

```tsx
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectGroupLabel,
  SelectItem,
  SelectLabel,
  SelectList,
  SelectSeparator,
  SelectTrigger,
} from "@makeplane/propel/components/select";
import { SelectField } from "@makeplane/propel/elements/select";
import { Fragment } from "react";

const REGION_GROUPS = [
  {
    label: "Americas",
    items: [
      { label: "US Central 1", value: "us-central-1" },
      { label: "US East 1", value: "us-east-1" },
    ],
  },
  {
    label: "Europe",
    items: [
      { label: "EU Central 1", value: "eu-central-1" },
      { label: "EU West 1", value: "eu-west-1" },
    ],
  },
];

export default function GroupedDemo() {
  return (
    <Select items={REGION_GROUPS.flatMap((group) => group.items)} defaultValue="us-central-1">
      <SelectField>
        <SelectLabel size="lg">Region</SelectLabel>
        <SelectTrigger size="lg" />
      </SelectField>
      <SelectContent>
        <SelectList>
          {REGION_GROUPS.map((group, index) => (
            <Fragment key={group.label}>
              {index > 0 ? <SelectSeparator /> : null}
              <SelectGroup>
                <SelectGroupLabel meta={group.items.length}>{group.label}</SelectGroupLabel>
                {group.items.map(({ label, value }) => (
                  <SelectItem key={value} value={value} label={label} />
                ))}
              </SelectGroup>
            </Fragment>
          ))}
        </SelectList>
      </SelectContent>
    </Select>
  );
}
```

### Option details

`secondaryText` adds muted text after an option's label, and `description` a muted second line (the
row grows to fit it). `trailing` pins content at the row's end, after the check. The trigger shows
the `label` alone.

```tsx
import { Badge } from "@makeplane/propel/components/badge";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectLabel,
  SelectList,
  SelectTrigger,
} from "@makeplane/propel/components/select";
import { SelectField } from "@makeplane/propel/elements/select";

const PLANS = [
  { label: "Starter", value: "starter", secondaryText: "Free", description: "1 vCPU · 1 GB RAM" },
  { label: "Pro", value: "pro", secondaryText: "$20/mo", description: "2 vCPU · 4 GB RAM" },
  {
    label: "Enterprise",
    value: "enterprise",
    secondaryText: "Custom",
    description: "Dedicated hosts, SSO and audit logs",
  },
];

export default function ItemDetailsDemo() {
  return (
    <Select items={PLANS} defaultValue="pro">
      <SelectField>
        <SelectLabel size="lg">Plan</SelectLabel>
        <SelectTrigger size="lg" />
      </SelectField>
      <SelectContent>
        <SelectList>
          {PLANS.map(({ label, value, secondaryText, description }) => (
            <SelectItem
              key={value}
              value={value}
              label={label}
              secondaryText={secondaryText}
              description={description}
              trailing={
                value === "pro" ? <Badge size="xs" variant="brand" label="Popular" /> : undefined
              }
            />
          ))}
        </SelectList>
      </SelectContent>
    </Select>
  );
}
```

### Popup width

`SelectContent` matches the trigger's width by default (`sizing="anchor"`). `sizing="auto"` sizes
the popup to its options instead, between 204px and 400px, for a trigger whose options need more (or
less) room than it has.

### Trigger width

Field-style triggers use `width="auto"` by default, preserving the existing 288px minimum while
allowing the trigger to grow. Use `width="fit"` when a `secondary` or `ghost` trigger should hug
its rendered icon, value, chevron, gaps, and padding. This does not change `SelectContent` sizing;
an anchor-sized popup can still grow wider than a compact trigger when its options need more room.
The `pill` variant is already intrinsically sized and does not accept `width`.

```tsx
import {
  Select,
  SelectContent,
  SelectItem,
  SelectLabel,
  SelectList,
  SelectTrigger,
  type SelectTriggerWidth,
} from "@makeplane/propel/components/select";
import { SelectField } from "@makeplane/propel/elements/select";

const PLANS = [
  { label: "Starter", value: "starter" },
  { label: "A considerably longer enterprise plan", value: "enterprise" },
];

const WIDTHS: SelectTriggerWidth[] = ["auto", "fit"];

export default function FitWidthDemo() {
  return (
    <div className="flex flex-wrap items-end gap-4">
      {WIDTHS.map((width) => (
        <Select key={width} items={PLANS} defaultValue="starter">
          <SelectField>
            <SelectLabel size="lg">{width}</SelectLabel>
            <SelectTrigger size="lg" width={width} />
          </SelectField>
          <SelectContent>
            <SelectList>
              {PLANS.map(({ label, value }) => (
                <SelectItem key={value} value={value} label={label} />
              ))}
            </SelectList>
          </SelectContent>
        </Select>
      ))}
    </div>
  );
}
```

### Sizes

For `secondary` and `ghost`, `size` runs md 28 / lg 32 / xl 36 / 2xl 40 px. Pass the same value to `SelectLabel`
and `SelectTrigger`: the label tracks the trigger's rung, while the option rows stay one fixed 32px
height at every size, like Combobox and Menu rows. The label runs 13px at `md` and `lg`, 14px at
`xl` and `2xl` — matching what a field wrapper renders at the same control height, so it sits one
step calmer than the value at `lg` and `2xl` and matches it at `xl`. See
[Sizing](/foundations/sizing) for the full ladder.

```tsx
import {
  Select,
  SelectContent,
  SelectItem,
  SelectLabel,
  SelectList,
  SelectTrigger,
  type SelectTriggerFieldSize,
} from "@makeplane/propel/components/select";
import { SelectField } from "@makeplane/propel/elements/select";

const SERVER_TYPES = [
  { label: "General purpose", value: "general" },
  { label: "Compute optimized", value: "compute" },
  { label: "Memory optimized", value: "memory" },
];

const SIZES: SelectTriggerFieldSize[] = ["md", "lg", "xl", "2xl"];

export default function SizesDemo() {
  return (
    <div className="flex flex-wrap items-end gap-3">
      {SIZES.map((size) => (
        <Select key={size} items={SERVER_TYPES} defaultValue="general">
          <SelectField>
            <SelectLabel size={size}>{size}</SelectLabel>
            <SelectTrigger size={size} />
          </SelectField>
          <SelectContent>
            <SelectList>
              {SERVER_TYPES.map(({ label, value }) => (
                <SelectItem key={value} value={value} label={label} />
              ))}
            </SelectList>
          </SelectContent>
        </Select>
      ))}
    </div>
  );
}
```

### Variants

`SelectTrigger`'s `secondary` variant (default) is the bordered field surface; `ghost` drops the
border and fill; `pill` keeps bordered chrome but hugs its value for compact property and filter
selectors. Like Propel Pill, the pill trigger has no automatic chevron: an open popup is conveyed
by its active chrome. Pair it with `SelectContent sizing="auto"` so its options are not constrained
by the compact anchor width. Its size scale is `xs`, `sm`, and `md`, matching Propel Pill; the type
contract rejects those compact sizes on `secondary`/`ghost` and rejects `lg`–`2xl` on `pill`.

```tsx
import {
  Select,
  SelectContent,
  SelectItem,
  SelectLabel,
  SelectList,
  SelectTrigger,
  type SelectTriggerVariant,
} from "@makeplane/propel/components/select";
import { SelectField } from "@makeplane/propel/elements/select";

const SERVER_TYPES = [
  { label: "General purpose", value: "general" },
  { label: "Compute optimized", value: "compute" },
  { label: "Memory optimized", value: "memory" },
];

const VARIANTS: SelectTriggerVariant[] = ["secondary", "ghost", "pill"];

export default function VariantsDemo() {
  return (
    <div className="flex flex-wrap items-end gap-3">
      {VARIANTS.map((variant) => (
        <Select key={variant} items={SERVER_TYPES} defaultValue="general">
          <SelectField>
            <SelectLabel size={variant === "pill" ? "md" : "lg"}>{variant}</SelectLabel>
            {variant === "pill" ? (
              <SelectTrigger size="md" variant="pill" />
            ) : (
              <SelectTrigger size="lg" variant={variant} />
            )}
          </SelectField>
          <SelectContent sizing={variant === "pill" ? "auto" : undefined}>
            <SelectList>
              {SERVER_TYPES.map(({ label, value }) => (
                <SelectItem key={value} value={value} label={label} />
              ))}
            </SelectList>
          </SelectContent>
        </Select>
      ))}
    </div>
  );
}
```

### With icon

`SelectTrigger`'s `icon` prop shows a leading glyph before the value, via the shared `Icon` slot.

```tsx
import { Icon } from "@makeplane/propel/components/icon";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectLabel,
  SelectList,
  SelectTrigger,
} from "@makeplane/propel/components/select";
import { SelectField } from "@makeplane/propel/elements/select";
import { ServerOutline } from "@makeplane/propel/icons";

const SERVER_TYPES = [
  { label: "General purpose", value: "general" },
  { label: "Compute optimized", value: "compute" },
  { label: "Memory optimized", value: "memory" },
];

export default function WithIconDemo() {
  return (
    <Select items={SERVER_TYPES} defaultValue="general">
      <SelectField>
        <SelectLabel size="lg">Server type</SelectLabel>
        <SelectTrigger size="lg" icon={<Icon icon={ServerOutline} tint="placeholder" />} />
      </SelectField>
      <SelectContent>
        <SelectList>
          {SERVER_TYPES.map(({ label, value }) => (
            <SelectItem key={value} value={value} label={label} />
          ))}
        </SelectList>
      </SelectContent>
    </Select>
  );
}
```

### Option icons

`SelectItem`'s `icon` prop shows a leading glyph before an option's label. In a `multiple` select
it follows the checkbox.

```tsx
import { Icon } from "@makeplane/propel/components/icon";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectLabel,
  SelectList,
  SelectTrigger,
} from "@makeplane/propel/components/select";
import { SelectField } from "@makeplane/propel/elements/select";
import { ModuleOutline, MemoryOutline, ServerOutline } from "@makeplane/propel/icons";

const SERVER_TYPES = [
  { label: "General purpose", value: "general", icon: ServerOutline },
  { label: "Compute optimized", value: "compute", icon: ModuleOutline },
  { label: "Memory optimized", value: "memory", icon: MemoryOutline },
];

export default function ItemIconsDemo() {
  return (
    <Select items={SERVER_TYPES} defaultValue="general">
      <SelectField>
        <SelectLabel size="lg">Server type</SelectLabel>
        <SelectTrigger size="lg" />
      </SelectField>
      <SelectContent>
        <SelectList>
          {SERVER_TYPES.map(({ label, value, icon }) => (
            <SelectItem
              key={value}
              value={value}
              label={label}
              icon={<Icon icon={icon} tint="secondary" />}
            />
          ))}
        </SelectList>
      </SelectContent>
    </Select>
  );
}
```
## API Reference

### Select

The select Root — Base UI's context/state provider (renders no element of its own). A
behavior-only role, so it lives in `components` (rules 1a, 2); the styled parts live in
`elements/select` and are grafted onto Base UI behavior here. It also shares `multiple` with its
`SelectItem`s, which switch to a leading checkbox marker for a multi-select.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `children` | `ReactNode` | — | The select's anatomy — a `SelectTrigger` and the popup of items. |

### SelectTrigger

The ready-made select trigger: grafts Base UI's `Select.Trigger` behavior onto the styled trigger
and bakes its anatomy — an optional leading icon, the selected value (Base UI's `Select.Value`
grafted onto `SelectValue`), and an owned chevron indicator for field-style variants. The `pill`
variant follows Propel Pill anatomy and has no baked trailing icon; its open state is conveyed by
active chrome. Children are baked, so the prop is omitted.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `size` (required) | `"xs" \| "sm" \| "md" \| "lg" \| "xl" \| "2xl"` | — |  |
| `placeholder` | `ReactNode` | — | Shown in the trigger while nothing is selected — Base UI's `Select.Value` placeholder. |
| `icon` | `ReactNode` | — | Element shown before the value, e.g. `<Icon icon={Server} tint="placeholder" />`. |
| `variant` | `"secondary" \| "ghost" \| "pill"` | — |  |
| `width` | `"auto" \| "fit"` | — | `auto` keeps the 288px minimum; `fit` hugs the rendered trigger content. |

### SelectContent

The select list surface: Base UI portal + positioner, with the popup grafted onto the shared
`OverlayPanel` — the same elevated card, radius, open/close animation and anchor width as the
Combobox and Menu panels, including the `ScrollArea` its list scrolls in.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `sizing` | `"auto" \| "anchor" \| "anchor-fixed"` | `anchor` | How the popup takes its width. `anchor` matches the trigger's width, growing only with its content up to the room beside the trigger. `auto` is the content's width instead — never narrower than 204px, never wider than 400px or the room beside the trigger — for a narrow trigger (e.g. a ghost select in a toolbar) whose options need more room than it has. |
| `header` | `ReactNode` | — | Sticky content pinned above the scrolling list, e.g. a `SelectStickyList` holding a `SelectSelectAll` row and a `SelectSeparator`. |
| `footer` | `ReactNode` | — | Sticky content pinned below the scrolling list, e.g. a `SelectFooter`. |
| `side` | `"top" \| "bottom" \| "left" \| "right" \| "inline-end" \| "inline-start"` | `bottom` | Which side of the trigger the list opens toward. |
| `sideOffset` | `number \| OffsetFunction` | `4` | Distance in px between the trigger and the list. |
| `align` | `"center" \| "start" \| "end"` | `start` | Alignment of the list relative to the trigger along `side`. |
| `alignOffset` | `number \| OffsetFunction` | `0` | Additional offset in px along the align axis — slides the list along the trigger's edge without changing `align`. |
| `collisionPadding` | `Padding` | `16` | Minimum gap in px between the list and the viewport edge it would otherwise touch. |
| `collisionBoundary` | `Boundary` | — | The element or rect the list is confined to when avoiding collisions. Base UI's clipping ancestors when unset. |
| `collisionAvoidance` | `CollisionAvoidance` | — | What to do when the list would overflow the boundary, set per axis: flip to the other side, shift along it, or stay put. Base UI flips the side and shifts the alignment when unset. |
| `sticky` | `boolean` | `false` | Keep the list on screen after the trigger scrolls out of view, instead of following it out. |
| `positionMethod` | `"absolute" \| "fixed"` | `"absolute"` | Which CSS `position` the positioner uses. `fixed` escapes overflow-clipping ancestors, e.g. a trigger inside a sticky header. |
| `anchor` | `Element \| VirtualElement \| RefObject<Element \| null> \| (() => Element \| VirtualElement \| null) \| null` | — | Position against this element instead of the trigger — an element, a ref, a virtual element, or a function returning one. Geometry only; the trigger keeps its role and interactions. |
| `disableAnchorTracking` | `boolean` | `false` | Stop tracking layout shifts of the anchor — position once, on open. |
| `alignItemWithTrigger` | `boolean` | `false` | Overlap the popup onto the trigger so the selected item's text lines up with the trigger's value (native `<select>`-style). Figma's spec opens the list flush below the trigger instead, so this defaults off — enable per-instance for the native-alignment look. While it is on, Base UI scrolls the list element itself rather than the panel's `ScrollArea`, so the list shows the native scrollbar instead of the panel's. |

### SelectLabel

The ready-made select label: grafts Base UI's `Select.Label` behavior — automatic association
with the trigger — onto the styled label.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `size` (required) | `"md" \| "lg" \| "xl" \| "2xl"` | — | Label text size. Pass the same step as the `SelectTrigger` it labels. Required. |

### SelectList

The container for the select items: Base UI's `Select.List` grafted onto the styled `SelectList`,
the padded list inside the `SelectContent` panel (the rows are `SelectItem`s).

No component-specific props — accepts the standard HTML attributes for the element it renders.

### SelectItem

The ready-made select option row: grafts Base UI's `Select.Item` behavior onto the styled
`SelectItem` row — the shared menu-row chrome, so the list matches Combobox and Menu — and lays
out an optional leading icon, the label with any inline secondary text, an optional description
line, the selection marker, and trailing content. A single-select row trails its label with a
check (`SelectItemIndicator`); inside a `multiple` select the row leads with a checkbox box
(`SelectCheckboxItemIndicator`), matching a multi-select Combobox. Both markers are
`keepMounted`: the check so its gutter holds while unselected (a selection change never
re-truncates a label), the checkbox so the empty box shows. Only the `label` goes through Base
UI's `Select.ItemText`, so it alone is what the trigger shows for the selected option.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `size` | `"md" \| "lg" \| "xl" \| "2xl"` | `"lg"` | No longer has any effect: option rows are one fixed height, whatever the trigger's size. Still accepted so existing call sites keep compiling — drop it. @deprecated Option rows no longer take a size. |
| `icon` | `ReactNode` | — | Leading element shown before the label, e.g. `<Icon icon={Server} tint="secondary" />`. In a `multiple` select it follows the checkbox box. |
| `description` | `string` | — | Muted secondary line under the label. The row grows to fit it. |
| `secondaryText` | `string` | — | Muted text shown inline after the label. |
| `trailing` | `ReactNode` | — | Content pinned at the row's inline end, after the check, e.g. a count (`12`) or a `<Badge />`. |
| `value` | `unknown` | — | Option value whose string form is used when `label` is omitted. Option value. Object values cannot derive display text, so they require `label`. |
| `label` | `string` | — | Option label. Defaults to the string form of `value`. Visible option and typeahead label. Required when `value` is not a primitive. |

### SelectGroup

Groups related options under a `SelectGroupLabel`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement<unknown, string \| JSXElementConstructor<any>> \| ComponentRenderFn<HTMLProps, SelectGroupState>` | — | Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |

### SelectGroupLabel

The muted heading naming a `SelectGroup`, with optional `meta` pinned at its end. Base UI's
`GroupLabel` behavior is grafted onto the heading's TITLE, not the whole row, so the group's
accessible name is the heading text alone — a count or a "Clear" button in `meta` stays out of
it. Place it inside the `SelectGroup` it names, so Base UI wires it as that group's label.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `meta` | `ReactNode` | — | Content pinned at the heading's inline end, e.g. a count or a "Clear" action. |

### SelectSeparator

A thin divider between groups of options — the same chrome as `ComboboxSeparator` and
`MenuSeparator`. Purely visual, so it is `aria-hidden` and carries no `separator` role: a listbox
may only own options and groups, so Base UI's `Select.Separator` (which renders
`role="separator"`) would be invalid ARIA inside the list. The `SelectGroup` labels already give
a screen reader the structure the line shows.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement<unknown, string \| JSXElementConstructor<any>> \| ComponentRenderFn<HTMLProps, {}>` | — | Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |

### SelectSelectAll

Sticky "select every option" row for a `multiple` select, the counterpart of `ComboboxSelectAll`.
Not a `SelectItem` — it is not an option — so compose it in `SelectContent`'s `header` (inside a
`SelectStickyList`) above the scrolling list, and wire `checked` / `indeterminate` / `onClick` to
the select's controlled `value`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `checked` (required) | `boolean` | — | Whether every option is currently selected. |
| `onClick` (required) | `() => void` | — | Called when the row is activated. |
| `label` | `string` | `Select all` | Visible row label. |
| `indeterminate` | `boolean` | `false` | Whether only some (not all) options are currently selected — shows a dash instead of a check. Takes precedence over `checked` for both the glyph and `aria-checked="mixed"`. |
| `disabled` | `boolean` | — | Disables the row. |

### SelectStickyList

Pads sticky rows in `SelectContent`'s `header` (a `SelectSelectAll` + `SelectSeparator`) with the
same inset the scrolling list uses.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement<unknown, string \| JSXElementConstructor<any>> \| ComponentRenderFn<HTMLProps, {}>` | — | Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |

### SelectFooter

A non-interactive footer pinned below the list (a hint, a count) — the same chrome as
`MenuFooter`. Pass it through `SelectContent`'s `footer`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement<unknown, string \| JSXElementConstructor<any>> \| ComponentRenderFn<HTMLProps, {}>` | — | Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |
