Nasaq

CountrySelect

Searchable country combobox with SVG flags and names in English or Arabic. The value is the ISO 3166-1 alpha-2 code. Uses PHONE_COUNTRIES or a LocationsDataSource.

PreviewOpen ↗

Code

import { CountrySelect, Field, FieldLabel } from "@fadymondy/nasaq/web";import { useState } from "react";export function Residence() {  const [iso, setIso] = useState("");  return (    <Field>      <FieldLabel>Country</FieldLabel>      <CountrySelect value={iso} onValueChange={setIso} />    </Field>  );}

Forms · beta

Live examples and controls: CountrySelect in the lab.

Install

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

A single combobox for choosing a country. Each item shows its flag (CountryFlag) and its name in the active language; typing filters by English name, Arabic name or ISO code. The value is the ISO code ("SA").

When to use

  • A country field on its own: nationality, country of residence, shipping country.

When not to use

  • A full address with city and area: use AddressInput.
  • A phone number: use PhoneInput, which has its own country list.

Import

import { CountrySelect } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"

Quick start

import { CountrySelect, Field, FieldLabel } from "@fadymondy/nasaq/web";
import { useState } from "react";

export function Residence() {
  const [iso, setIso] = useState("");
  return (
    <Field>
      <FieldLabel>Country</FieldLabel>
      <CountrySelect value={iso} onValueChange={setIso} />
    </Field>
  );
}

Anatomy

CountrySelect               div (display: contents)   data-slot="country-select"
├─ input group              Combobox input, clear, chevron
├─ popup                    list of CountryFlag + name
└─ hidden input             only when `name` is set

API

CountrySelect

PropTypeDefaultDescription
value?stringnoneControlled ISO alpha-2 code, "" for none.
defaultValue?string""Initial code when uncontrolled.
onValueChange?(iso: string) => voidnoneCalled with the code, "" when cleared.
countries?readonly PhoneCountry[]PHONE_COUNTRIESThe list to offer. Ignored when dataSource is set.
dataSource?LocationsDataSourcenoneLoad countries from a locations source; items need an iso2. Create it once.
disabled? / invalid?booleanfalseDisabled state; aria-invalid.
name?stringnoneRenders a hidden input with the ISO code.
id? / placeholder? / aria-label?stringnoneInput id, placeholder (default "Select a country"), name when there is no FieldLabel.
locale? / dir?string / "ltr" | "rtl"from the providerOverride for strings, names and popup direction.
className?stringnoneMerged onto the wrapper (which is display: contents).

Examples

Gulf countries only

import { CountrySelect, PHONE_COUNTRIES } from "@fadymondy/nasaq/web";

const gcc = PHONE_COUNTRIES.filter((c) => ["SA", "AE", "KW", "QA", "BH", "OM"].includes(c.iso));

export const Gulf = () => <CountrySelect countries={gcc} aria-label="Country" />;

From the hub

import { CountrySelect, createHubLocationsDataSource } from "@fadymondy/nasaq/web";

const hub = createHubLocationsDataSource();

export const FromHub = () => <CountrySelect dataSource={hub} aria-label="Country" />;

Accessibility

The input is a Base UI combobox and a Field control, so FieldLabel names it. Flags are decorative; the name is text.

KeyAction
Down / typingOpens the list and filters it.
Up / DownMoves the highlighted country.
EnterSelects it.
EscCloses the list.

Caller must localise aria-label and placeholder.

RTL & i18n

Names follow the active language (English or Arabic, falling back to the other when empty); search matches both. The popup takes the direction of the provider.

Styling & tokens

Same as Combobox: border-input, bg-card, rounded-control, focus nq-focus. The wrapper is display: contents, so className only matters for layout contexts such as grid placement. Never override colours with raw hex.

Do / Don't

  • Do store the ISO code; it is stable across languages.
  • Don't use it for phone numbers; PhoneInput already has a country list.

Lab

https://nasaq-ui.fadymondy.com/?path=/docs/components-forms-address-input--docs

On this page