{
  "version": "0.2.0-preview.1",
  "content_digest": "70ac710f4d22dce040e7ac593379ba8aca9dcb59a0b9c0f839819cae0e2bb721",
  "status": "preview",
  "authority": {
    "repository": "cloakedinc/design",
    "path": "packages/design-system",
    "catalog": "packages/design-system/catalog.json",
    "status": "preview"
  },
  "provenance": {
    "repo": "cloakedinc/automation",
    "commit": "f96f416e1c3bfbfaffcd155a88b87b18b8bb25f1",
    "path": "packages/design-system",
    "imported_spec_status": "approved"
  },
  "adaptations": [
    {
      "id": "button-content-gap",
      "status": "preview",
      "description": "Use the specification's 4px content gap instead of the inherited 8px implementation gap."
    },
    {
      "id": "keyboard-focus",
      "status": "preview",
      "description": "Add visible Button and Input keyboard focus and an overridable inset focus default for shared button resets, including FAQ cards and ListItem rows."
    },
    {
      "id": "supporting-text-contrast",
      "status": "preview",
      "description": "Map light secondary text to the existing grey-04-strong primitive for readable helper text on white and cream."
    },
    {
      "id": "danger-text-contrast",
      "status": "preview",
      "description": "Separate readable danger text/borders from destructive fills; preserve the primary danger-button fill and label pair."
    },
    {
      "id": "preview-status",
      "status": "preview",
      "description": "Local components, specs and token adaptations await human sign-off; upstream approved status is provenance only."
    },
    {
      "id": "motion-comparison-accessibility",
      "status": "preview",
      "description": "Preserve the original MotionShowcase comparisons while requiring explicit replay, responding to live reduced-motion changes, and keeping duration tracks usable on small screens."
    },
    {
      "id": "list-item-ownership",
      "status": "preview",
      "description": "List owns listitem wrappers for its content rows, while section labels stay outside the row count and standalone rows retain their existing semantics."
    },
    {
      "id": "card-delta-text-contrast",
      "status": "preview",
      "description": "Mix Card.Delta foregrounds from 60% existing tone solid and 40% primary text for readable contrast in both themes; preserve the four original tone fills."
    },
    {
      "id": "carousel-keyboard-access",
      "status": "preview",
      "description": "Keep all native-scrolling carousel slide controls exposed to assistive technology and keyboard navigation; pause autoplay while focus is inside the carousel."
    }
  ],
  "id": "radio",
  "name": "Radio",
  "category": "Primitives",
  "contract_status": "preview",
  "contract_kind": "source-derived",
  "review": {
    "local_status": "not-reviewed",
    "source_approval": null,
    "imported_spec_status": "approved",
    "spec_origin": "imported-adapted",
    "local_spec_source_status": "approved",
    "imported_source_revision": "f96f416e1c3bfbfaffcd155a88b87b18b8bb25f1",
    "note": "Inherited specification status is provenance, not approval of the current local implementation or extracted contract."
  },
  "approval": "required",
  "visual_reference": {
    "stories": [
      {
        "id": "cloaked-design-system-primitives-radio--playground",
        "name": "Playground",
        "title": "Cloaked Design System/Primitives/Radio",
        "exportName": "Playground",
        "source_path": "packages/design-system/src/components/primitives/Radio/Radio.stories.tsx",
        "source_digest": "46cf3fef3c2424af7bea63235be7dddaedf82ab1c5edb801dabddfec108cd79a",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-radio--playground&viewMode=story"
      },
      {
        "id": "cloaked-design-system-primitives-radio--unselected",
        "name": "Unselected",
        "title": "Cloaked Design System/Primitives/Radio",
        "exportName": "Unselected",
        "source_path": "packages/design-system/src/components/primitives/Radio/Radio.stories.tsx",
        "source_digest": "46cf3fef3c2424af7bea63235be7dddaedf82ab1c5edb801dabddfec108cd79a",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-radio--unselected&viewMode=story"
      },
      {
        "id": "cloaked-design-system-primitives-radio--selected",
        "name": "Selected",
        "title": "Cloaked Design System/Primitives/Radio",
        "exportName": "Selected",
        "source_path": "packages/design-system/src/components/primitives/Radio/Radio.stories.tsx",
        "source_digest": "46cf3fef3c2424af7bea63235be7dddaedf82ab1c5edb801dabddfec108cd79a",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-radio--selected&viewMode=story"
      },
      {
        "id": "cloaked-design-system-primitives-radio--disabled",
        "name": "Disabled",
        "title": "Cloaked Design System/Primitives/Radio",
        "exportName": "Disabled",
        "source_path": "packages/design-system/src/components/primitives/Radio/Radio.stories.tsx",
        "source_digest": "46cf3fef3c2424af7bea63235be7dddaedf82ab1c5edb801dabddfec108cd79a",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-radio--disabled&viewMode=story"
      },
      {
        "id": "cloaked-design-system-primitives-radio--states",
        "name": "States",
        "title": "Cloaked Design System/Primitives/Radio",
        "exportName": "States",
        "source_path": "packages/design-system/src/components/primitives/Radio/Radio.stories.tsx",
        "source_digest": "46cf3fef3c2424af7bea63235be7dddaedf82ab1c5edb801dabddfec108cd79a",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-radio--states&viewMode=story"
      },
      {
        "id": "cloaked-design-system-primitives-radio--dark-theme",
        "name": "Dark Theme",
        "title": "Cloaked Design System/Primitives/Radio",
        "exportName": "DarkTheme",
        "source_path": "packages/design-system/src/components/primitives/Radio/Radio.stories.tsx",
        "source_digest": "46cf3fef3c2424af7bea63235be7dddaedf82ab1c5edb801dabddfec108cd79a",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-radio--dark-theme&viewMode=story"
      }
    ],
    "name": "Radio",
    "id": "radio",
    "category": "Primitives"
  },
  "stories_source": {
    "path": "packages/design-system/src/components/primitives/Radio/Radio.stories.tsx",
    "code": "import type { Meta, StoryObj } from '@storybook/react-vite';\nimport React from 'react';\nimport { disabledControl, hapticArgType } from '../../../storybook/controlOptions';\nimport { HStack } from '../../layout/HStack/HStack';\nimport { VStack } from '../../layout/VStack/VStack';\nimport { Text } from '../Text/Text';\nimport { Radio } from './Radio';\n\nconst meta: Meta<typeof Radio> = {\n    title: 'Cloaked Design System/Primitives/Radio',\n    component: Radio,\n    parameters: {\n        a11y: { test: 'error' },\n        docs: {\n            description: {\n                component:\n                    'Round single-select control (`role=\"radio\"`) for the bare DS 4.5 selection chip. It is ' +\n                    'select-only: pressing an unselected radio fires `onSelect`, but pressing the selected radio is a ' +\n                    'no-op — exclusive selection is owned by the parent. For a labeled list of mutually exclusive ' +\n                    'options use `RadioGroup`, which composes this chip with copy and group semantics. Fully ' +\n                    'controlled: pass `selected` and update it from `onSelect`.',\n            },\n        },\n    },\n    args: { selected: false, ariaLabel: 'Radio' },\n    argTypes: {\n        selected: { control: 'boolean', description: 'Whether this radio is the selected option (controlled).' },\n        disabled: { control: 'boolean', description: 'Prevents interaction and dims the chip.' },\n        onSelect: { ...disabledControl, description: 'Called when an unselected radio is pressed.' },\n        haptic: { ...hapticArgType, description: 'Haptic feedback fired on selection. Defaults to `selection`.' },\n    },\n};\nexport default meta;\ntype Story = StoryObj<typeof Radio>;\n\nexport const Playground: Story = { args: { testId: 'radio-story-playground' } };\n\nexport const Unselected: Story = {\n    args: { selected: false, ariaLabel: 'Unselected example', testId: 'radio-story-unselected' },\n};\nexport const Selected: Story = {\n    args: { selected: true, ariaLabel: 'Selected example', testId: 'radio-story-selected' },\n};\nexport const Disabled: Story = {\n    args: { selected: false, disabled: true, ariaLabel: 'Disabled example', testId: 'radio-story-disabled' },\n};\n\n/** Every selected × disabled combination side by side. */\nexport const States: Story = {\n    render: () => (\n        <VStack gap={16}>\n            <RadioState label='Unselected' selected={false} />\n            <RadioState label='Selected' selected />\n            <RadioState label='Disabled unselected' selected={false} disabled />\n            <RadioState label='Disabled selected' selected disabled />\n        </VStack>\n    ),\n};\n\nexport const DarkTheme: Story = {\n    args: { selected: true, ariaLabel: 'Dark theme selected example', testId: 'radio-story-dark' },\n    globals: { theme: 'dark' },\n};\n\nfunction RadioState({ label, selected, disabled = false }: { label: string; selected: boolean; disabled?: boolean }) {\n    return (\n        <HStack gap={12} align='center'>\n            <Radio\n                selected={selected}\n                disabled={disabled}\n                ariaLabel={label}\n                testId={`radio-story-state-${label.toLowerCase().replace(/\\s+/g, '-')}`}\n            />\n            <Text variant='body' color={disabled ? 'secondary' : 'primary'}>\n                {label}\n            </Text>\n        </HStack>\n    );\n}\n"
  },
  "specification": {
    "$schema": "../../../specs/component-spec.schema.json",
    "identity": {
      "name": "Radio",
      "status": "preview",
      "version": "2.0.0",
      "summary": "A controlled round single-select control that selects an option without deselecting the current option on a second press."
    },
    "parts": [
      {
        "id": "control",
        "label": "Control",
        "description": "Owns radio semantics, focus treatment, interaction, and disabled behavior."
      },
      {
        "id": "selection-chip",
        "label": "Selection chip",
        "description": "Uses the shared internal selection visual without exposing it as a standalone public component."
      },
      {
        "id": "dot",
        "label": "Selection dot",
        "description": "Appears only while this option is selected."
      }
    ],
    "allowedDesignChoices": {
      "variants": {
        "base": {
          "label": "Base",
          "description": "Radio has one round visual treatment."
        }
      },
      "sizes": {}
    },
    "variants": [
      {
        "id": "base",
        "label": "Base",
        "description": "A round select-only control for one option in an exclusive set.",
        "platforms": [
          "ios",
          "android",
          "web"
        ]
      }
    ],
    "sizes": [],
    "measurements": [
      {
        "id": "control-diameter",
        "label": "Control diameter",
        "kind": "exact",
        "token": "--cds-size-32",
        "value": 32,
        "unit": "px",
        "appliesTo": [
          "control",
          "selection-chip"
        ]
      },
      {
        "id": "selection-dot-diameter",
        "label": "Selection dot diameter",
        "kind": "exact",
        "token": "--cds-size-8",
        "value": 8,
        "unit": "px",
        "appliesTo": [
          "dot",
          "selected"
        ]
      }
    ],
    "layout": {
      "alignment": "The selection dot is centered inside the circular chip.",
      "flow": "The bare control is inline; a parent group composes visible labels and descriptions beside it.",
      "notes": [
        "Use RadioGroup when presenting a complete labeled set of mutually exclusive options."
      ]
    },
    "typographyAndColor": {
      "typography": [
        {
          "label": "Composed label",
          "description": "A visible option label beside the bare control uses the body ramp.",
          "token": "--cds-type-body-size"
        }
      ],
      "colors": [
        {
          "label": "Unselected chip",
          "description": "Uses the neutral selection-off container role.",
          "token": "--cds-selection-off-container"
        },
        {
          "label": "Selected chip",
          "description": "Uses the theme-aware bold fill.",
          "token": "--cds-bg-bold"
        },
        {
          "label": "Selection dot",
          "description": "Maintains contrast on the selected fill.",
          "token": "--cds-text-on-bold"
        },
        {
          "label": "Focus ring",
          "description": "Uses the brand accent for keyboard focus.",
          "token": "--cds-brand"
        }
      ]
    },
    "states": [
      {
        "id": "unselected",
        "label": "Unselected",
        "description": "Shows the neutral empty chip and reports aria-checked false."
      },
      {
        "id": "selected",
        "label": "Selected",
        "description": "Shows the bold chip with a centered dot and reports aria-checked true."
      },
      {
        "id": "disabled-unselected",
        "label": "Disabled unselected",
        "description": "Keeps the unselected value visible while blocking selection."
      },
      {
        "id": "disabled-selected",
        "label": "Disabled selected",
        "description": "Keeps the selected value visible while blocking selection."
      },
      {
        "id": "keyboard-focus",
        "label": "Keyboard focus",
        "description": "Shows the brand focus ring around the circular control."
      }
    ],
    "behavior": [
      {
        "label": "Select only",
        "description": "Invoke selection once for an enabled unselected option; pressing the selected option is a no-op."
      },
      {
        "label": "Parent ownership",
        "description": "Let the parent group enforce exclusivity and update which option is selected."
      },
      {
        "label": "Disabled",
        "description": "Do not invoke selection or haptic feedback while disabled."
      }
    ],
    "accessibility": [
      {
        "label": "Radio semantics",
        "description": "Expose radio role, the controlled selected value, and native disabled behavior."
      },
      {
        "label": "Group semantics",
        "description": "Place related radio controls in a named radiogroup and associate each with visible option text."
      }
    ],
    "contentAdaptation": [
      {
        "label": "Option copy",
        "description": "Keep the circular control fixed while visible labels and descriptions wrap in the parent layout."
      }
    ],
    "motionHaptics": {
      "motion": [
        {
          "label": "Selection change",
          "description": "Change the chip fill and dot visibility without layout movement."
        }
      ],
      "haptics": [
        {
          "label": "Selection feedback",
          "description": "Request the selection haptic after an enabled new selection unless feedback is disabled."
        }
      ]
    },
    "platformDifferences": []
  },
  "specification_source": "packages/design-system/src/components/primitives/Radio/Radio.spec.json",
  "guidance": {
    "summary": "A controlled round single-select control that selects an option without deselecting the current option on a second press.",
    "guidance": [
      {
        "heading": "Overview",
        "body": "The bare single-select chip (`role=\"radio\"`). Select-only — pressing an unselected radio fires\n`onSelect`; pressing the selected one is a no-op, because exclusive selection is owned by the parent."
      },
      {
        "heading": "When to use",
        "body": "You rarely reach for `Radio` directly — for a labeled set of mutually exclusive options use\n`RadioGroup`, which composes this chip with copy, layout, and group semantics. Drop to a bare\n`Radio` only when you are building a custom row layout the group can't express. Compared with its\nsiblings:\n\n-   Selecting **more than one** item from a set? Use `Checkbox`.\n-   A **compact 2–4 option** switch inline (a view or filter toggle)? Use `SegmentedControl`.\n-   A **long list** of choices where space is tight? Use `Select`."
      }
    ],
    "usage": [],
    "examples": [],
    "source": "packages/design-system/src/components/primitives/Radio/Radio.mdx",
    "status": "local-preview",
    "note": "Guidance is read from local documentation, originally imported from the frozen source. Platform assertions in guidance are not parity verification."
  },
  "links": {
    "human": "/component-radio",
    "json": "/data/visual/components/radio.json",
    "storybook": "/storybook/?path=/story/cloaked-design-system-primitives-radio--playground"
  }
}
