Ballmac UI home

Native Select

The browser's own select, styled to match the input: three sizes, a placeholder, groups, a leading icon, invalid and disabled states and a loading spinner, so phones keep their picker and forms keep working.

Installation

$ pnpm dlx shadcn@latest add @ballmac/native-select

Usage

import { NativeSelect, NativeSelectGroup, NativeSelectOption } from "@/components/ballmac/native-select"

The full example is in the Code tab above.

Examples

Groups and an icon

Sizes

In a form, with an error

It decides which tips you see first.

Options still loading

Disabled, invalid and multiple

API reference

PropTypeDefault
onValueChange

Called with the chosen value, as well as the usual `onChange`.

(value: string) => void—
startIcon

Drawn before the text, such as an icon. Keep it decorative.

React.ReactNode—
loading

Shows a spinner in place of the arrow and marks the field busy, while the options load. The field stays usable.

booleanfalse
placeholder

Text of a first, empty choice that asks for a selection. It is not offered once something is chosen.

string—
rows

Lines to show for a `multiple` select.

number—
size"sm" | "default" | "lg""default"
listbox"false" | "true"false

Also accepts the standard attributes of its root element.

Accessibility

KeyAction
Tab / Shift+TabMoves to and from the field
Space / Alt+Down / EnterOpens the browser's list; arrow keys and typing choose
Screen readersIt is a real select, so name, value, options and groups are read by the browser; give it a label
aria-invalid and aria-describedbySet them with an error message, as on an input

Quality scorecard

8/8

Every applicable check passes

Measured in Chromium 153.0.8010.12 on October 19, 2026, on version 1.0.0, across 6 examples.

How we measure
  • Passed: Accessibility scan

    No serious or critical issues in light and dark, on a phone and a desktop (axe-core 4.13.0, WCAG 2.1 AA and best-practice rules).

  • Passed: Small screens

    No sideways scrolling at 360, 390 or 1280 px wide.

  • Passed: Reduced motion

    Every endless animation stops when the visitor asks for less motion.

  • Passed: Right to left

    Mirrors correctly in Arabic, Hebrew, Persian and Urdu layouts (0% of elements off the mirror, limit 15%).

  • Passed: Clean console

    No console errors or React hydration errors while loading.

  • Passed: Keyboard

    10 tab stops, each showing a visible change when it takes focus. 4 documented keys.

  • Passed: Loading, empty and error

    Ships loading, disabled states, each with an example.

  • Passed: Automated tests

    Covered by native-select.test.tsx.

  • For information: Footprint

    2.0 KB of source (gzip) in 1 file. Installs class-variance-authority, lucide-react.

Automated checks find a subset of problems and do not replace testing with a screen reader and a keyboard in your own app. What they miss.

Use with AI

<NativeSelect name placeholder> with <NativeSelectOption value> children and <NativeSelectGroup label> for groups. It is a real select: use value and onValueChange, or leave it uncontrolled in a form. With the shadcn MCP server set up (guide), ask your agent:

Add the Ballmac UI Native Select (@ballmac/native-select) to this project with the shadcn MCP, then use it where it fits.

Use it for

  • Forms where a short list of choices should use the device's own picker (phones, tablets)
  • Long lists such as countries or time zones where type-to-jump matters
  • Anywhere accessibility and autofill should be exactly the browser's

Not for

  • Options with icons, descriptions or search; use select or combobox
  • Choosing many items with chips; use multi-select
  • A handful of choices that deserve to be seen at once; use radio-group or segmented-control

Registry JSON: https://ui.ballmac.com/r/native-select.json

Credits

Based on shadcn/ui Input, adapted by Ballmac. Free to use in personal and commercial projects.

Registry
shadcn/utils

Ballmac UI Pro

Need the whole screen, not one piece?

150 premium blocks (dashboards, settings, calendars, mail, shops, onboarding), a private shadcn registry and Figma tokens. Blocks that show data come with loading, empty and error states built in.

Not ready? Try three Pro blocks free

Leave your email and the blocks appear right here, ready to copy. Yours to use in any project.