Native Select and Input OTP
Use native select and input otp with the current published Askr packages.
@askrjs/themes/native-select0.0.13@askrjs/themes/input-otp0.0.13
How to use native select and input otp
Native Select and Input OTP should use the standard themed surface unless the application is deliberately implementing its own design system on top of @askrjs/ui.
- Import the themed component from @askrjs/themes/components; use @askrjs/ui directly only when building a custom visual system.
- Keep native select and input otp labels, state, and application actions visible at the call site instead of styling internal DOM nodes.
- Verify keyboard behavior, focus movement or return, disabled state, and both standard themes.
import { InputOTP, InputOTPGroup, InputOTPSlot, NativeSelect } from '@askrjs/themes/components';
<NativeSelect name="timezone" aria-label="Timezone">
<option value="America/New_York">Eastern time</option>
</NativeSelect>
<InputOTP maxlength={6} value={code()} onValueChange={code.set}>
<InputOTPGroup>{[0, 1, 2, 3, 4, 5].map((index) => <InputOTPSlot index={index} />)}</InputOTPGroup>
</InputOTP>Purpose
Native Select wraps a real `<select>` element; Input OTP wraps a set of generic, untyped slot elements meant to look like a one-time-passcode input. They land in the same experimental bucket for different reasons — Native Select is genuinely close to finished because the browser does most of the work, while Input OTP is closer to a visual mockup than a working input.
Install and import
Import `NativeSelect` from `@askrjs/themes/native-select`, and `InputOTP`, `InputOTPGroup`, `InputOTPSlot`, `InputOTPSeparator` from `@askrjs/themes/input-otp`. Both resolve to the same shared components barrel as the rest of `@askrjs/themes`, so the subpath is a naming convention, not a separately built module.
Live examples
`NativeSelect` works as a drop-in example immediately — render it with `<option>` children and you have a fully functional, accessible select with zero extra code. `InputOTP` does not: `InputOTPSlot` renders a `<span>`, not an `<input>`, so a real example needs you to layer actual focusable inputs (or a hidden text input plus visual slots) on top of the markup this component provides.
Anatomy
`NativeSelect` renders a single native `<select data-slot="native-select">` and accepts `children` directly, so you populate it with plain `<option>` elements just as you would outside any framework. `InputOTP` (`role="group"`) contains `InputOTPGroup` (`role="group"`) holding a row of `InputOTPSlot` elements, optionally separated by `InputOTPSeparator`, which defaults to rendering a `"-"` character marked `aria-hidden="true"`.
State model
`NativeSelect` has no framework-level state — it's a real `<select>`, so its value lives in the DOM and in whatever `onChange`/`value` props you spread onto it, identical to any native form control. `InputOTP` has no state at all: `InputOTPSlot` doesn't track a character, a focus index, or a completion flag, so tracking which slot is active and what digit it holds is code you write from scratch.
Keyboard and accessibility
`NativeSelect` gets full native keyboard support — arrow keys, type-ahead, Space/Enter to open — for free, because it's an unmodified `<select>` element. `InputOTP` gets none of that: since its slots are `<span>`s rather than focusable inputs, there's no built-in tab order, no auto-advance to the next slot on keypress, and no backspace-to-previous-slot behavior; all of it has to be implemented by whatever real input elements you place inside the slots.
Styling and tokens
`NativeSelect` applies the shared `input` class plus `data-slot="native-select"`, so it matches the visual weight of `Input` and other form fields without a custom native-select skin. `InputOTP`'s parts each carry their own `data-slot` (`input-otp`, `input-otp-group`, `input-otp-slot`, `input-otp-separator`), giving you hooks to style the slot boxes and separators independently.
API
`NativeSelect` accepts the generic `CatalogComponentProps` shape plus native `<select>` attributes — there's no `NativeSelectProps` type restricting `value` or `onChange` beyond what a `<select>` already supports. Every `InputOTP` part is likewise typed only as `CatalogComponentProps`, with no `length`, `value`, or `onComplete` prop — the kinds of APIs a finished OTP input would need, and none of them exist yet.
Edge cases
For `NativeSelect`, styling a native `<select>`'s dropdown popup consistently across browsers is a platform limitation you inherit, not an Askr gap — don't expect token overrides to reach into the OS-rendered option list. For `InputOTP`, treat it as scaffolding: shipping it as-is without adding real inputs, focus management, and paste-splitting (so pasting a full code fills every slot) produces a control that looks right but isn't usable by keyboard or screen reader.
Related pages
See Combobox and Command for the other themes-only experimental family that ships markup without behavior. See Structures and Forms and controls for the supported, behavior-complete input components to reach for when a real product surface needs a form control today.