Select (Native)
A styleable select built on Base UI's listbox — full keyboard support and typeahead, tokened to match every other control.
Colors
Sizes
Real use · shipping region
Using Select (Native)
Silica ships one design system through three paths. They share a class vocabulary but are not interchangeable — pick the one that matches what you are building.
Plain HTML — CSS classes
The Tailwind v4 plugin. Works in any framework or none — Rails, Django, PHP, Go, a static file. This path is complete for Select (Native) — it needs no JavaScript, so the classes below are the whole story.
/* in your CSS */
@import "tailwindcss";
@plugin "@wizeworks/silicaui";Root class select, with 13 modifiers:
.select.select-accent.select-error.select-info.select-lg.select-md.select-neutral.select-primary.select-secondary.select-sm.select-success.select-warning.select-xl.select-xs
React
Typed components over those same classes, with behavior and accessibility from Base UI.
npm i @wizeworks/silicaui-reactimport { Select } from "@wizeworks/silicaui-react";Props
SelectItemProps
| Prop | Type | Required | Description |
|---|---|---|---|
| value | unknown | yes | The value stored when this item is chosen. |
| children | React.ReactNode | no | — |
SelectProps
| Prop | Type | Required | Description |
|---|---|---|---|
| value | unknown | no | Controlled value (array when multiple). |
| defaultValue | unknown | no | Uncontrolled initial value. |
| onValueChange | (value: unknown, eventDetails?: unknown) => void | no | Fires with the newly-selected value. |
| multiple | boolean | no | Allow selecting multiple items (value becomes an array). |
| items | SelectItems | no | Value→label map used to render the trigger's selected label (and, if no children are given, to auto-render the options). A record ({value: label}) or an array ([{ value, label }]). |
| name | string | no | Field name for form submission. |
| disabled | boolean | no | — |
| required | boolean | no | — |
| readOnly | boolean | no | — |
| placeholder | React.ReactNode | no | Shown on the trigger while nothing is selected. |
| color | SelectColor | no | Accent for the trigger border + focus ring (shares NativeSelect colors). |
| size | SelectSize | no | Trigger height; matches same-size Inputs/Buttons. |
| side | SelectSide | no | — |
| align | SelectAlign | no | — |
| sideOffset | number | no | — |
| alignItemWithTrigger | boolean | no | Overlay the selected item on the trigger (native-select style). Default false. |
| className | string | no | Class for the trigger button. |
| popupClassName | string | no | Class for the popup surface. |
| popupProps | React.ComponentProps<typeof BaseSelect.Popup> & { [key: `data-${string}`]: string; } | no | Extra props spread onto the popup surface. |
| "aria-label" | string | no | Accessible name when there's no associated visible label. |
| "aria-labelledby" | string | no | — |
| id | string | no | — |
| children | React.ReactNode | no | SelectItem/SelectGroup/SelectSeparators. Omit to auto-render items. |
| anchor | BasePositionerProps["anchor"] | no | What to position against. Defaults to the component's own trigger. |
| positionMethod | BasePositionerProps["positionMethod"] | no | absolute (default) or fixed. Use fixed to escape a clipping ancestor. |
| alignOffset | BasePositionerProps["alignOffset"] | no | Offset along the alignment axis, in px. Pairs with align. |
| collisionBoundary | BasePositionerProps["collisionBoundary"] | no | The element the popup must stay inside. Defaults to the viewport — set it to a scroll container so the popup collides with the panel, not the window. |
| collisionPadding | BasePositionerProps["collisionPadding"] | no | Inset from the collision boundary, in px. |
| collisionAvoidance | BasePositionerProps["collisionAvoidance"] | no | Which collision strategy runs per axis (flip, shift, none). |
| sticky | BasePositionerProps["sticky"] | no | Keep the popup glued to the anchor while it scrolls out of view. |
| arrowPadding | BasePositionerProps["arrowPadding"] | no | Minimum distance from the popup's corner to the arrow, in px. |
| disableAnchorTracking | BasePositionerProps["disableAnchorTracking"] | no | Stop re-measuring when the anchor moves. Cheaper, but goes stale. |
Source of the demo above
The exact file that renders the examples above, so it can never drift from them. It imports a few of this site’s own layout helpers (../lib/…), so read it for the component calls rather than copying it whole.
Show source
import { NativeSelect } from "@wizeworks/silicaui-react";
import { Section, Row, Stack } from "../lib/Section";
import { SIZES } from "../lib/data";
export function SelectDemo() {
return (
<>
<Section title="Colors">
<Stack className="max-w-md">
<NativeSelect defaultValue="">
<option value="" disabled>
Pick a framework…
</option>
<option>React</option>
<option>Svelte</option>
<option>Vue</option>
<option>Solid</option>
</NativeSelect>
<NativeSelect color="primary" defaultValue="React">
<option>React</option>
<option>Svelte</option>
<option>Vue</option>
</NativeSelect>
<NativeSelect color="success" defaultValue="React">
<option>React</option>
<option>Svelte</option>
</NativeSelect>
<NativeSelect color="error" defaultValue="React">
<option>React</option>
<option>Svelte</option>
</NativeSelect>
<NativeSelect disabled defaultValue="React">
<option>React</option>
</NativeSelect>
</Stack>
</Section>
<Section title="Sizes">
<Row>
{SIZES.map((size) => (
<NativeSelect key={size} size={size} defaultValue={size}>
<option>{size}</option>
</NativeSelect>
))}
</Row>
</Section>
<Section title="Real use · shipping region">
<div className="grid max-w-sm gap-3 rounded-box border border-base-300 bg-base-100 p-5 shadow-sm">
<label className="flex flex-col gap-1.5 text-sm">
Country
<NativeSelect color="primary" defaultValue="US">
<option value="US">United States</option>
<option value="CA">Canada</option>
<option value="MX">Mexico</option>
<option value="UK">United Kingdom</option>
</NativeSelect>
</label>
<label className="flex flex-col gap-1.5 text-sm">
Shipping speed
<NativeSelect defaultValue="standard">
<option value="standard">Standard (5–7 days)</option>
<option value="express">Express (2–3 days)</option>
<option value="overnight">Overnight</option>
</NativeSelect>
</label>
</div>
</Section>
</>
);
}Vanilla — node tree to HTML
Select — a native <select>; options come from props.options (or child nodes). Build a node tree, project it with toHtml(), and let the zero-dependency runtime hydrate it. This is the path for generated or user-authored documents — a site builder, CMS output, a static export.
npm i @wizeworks/silicaui-html @wizeworks/silicaui-behaviorsimport { atom, toHtml } from "@wizeworks/silicaui-html";
const node = atom("Select", "select", { /* props */ });
const markup = toHtml(node);Styling on this path is the class string in the second argument — the same classes as the Plain HTML section above. There is no color prop here; write "select select-primary" rather than passing a colour as a prop.
- Takes children
- no
- Hydrated by
- nothing — this one is static markup
The full API for Select (Native), on every path, is available through the Silica MCP server.