# Native Select and Input OTP

> Native Select and Input OTP: anatomy, keyboard behavior, state, and theming in Askr.

Source: [https://askrjs.com/docs/components/native-select-and-input-otp](https://askrjs.com/docs/components/native-select-and-input-otp)

Status: experimental. Packages: @askrjs/themes/native-select, @askrjs/themes/input-otp.

**Published packages are authoritative.** Examples may lag behind a published contract. When guidance differs, verify the exports and TypeScript declarations in your installed package, then file an issue.

## Example

```tsx
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={setCode}>
    <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.

## Documentation navigation

[Previous](https://askrjs.com/docs/components/calendar-and-date-picker/index.md) | [Next](https://askrjs.com/docs/components/dialog/index.md)
