{
  "components": [
    {
      "id": "accordion",
      "name": "Accordion",
      "description": "A vertically-stacked set of disclosure controls, each pairing a header button with a panel of content that expands or collapses. Distinct from Tabs (always shows one panel, replaces on selection) by allowing zero, one, or multiple panels open at once and by preserving all panel labels on screen. Used for FAQs, settings groupings, progressive disclosure of dense reference content, and any list of named regions where content is browsable but not all needed simultaneously."
    },
    {
      "id": "alert",
      "name": "Alert",
      "description": "An inline non-blocking message that surfaces important information to the user — system status, validation errors, success confirmation, contextual warnings — and announces itself to assistive tech via an `aria-live` region. Distinct from Modal (blocking, demands response), Toast (auto-dismissed, transient), and Tooltip (on-demand description). Alert sits in the document flow, persists until dismissed or the underlying state changes, and may carry optional inline actions."
    },
    {
      "id": "avatar",
      "name": "Avatar",
      "description": "A graphic representation of a user, organisation, or entity — image, initials, or icon — rendered in a bounded surface (circle or square). Carries a fallback chain when the primary representation is missing or fails to load. Often paired with a status indicator and composed into avatar-groups for collaborator lists."
    },
    {
      "id": "avatar-group",
      "name": "Avatar Group",
      "description": "A composition of avatar instances rendered as a stack or grid with bounded count and an overflow indicator (+N) for collaborator lists, attribution rows, and shared-document headers. Codifies the canonical overflow contract — counts beyond `max` collapse into a single indicator tile — and the disclosure pattern for revealing the full member list."
    },
    {
      "id": "badge",
      "name": "Badge",
      "description": "A compact standalone marker that announces status, count, or category alongside another element — a list-item count, a navigation badge, a status dot on an avatar, an inline severity tag. Read-only by canonical contract; the host element handles interactivity."
    },
    {
      "id": "banner",
      "name": "Banner",
      "description": "A region-wide persistent informational surface — typically pinned to the top of a page or section — that surfaces system-level notices, promotional content, or status messages that should be visible across the user's session. Distinct from Alert (contextual, bound to a specific situation) by its persistence and scope, from Toast (transient, corner-anchored) by its persistence and full width, and from Modal (blocking) by its non-blocking contract. Used for cookie consent, maintenance notices, beta-feature callouts, system-degradation warnings, and full-bleed promotional CTAs."
    },
    {
      "id": "breadcrumbs",
      "name": "Breadcrumbs",
      "description": "A horizontal trail of links representing the user's location within a hierarchical site or app. Wrapped in a navigation landmark (`<nav aria-label=\"Breadcrumb\">`), rendered as an ordered list with the last item marked `aria-current=\"page\"` and rendered as static text (not a link). Separators are decorative and hidden from AT."
    },
    {
      "id": "button",
      "name": "Button",
      "description": "An interactive element that triggers an action when activated. Anchors most user-initiated state changes — submitting forms, opening dialogs, advancing flows. Distinct from a Link (which navigates) in semantic and visual treatment."
    },
    {
      "id": "card",
      "name": "Card",
      "description": "A bounded container that groups a coherent unit of content — typically a title, supporting body, optional media, and optional actions — and lifts it as a single perceivable object on the page."
    },
    {
      "id": "checkbox",
      "name": "Checkbox",
      "description": "A binary form control with three visual states — unchecked, checked, and mixed (indeterminate). Used for multi-select lists (\"select all that apply\"), boolean form fields (\"subscribe to newsletter\"), and parent-child group toggles where the parent reflects the aggregate state of its children. Distinct from Switch (momentary on/off) and Radio (mutually exclusive within a group)."
    },
    {
      "id": "code-block",
      "name": "Code Block",
      "description": "A monospace surface for presenting source code, terminal output, or any verbatim technical content. The block variant carries chrome — language label, copy button, optional line numbers — around the `<code>` element; the inline variant renders bare `<code>` inside flowing prose for short technical references. Syntax-highlighting spans are decorative (`aria-hidden=\"true\"`) so SR users hear the raw code text; line numbers render via CSS `counter-increment` so they never enter the clipboard; the copy button has an explicit accessible name and announces success via an `aria-live` region."
    },
    {
      "id": "combobox",
      "name": "Combobox",
      "description": "A text input combined with a popup list of suggestions. The user types to filter, navigates with arrow keys, and selects an option to commit a value. Distinct from a Select (which has no text input) and from Autocomplete (which is a behavior, not a component name in most design systems)."
    },
    {
      "id": "disclosure",
      "name": "Disclosure",
      "description": "A single collapsible region with one toggle — a button that expands or collapses an associated content panel. The atomic unit of disclosure: Accordion is a list of disclosures grouped with shared keyboard navigation, but a standalone Disclosure has no peers and no group semantics. Used for \"show more\" patterns in prose, expandable details rows, optional advanced settings, inline help expansion, and any single named region whose content is disclosable on demand."
    },
    {
      "id": "drawer",
      "name": "Drawer",
      "description": "An edge-anchored panel that slides in from a viewport edge to surface contextual content alongside (or temporarily replacing) the underlying view. Distinct from Modal in two ways: positioning is edge-anchored rather than centered, and the modal/non-modal behaviour is a property rather than the defining trait. Common uses: filter panels, detail-view side-sheets, mobile navigation, settings flyouts."
    },
    {
      "id": "grid-pattern",
      "name": "Grid",
      "description": "An interactive 2D data structure where cells themselves are focusable — the APG escalation from `Table` (read-only data display) for surfaces where users navigate cell-by-cell, edit in place, or select rectangular regions. Carries `role=\"grid\"` on the root, `role=\"row\"` on rows, and `role=\"gridcell\"` / `role=\"columnheader\"` / `role=\"rowheader\"` on cells. Keyboard model: roving-tabindex (one cell holds the tab stop), 2D arrow navigation, Home/End/Ctrl+Home/Ctrl+End for boundary jumps, F2 / Enter to enter edit-mode, Escape to cancel."
    },
    {
      "id": "icon",
      "name": "Icon",
      "description": "An SVG-based pictogram rendered inline with surrounding text or as a standalone glyph inside another component. Carries either decorative or meaningful semantics depending on whether a visible text label accompanies it. The canonical primitive that every larger component composes for affordance, status, or wayfinding cues."
    },
    {
      "id": "link",
      "name": "Link",
      "description": "An interactive element that navigates the user to another resource — another page, an anchor within the current page, an external URL, a downloadable file, or a `mailto:` / `tel:` target. Distinct from Button (which performs an action without navigation). Renders as `<a href>` in HTML and inherits the entire native anchor contract: middle-click opens in a new tab, right-click exposes the URL, copy- as-link works, the URL is visible in the status bar."
    },
    {
      "id": "list-item",
      "name": "List Item",
      "description": "A single row in a list — settings rows, contact lists, file browsers, transactions, message threads, search results. Distinct from Card (standalone object with no implicit siblings) by living inside an explicit list (`<ul>`, `<ol>`, or `<dl>`) and cooperating with sibling rows for keyboard navigation, selection semantics, and visual rhythm. Distinct from Tile (image-led, 2D grid) by being one-dimensional and text/metadata-led."
    },
    {
      "id": "menu",
      "name": "Menu",
      "description": "A standalone list of commands carrying `role=\"menu\"` plus children with `role=\"menuitem\"`, `role=\"menuitemcheckbox\"`, or `role=\"menuitemradio\"`. Distinct from `MenuButton` (combined trigger + menu pattern) by being the menu surface itself — composable as a context-menu (right-click triggered), permanently-embedded surface, or sub-menu of a parent menu. Implements the APG menu keyboard model: arrow keys navigate items, Home / End jump to boundaries, typeahead jumps to items by initial letter, ArrowRight opens submenus, ArrowLeft / Escape closes submenus, roving-tabindex with single tab-stop into the menu."
    },
    {
      "id": "menu-button",
      "name": "Menu Button",
      "description": "A button that opens a menu of actions or commands — a more document item, a settings list, an overflow (\"…\") menu of context actions. Distinct from Popover (interactive arbitrary content) by its `role=\"menu\"` semantic and APG menu-keyboard contract; distinct from Select (single-value commit) by invoking actions rather than selecting values; distinct from navigation menus by being a transient action surface, not a persistent navigation region."
    },
    {
      "id": "modal",
      "name": "Modal",
      "description": "A transient overlay surface that suspends the underlying view and demands attention or input before the user can return to the rest of the page. Synonymous with \"dialog\" in the ARIA Authoring Practices Guide; \"modal\" emphasises the *modality* (the page is blocked) over the dialog box itself."
    },
    {
      "id": "pagination",
      "name": "Pagination",
      "description": "A navigation component for moving between discrete pages of a larger dataset — search results, table rows, document indices. Wrapped in a `<nav>` landmark with a specific `aria-label` (\"Pagination\"); current page marked with `aria-current=\"page\"`; disabled previous / next controls retain DOM presence with `aria-disabled=\"true\"` so the tab-order stays stable as users page through. Three structural variants — numbered (the page list), prev-next-only (single previous + next plus a \"Page X of N\" context), and load-more (single button that appends the next page below the current data)."
    },
    {
      "id": "popover",
      "name": "Popover",
      "description": "A non-modal floating surface anchored to a trigger element, used to surface contextual content the user reads or acts on without leaving the underlying view. Distinct from Modal (always centred and blocking), Drawer (edge-anchored, may be modal), and Tooltip (non-interactive, hover-driven, descriptive only). Popover content is interactive — buttons, forms, lists — and the user may tab into it."
    },
    {
      "id": "progress",
      "name": "Progress",
      "description": "A non-interactive indicator showing the completion status of an ongoing task — uploads, downloads, multi-step server operations, long form submissions. Carries `role=\"progressbar\"` plus an accessible name; determinate progress reports `aria-valuemin` / `aria-valuemax` / `aria-valuenow` so AT users hear the percentage; indeterminate progress omits `aria-valuenow` per APG and announces a busy state. Two structural variants (linear bar, circular ring) cover the canonical visual shapes; native HTML `<progress>` is an acceptable alternative implementation when no styling control is needed."
    },
    {
      "id": "radio-group",
      "name": "Radio Group",
      "description": "A mutually-exclusive selection control — a fieldset of radio buttons where exactly one option is selected at a time. Native `<input type=\"radio\">` instances grouped by a shared `name` attribute, wrapped in a `<fieldset>` with `<legend>` (or `role=\"radiogroup\"` with `aria-labelledby`). Distinct from Checkbox by enforcing single-selection mutex; distinct from Select by surfacing all options inline rather than behind a popup."
    },
    {
      "id": "search-input",
      "name": "Search Input",
      "description": "A text input optimised for free-text search queries — typically pinned at the top of a search-driven page or in a navigation bar — with a leading magnifier icon, optional clear affordance, and optional results-preview popup. Distinct from Combobox by emitting a free-text query rather than committing a constrained value: search results live in a separate region (a search-results page or a results panel) rather than in the input's listbox. Distinct from plain Input by structuring the search-and-submit contract."
    },
    {
      "id": "segmented-control",
      "name": "Segmented Control",
      "description": "A row (or column) of connected buttons that lets the user switch between mutually-exclusive views of the same content — list vs grid, day vs week vs month, KB vs MB vs GB unit toggles. Distinct from Tabs (which switches between different *content*), distinct from RadioGroup (which captures form values rather than view state), distinct from Toggle (which is binary, not n-way). Used for content-presentation toggles where the underlying data is the same and the segments select the visual shape."
    },
    {
      "id": "select",
      "name": "Select",
      "description": "A control that lets the user choose one or more values from a fixed list. Distinct from Combobox by the absence of a text-input front (no typeahead filtering); the user clicks or keyboard- navigates to a value and commits. Distinct from Radio by presenting choices in a popup rather than as visible alternatives. Renders as native `<select>` by default; custom implementations follow the APG Listbox pattern with portal- mounted popup, `aria-activedescendant` highlighting, and typeahead by first-letter."
    },
    {
      "id": "sidebar-nav",
      "name": "Sidebar Nav",
      "description": "A persistent navigation region pinned to a viewport edge — typically the inline-start (visual left in LTR) on desktop, collapsing to a drawer on mobile. Holds links to independent pages or top-level sections of an application. Distinct from Tabs (in-page content switching), MenuButton (transient action surface), and Drawer-as-navigation (the modal on-demand variant of this pattern). SidebarNav is the canonical pattern for multi-section apps with persistent global navigation."
    },
    {
      "id": "skeleton",
      "name": "Skeleton",
      "description": "A placeholder element that occupies the layout footprint of content not yet loaded. Distinct from a spinner: the skeleton preserves the exact dimensions of the eventual content, eliminating layout shift on load. Three variants cover the canonical placeholder shapes — text rows, circular avatars, and rectangular blocks."
    },
    {
      "id": "stepper",
      "name": "Stepper",
      "description": "A sequential multi-step indicator that visualises progress through an ordered process — checkout flows, signup wizards, multi-step forms, onboarding sequences. Distinct from Tabs (which switches between non-sequential parallel views) by enforcing order: steps complete in sequence, prior steps may be revisited but later steps are gated until prior steps validate. Distinct from Accordion (independent collapsible regions) by the strict sequence and the visible progress-through-N-steps state."
    },
    {
      "id": "switch",
      "name": "Switch",
      "description": "A binary on/off control with immediate effect — track plus thumb that slides between two positions. Uses `role=\"switch\"` to signal \"this control immediately enables/disables a behaviour\" rather than \"this is a boolean form field\" (which is `Checkbox`). Common alternate name \"Toggle\" across design systems (Atlassian, Carbon, Polaris). No tri-state mixed value — switches are strictly binary."
    },
    {
      "id": "table",
      "name": "Table",
      "description": "A two-dimensional data grid with column headers and rows of cells, used for presenting tabular data where users scan and compare attributes across many records — inventory, contacts, transactions, search results with multiple sortable fields. Distinct from ListItem (1D rows; one-attribute-per-row) by the second axis of columns, and distinct from the APG `grid` pattern (interactive cells with 2D arrow-key navigation) by treating cells as static data unless explicitly escalated. Native HTML semantics — `<table>`, `<caption>`, `<thead>`, `<tbody>`, `<th scope=\"col\">`, `<td>` — are the canonical baseline; ARIA roles only when the structural elements are unavailable."
    },
    {
      "id": "tabs",
      "name": "Tabs",
      "description": "A switching control that exposes a flat set of mutually exclusive panels through a row (or column) of tab triggers. Used to chunk related content under a single surface so only one chunk is visible at a time."
    },
    {
      "id": "tag-input",
      "name": "Tag Input",
      "description": "An input that accepts multiple discrete values, rendering each committed value inline as a removable token next to a text input. Distinct from Combobox by emphasising visible accumulated state (the user sees all selected values as tokens), distinct from Select-multi by rendering tokens inline rather than as a count or comma-list, distinct from plain Input by structuring multi-value semantics. Used for email-recipient pickers, label/topic editors, filter-tag composers, multi-attribute search inputs."
    },
    {
      "id": "text-input",
      "name": "Text Input",
      "description": "A bounded surface for free-text user entry that resolves to a single string value — the canonical primitive for forms. Composes a visible label, an `<input>` element, optional description and error message, and optional leading/trailing decorations. Distinct from SearchInput (which emits a query) and from Combobox (which commits from a constrained list) — TextInput accepts and exposes arbitrary user-typed strings."
    },
    {
      "id": "textarea",
      "name": "Textarea",
      "description": "A multi-line plain-text editing control for free-form prose — comments, feedback, descriptions, support-ticket bodies. Native HTML `<textarea>` is canonical; carries `aria-multiline=true` implicitly. Distinct from TextInput by the multi-line value shape (line-breaks preserved on submission), by the `rows` axis, and by the auto-resize contract that grows the field as content fills."
    },
    {
      "id": "tile",
      "name": "Tile",
      "description": "An image-led grid item with minimal supporting text. Used for galleries, asset grids, image picker grids, and any layout where visual content is primary and text is supplementary or absent. Distinct from Card (content-led with hierarchical title+body+media+actions); a wall of Tiles reads as a gallery, a wall of Cards reads as a feed. Tiles are commonly arranged in a grid with consistent aspect ratios and may be interactive (whole-tile activates) or selectable (whole-tile multi-selects)."
    },
    {
      "id": "toast",
      "name": "Toast",
      "description": "A transient floating notification anchored to a corner of the viewport, auto-dismissing after a short visible duration. Distinct from Alert (inline, persistent) by its ephemerality and positioning; distinct from Modal (blocking) by its non-modal contract. Used for success confirmations after asynchronous actions, transient status messages, undoable operations, and short notifications that do not require explicit acknowledgement."
    },
    {
      "id": "tooltip",
      "name": "Tooltip",
      "description": "A non-interactive floating panel that surfaces brief descriptive text about its trigger, revealed on hover or focus and dismissed on blur, pointer-leave, or Escape. Distinct from Popover (interactive) and Modal (blocking): tooltip content is read-only, the user never enters the tooltip, and Tab moves past the trigger without entering the tooltip body. Used for icon labels, abbreviation expansions, short helper text — never for essential information."
    },
    {
      "id": "tree-grid",
      "name": "Tree Grid",
      "description": "An interactive 2D data structure with hierarchical rows — the APG escalation from `Grid` for surfaces where rows have parent- child relationships and per-row expand / collapse semantics. Carries `role=\"treegrid\"` on the root, `role=\"row\"` with `aria-level` plus `aria-expanded` (on parent rows) per row. Inherits the grid keyboard model (roving-tabindex, 2D arrow navigation, F2 / Enter / Escape edit-mode lifecycle) and adds ArrowRight / ArrowLeft for tree-navigation: ArrowRight expands a collapsed parent or moves to first child; ArrowLeft collapses an expanded parent or moves to parent."
    }
  ]
}