# NativeSelect

> The browser's own select, styled like Input, with options as data or as option/optgroup children, a placeholder, two sizes and the Field label, description and invalid state.

Source: https://docs.nasaqui.com/components/native-select

## Install

```bash
npx shadcn@latest add https://docs.nasaqui.com/r/native-select.json
```

A styled `<select>`. Phones open their own wheel or sheet, it posts with plain HTML forms, and it is light.

## When to use

- Mobile-first forms and long plain lists (countries, time zones).
- Server forms that must work without JavaScript.

## When not to use

- Options with icons, descriptions or search: use [`Select`](https://docs.nasaqui.com/components/select) or [`Combobox`](https://docs.nasaqui.com/components/combobox).
- Several values: use `Combobox` with multiple, or checkboxes.

## Import

```tsx
import { NativeSelect } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"
```

## Quick start

```tsx
import { Field, FieldLabel, NativeSelect } from "@fadymondy/nasaq/web";

export function Country() {
  return (
    <Field>
      <FieldLabel>Country</FieldLabel>
      <NativeSelect
        name="country"
        defaultValue=""
        required
        placeholder="Choose a country"
        options={[
          { value: "eg", label: "Egypt" },
          { value: "sa", label: "Saudi Arabia" },
        ]}
      />
    </Field>
  );
}
```

## Anatomy

```
NativeSelect                    data-slot="native-select" (wrapper)
├─ select                       Field control: gets the label, description and invalid state
│  ├─ option value=""           the placeholder (disabled when required)
│  └─ options / children
└─ ChevronDown                  at the inline end
```

## API

**NativeSelect**: every `select` prop except `size`, plus:

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `options` | `readonly NativeSelectOption[]` | | `{ value, label, disabled? }`. Or pass `option` / `optgroup` children. |
| `placeholder` | `string` | | A first empty option. With `required` it cannot be picked again. |
| `size` | `"sm" \| "md"` | `"md"` | Control height. |

`className` goes on the wrapper; the other props go on the `select`.

## Accessibility

- It is a real `select`: keyboard, screen readers and autofill work as the platform does.
- Inside `Field`, `FieldLabel` names it and `FieldError` describes it.
- Text is 16px on touch screens so iOS does not zoom.

## RTL & i18n

- The chevron sits at the inline end and the padding mirrors. Option text follows the page direction.

## Styling & tokens

- Same height, border, radius and focus ring as `Input` (`h-control`, `rounded-control`, `--nq-focus`).

## Do / Don't

- Do use a placeholder like "Choose…" with `required` instead of preselecting a wrong value.
- Don't use it for fewer than four options: radios show the choice without a click.

## Related

- [`Select`](https://docs.nasaqui.com/components/select)
- [`Combobox`](https://docs.nasaqui.com/components/combobox)
- [`Field`](https://docs.nasaqui.com/components/field)
- [`Form`](https://docs.nasaqui.com/components/form)

## Lab

https://docs.nasaqui.com/?path=/docs/components-forms-native-select--docs

## Code

### React

```tsx
import { Field, FieldLabel, NativeSelect } from "@fadymondy/nasaq/web";

export function Country() {
  return (
    <Field>
      <FieldLabel>Country</FieldLabel>
      <NativeSelect
        name="country"
        defaultValue=""
        required
        placeholder="Choose a country"
        options={[
          { value: "eg", label: "Egypt" },
          { value: "sa", label: "Saudi Arabia" },
        ]}
      />
    </Field>
  );
}
```

### shadcn

```tsx
import { Field, FieldLabel } from "@/components/ui/field";
import { NativeSelect } from "@/components/ui/native-select";

export function Country() {
  return (
    <Field>
      <FieldLabel>Country</FieldLabel>
      <NativeSelect
        name="country"
        defaultValue=""
        required
        placeholder="Choose a country"
        options={[
          { value: "eg", label: "Egypt" },
          { value: "sa", label: "Saudi Arabia" },
        ]}
      />
    </Field>
  );
}
```

### Vue

```vue
<script setup lang="ts">
import { NqNativeSelect } from "@fadymondy/nasaq/vue";

const countries = [
  { value: "eg", label: "Egypt" },
  { value: "sa", label: "Saudi Arabia" },
];
</script>

<template>
  <div class="flex flex-col gap-1.5">
    <label for="country" class="text-label text-foreground">Country</label>
    <NqNativeSelect id="country" name="country" default-value="" required placeholder="Choose a country" :options="countries" />
  </div>
</template>
```

### Blade

```blade
<div class="flex flex-col gap-1.5">
    <label for="country" class="text-label text-foreground">Country</label>
    <x-nq::native-select id="country" name="country" value="" required placeholder="Choose a country"
        :options="[['value' => 'eg', 'label' => 'Egypt'], ['value' => 'sa', 'label' => 'Saudi Arabia']]" />
</div>
```

### HTML + Alpine

```html
<div class="flex flex-col gap-1.5">
    <label for="country" class="text-label text-foreground">Country</label>
    <div data-slot="native-select" class="relative w-full min-w-0">
    <select  required           class="w-full min-w-0 appearance-none rounded-control border border-input bg-card ps-3 pe-9 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control" id="country" name="country">
                    <option value=""  disabled   selected >Choose a country</option>
                            <option value="eg"  >Egypt</option>
                    <option value="sa"  >Saudi Arabia</option>
    </select>
    <svg aria-hidden="true" class="pointer-events-none absolute end-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m6 9 6 6 6-6"/>
</svg></div>
</div>
```
