- Components
Native select
The browser's own select in the system's field style. Best on phones and for short lists.
npx shadcn add @klarhimmel/native-select @klarhimmel/inputWhen to use
Use for
One value from a short, fixed list, especially on phones.
Not for
Long searchable lists, or options with icons.
Pairs with
Field, forms and filters.
Preview
You can change this later.
native-select.tsx
import { Theme } from '@/components/klarhimmel/theme/style';
import { Field } from '@/components/klarhimmel/ui/input';
import { NativeSelect } from '@/components/klarhimmel/ui/native-select';
export default function Example() {
return (
<Theme theme="brand">
<Field label="Room type">
{(p) => (
<NativeSelect {...p}>
<option>Single</option>
<option>Double</option>
</NativeSelect>
)}
</Field>
</Theme>
);
}Install
Import
import { NativeSelect } from '@/components/klarhimmel/ui/native-select';- Lands in
- components/klarhimmel/ui/native-select.tsx, plus cn() and the theme item if they are missing. Import theme.css after Tailwind.
- Render in
- Render it inside <Theme>, once near the root of your app. Tokens and fonts are scoped to it, so outside it the component is unstyled.
Examples
Form
Breakfast is included in every room.
Chosen: double.
import { useState } from 'react'; import { Button } from '@/components/klarhimmel/ui/button'; import { Field } from '@/components/klarhimmel/ui/input'; import { NativeSelect } from '@/components/klarhimmel/ui/native-select'; export default function NativeSelectForm() { const [type, setType] = useState('double'); return ( <div className="flex w-full max-w-xs flex-col gap-4"> <Field label="Room type" hint="Breakfast is included in every room."> {(p) => ( <NativeSelect value={type} onChange={(e) => setType(e.target.value)} {...p}> <option value="single">Single</option> <option value="double">Double</option> <option value="suite">Suite</option> </NativeSelect> )} </Field> <p aria-live="polite" className="text-kh-small text-kh-muted">Chosen: {type}.</p> <Button variant="secondary" onClick={() => setType('double')}>Reset</Button> </div> ); }States
Pick a month to continue.
import { Field } from '@/components/klarhimmel/ui/input'; import { NativeSelect } from '@/components/klarhimmel/ui/native-select'; export default function NativeSelectStates() { return ( <div className="flex w-full max-w-xs flex-col gap-4"> <Field label="Arrival month" error="Pick a month to continue."> {(p) => ( <NativeSelect defaultValue="" {...p}> <option value="" disabled>Choose a month</option> <option>June</option> <option>July</option> </NativeSelect> )} </Field> <Field label="Country"> {(p) => ( <NativeSelect disabled defaultValue="se" {...p}> <option value="se">Sweden</option> </NativeSelect> )} </Field> </div> ); }
API reference
| Prop | Type | Default | Description |
|---|---|---|---|
invalid | boolean | false | Sets aria-invalid and the danger border. |
...select | SelectHTMLAttributes | - | Every native select attribute is passed through; children are the options. |
className | string | - | Applied to the wrapper, so you can set its width. |
Accessibility
| Key | Does |
|---|---|
Space / Enter / Up / Down | Opens the browser's picker |
Type a letter | Jumps to a matching option |
The browser draws the open list, so it is always accessible and always native.
Accessibility