Skip to content
Noksha UIv0.1
Colour theme

forms

Select

A listbox with typeahead, roving focus and collision-aware positioning โ€” not a native select.

Examples

Single choice

A listbox, not a native `<select>` โ€” so it can be styled, but it still posts with a form through a hidden input.

Type a letter with the list open to jump to it.

Grouped options

Trigger shells

Thirteen shells over one listbox. `variant` and `size` carry the shape; `renderValue` is what puts an icon, a glyph or a status dot in front of the label. Every tile copies on its own.

Outline
Soft
Ghost
Pill
Underline
Elevated
Accent bar
Inverse slab
Dashed
Prefixed icon
Monospace compact
Status dot
Densities

Sizes

All five control sizes, then the same scale combined with shape overrides so a compact form and a hero form use one component.

Scale

XS
SM
MD
LG
XL

Sizes with shape overrides

XS ยท soft pill
SM ยท ghost underline
MD ยท squared
LG ยท elevated
XL ยท accent ring
XS ยท full width
XL ยท inverse

States

Placeholder, disabled, invalid and required โ€” on the root, on individual options, and wired through `FieldRoot` for label and error text.

On the root

Default
Placeholder
Disabled
Disabled and empty
Invalid
Invalid with value
Required

On options

Disabled option
All options disabled

With FieldRoot

With description

Changing this prorates the current period.

With error

Pick a tier before continuing.

Required with description

Enterprise includes a named engineer.

Prefixes and suffixes

`renderValue` owns the trigger content, so a flag, an avatar, a count, a price or a keyboard hint all sit inside the same control.

Flag prefix
Dial code suffix
Avatar initials
Count badge
Price suffix
Severity dot
Leading search icon
Locked prefix
Inline label
Keyboard hint
Uppercase code
Two-line trigger

Grouping

Groups with and without a leading ungrouped item, disabled sections, emoji labels, and lists wide enough to break out of the trigger.

Two groups
Three groups
Ungrouped first
Disabled inside group
Single group
Emoji labels
Pill trigger
Four groups, scrolling
Uppercase group labels
Monospace values
Wide list
Elevated surface

Rich option rows

Two-line rows, avatars and trailing metadata. `textValue` keeps type-to-select working when the label is no longer plain text.

Two-line rows
Title and price
Avatar rows
Member and role
Repo rows
Wide list
Elevated surface
Pill trigger
Large trigger
Compact trigger
Disabled rich row
Inverse trigger

Placement

`side`, `align`, `sideOffset` and `collisionPadding` on the content, plus `matchTriggerWidth` against a free-width list.

side

Bottom
Top
Right
Left

align

Start
Center
End

sideOffset and collisionPadding

Offset 2
Offset 16
Collision padding 32

Width

Match trigger width
Free width

Semantic tones

Neutral, accent, success, warning and danger โ€” each as a subtle fill, a solid fill and an edge treatment, all from the token set.

Subtle and solid

Accent subtle
Accent solid
Success subtle
Success solid
Warning subtle
Warning solid
Danger subtle
Danger solid

Neutral, edges and rings

Neutral
Success ring
Accent left edge
Danger left edge

Controlled patterns

Dependent selects, mirrored state, reset and clear buttons, a controlled `open`, and two triggers bound to one value. Each tile copies with its own state.

Dependent country and city
Mirrored value
value: m
Reset button
Clearable
Change counter
changes: 0
Controlled open
Default value
Uncontrolled
Lock toggle
Two in sync
Derived summary
3 cities available

Forms

`name` posts through a hidden input. The rest is `FieldRoot` โ€” labels, descriptions, errors, sizes and a real submit.

Named for form posts
Label and control
Label and description

Routing for new tickets.

Required marker
Error state

This field is required.

Disabled field

Locked by your administrator.

Small field
Large field
Horizontal field
Hidden required marker
Submits with form
Two fields stacked

Long lists

Twenty-four timezones and thirty years. The size middleware caps the list to the space below the trigger; type a letter to jump.

24 timezones
30 years
Capped height
Tall list
Monospace ports
Font weights
Opens upward
Narrow trigger
Large rows
Disabled entries
Pill trigger
Elevated surface

Own the source

Noksha ships as a package and as copy-paste source. Take the files and they are yours to change. These are read from the generated registry, so they are exactly what the library ships โ€” never a paraphrase of it.

Take these files, and field, internal helpers along with them โ€” the imports below point at them. Or let the CLI do it: npx @noksha-ui/cli add select writes them, follows the same dependency graph, and fixes up the imports.

export {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectRoot,
  SelectTrigger,
  selectTriggerVariants,
} from './select.js';
export type {
  SelectContentProps,
  SelectGroupProps,
  SelectItemData,
  SelectItemProps,
  SelectProps,
  SelectSize,
  SelectTriggerProps,
  SelectVariant,
} from './select.types.js';

API reference

SelectProps

PropTypeDescription
valuestringโ€”
defaultValuestringโ€”
onValueChange(value: string) => voidโ€”
openbooleanโ€”
defaultOpenbooleanโ€”
onOpenChange(open: boolean) => voidโ€”
namestringPosts with the surrounding form under this name.
disabledbooleanโ€”
requiredbooleanโ€”
invalidbooleanโ€”
childrenReact.ReactNodeโ€”

SelectTriggerProps

Also accepts everything from Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'value'>.

PropTypeDescription
variantSelectVariantโ€”
sizeSelectSizeโ€”
placeholderReact.ReactNodeShown when nothing is selected.
renderValue(value: string | undefined) => React.ReactNodeReplaces the default rendering of the selected item's label.

SelectContentProps

Also accepts everything from React.HTMLAttributes<HTMLDivElement>.

PropTypeDescription
sideSideโ€”
alignAlignโ€”
sideOffsetnumberโ€”
collisionPaddingnumberโ€”
containerElement | nullโ€”
matchTriggerWidthbooleanMake the list at least as wide as the trigger.

SelectItemProps

Also accepts everything from Omit<React.HTMLAttributes<HTMLDivElement>, 'children'>.

PropTypeDescription
value*stringโ€”
disabledbooleanโ€”
childrenReact.ReactNodeThe label. Read directly out of the element tree, so it must be plain enough to render inside the trigger too โ€” text, or text with an icon.
textValuestringOverrides the text used for type-to-select when children are not plain text.

SelectGroupProps

Also accepts everything from React.HTMLAttributes<HTMLDivElement>.

PropTypeDescription
labelReact.ReactNodeโ€”

SelectItemData

PropTypeDescription
value*stringโ€”
label*React.ReactNodeโ€”
textValue*stringโ€”
disabled*booleanโ€”