{
  "id": "locale-selector",
  "name": "LocaleSelector",
  "level": "molecule",
  "status": "stable",
  "purpose": "Locale picker with native language names.",
  "description": "**Purpose.** Single-choice locale picker. Shows the selected locale's flag and native name in a trigger and exposes the full list — searchable when long — in a `Popover`. The list is content-controlled by the integrator so the molecule never ships a hardcoded language catalogue.\n\n**When to use.**\n- A header / top-bar locale switch on a public marketing page.\n- A settings field where the user picks the language of the product UI.\n- A document or workspace surface where the active locale is part of the metadata.\n\n**When NOT to use.**\n- Choosing a country that isn't tied to a language — use a plain `Select`.\n- Multi-select language preferences — compose `Combobox` instead.\n- A free-text search across many unrelated entities — use a `Combobox` or a `CommandMenu`.\n\n**Composes.**\n- `Popover` — the floating panel and ARIA dialog surface.\n- `cmdk` `Command` — the searchable list with type-ahead, arrow-key navigation and `aria-activedescendant`.\n\n**Display modes.**\n- `flag-and-text` (default) — flag + native name, e.g. `🇪🇸 Español`.\n- `flag-only` — flag only; ideal for top-bars. Requires an `aria-label` (a sensible default is computed from the selected locale's native name).\n- `text-only` — native name only; useful when the brand cannot rely on emoji flag rendering across all platforms (notably Windows).\n\n**Search.**\n- The list grows a search input when `locales.length >= searchThreshold` (default `5`).\n- The filter scores against the native name, the optional English alias (`searchAliases`) and the locale code, so users discover their language even when they do not yet read it.\n\n**Accessibility.**\n- The trigger is `role=\"combobox\"`, `aria-haspopup=\"listbox\"`, `aria-expanded` reflects the open state.\n- Keyboard contract inherits from `Popover` + `cmdk`: Enter / Space opens, ↑↓ navigate, Enter selects, Escape closes and returns focus to the trigger.\n- `flag-only` requires an explicit or computed `aria-label` so screen-reader users hear the active locale.\n\n**Related patterns.**\n- `Patterns/Decision Matrix · NavigationChoice` — picks a value from a long set.\n- `Patterns/Surfaces/Overlays · OverlayDecisionTable` — Popover (not Dropdown, not Dialog) is the right primitive.\n- `Patterns/Surfaces/Forms · SearchAndSelect` — the search-within-a-list contract.\n- `Patterns/Flows/Navigation · PopoverForContextualWork` — anatomy of the panel.\n- `Patterns/Flows/Search & Command · SearchFieldVsCombobox` — when to expose the search input.\n- `Patterns/Foundations/Visual Priority · QuietSecondaryActions` — the selected-row tint and tick are quiet, not loud.\n- `Patterns/Foundations/Density & Growth · ContentGrowth` — search appears as the dataset grows.",
  "role": "input",
  "import": "@rrios-forge/ui/molecules/locale-selector",
  "exports": [
    "LocaleSelector",
    "localeToFlagEmoji",
    "LOCALE_SELECTOR_DISPLAYS",
    "LOCALE_SELECTOR_SIZES",
    "localeSelectorInputVariants",
    "localeSelectorItemVariants",
    "localeSelectorTriggerVariants"
  ],
  "source": "packages/ui/src/molecules/locale-selector",
  "axes": [
    {
      "axis": "size",
      "part": null,
      "values": [
        "sm",
        "md",
        "lg"
      ],
      "default": "md",
      "meaning": "Ergonomic scale, in three families (control, text, container)."
    },
    {
      "axis": "display",
      "part": null,
      "values": [
        "flag-only",
        "flag-and-text",
        "text-only"
      ],
      "default": "flag-and-text",
      "meaning": "What a selector shows."
    },
    {
      "axis": "selected",
      "part": null,
      "values": [
        "true",
        "false"
      ],
      "default": "false",
      "meaning": "Chosen in a set: the selected wash plus a non-colour cue (weight, check)."
    }
  ],
  "needs": [],
  "patterns": [
    "Patterns/Decision Matrix · OverlayChoice",
    "Patterns/Decision Matrix · NavigationChoice",
    "Patterns/Surfaces/Overlays · OverlayDecisionTable",
    "Patterns/Surfaces/Overlays · EscapeAndReturnPath",
    "Patterns/Surfaces/Forms · SearchAndSelect",
    "Patterns/Flows/Navigation · NavigationLayers",
    "Patterns/Flows/Navigation · PopoverForContextualWork",
    "Patterns/Flows/Search & Command · SearchFieldVsCombobox",
    "Patterns/Foundations/Visual Priority · QuietSecondaryActions",
    "Patterns/Foundations/Visual Priority · StatusHierarchy",
    "Patterns/Foundations/Density & Growth · DensityLevels",
    "Patterns/Foundations/Density & Growth · ContentGrowth",
    "Patterns/Foundations/Composition · CompositionChecklist",
    "Patterns/Foundations/Composition · ReuseBeforeCreate"
  ],
  "a11yExceptions": [],
  "decisions": [
    {
      "id": "ADR-024",
      "title": "`LocaleSelector` is a new molecule, not an extension of `Combobox`"
    }
  ],
  "stories": [
    {
      "name": "Playground",
      "id": "components-molecules-localeselector--playground",
      "interaction": false,
      "snapshots": [
        "dark",
        "high-contrast",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-molecules-localeselector--playground",
      "frame": "/iframe.html?id=components-molecules-localeselector--playground&viewMode=story"
    },
    {
      "name": "Display Modes",
      "id": "components-molecules-localeselector--display-modes",
      "interaction": false,
      "snapshots": [
        "dark",
        "high-contrast",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-molecules-localeselector--display-modes",
      "frame": "/iframe.html?id=components-molecules-localeselector--display-modes&viewMode=story"
    },
    {
      "name": "Sizes",
      "id": "components-molecules-localeselector--sizes",
      "interaction": false,
      "snapshots": [
        "dark",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-molecules-localeselector--sizes",
      "frame": "/iframe.html?id=components-molecules-localeselector--sizes&viewMode=story"
    },
    {
      "name": "With Search",
      "id": "components-molecules-localeselector--with-search",
      "interaction": false,
      "snapshots": [
        "dark",
        "high-contrast",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-molecules-localeselector--with-search",
      "frame": "/iframe.html?id=components-molecules-localeselector--with-search&viewMode=story"
    },
    {
      "name": "Without Search",
      "id": "components-molecules-localeselector--without-search",
      "interaction": false,
      "snapshots": [
        "dark",
        "high-contrast",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-molecules-localeselector--without-search",
      "frame": "/iframe.html?id=components-molecules-localeselector--without-search&viewMode=story"
    },
    {
      "name": "States",
      "id": "components-molecules-localeselector--states",
      "interaction": false,
      "snapshots": [
        "dark",
        "high-contrast",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-molecules-localeselector--states",
      "frame": "/iframe.html?id=components-molecules-localeselector--states&viewMode=story"
    },
    {
      "name": "In Context",
      "id": "components-molecules-localeselector--in-context",
      "interaction": false,
      "snapshots": [
        "dark",
        "high-contrast",
        "light"
      ],
      "skipsSnapshot": false,
      "docs": "/?path=/story/components-molecules-localeselector--in-context",
      "frame": "/iframe.html?id=components-molecules-localeselector--in-context&viewMode=story"
    }
  ],
  "storyFile": "tooling/storybook/stories/components/molecules/locale-selector.stories.tsx"
}
