{
  "tag": "ed-radio-group",
  "kind": "component",
  "summary": "Radio groups are used to group multiple [radios](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/radio) so they function as a single form control.",
  "status": "experimental",
  "level": "atom",
  "since": "1.0",
  "docs": "https://test-apps.eurodata.de/a/eurodata-ui/docs/components/radio-group/",
  "usage": "https://test-apps.eurodata.de/a/eurodata-ui/docs/components/radio-group/usage/",
  "playwright": "getByTestId('…')",
  "dependencies": [
    "ed-radio"
  ],
  "use": [
    "A single choice among mutually exclusive options, where exactly one can be selected at a time",
    "Small, static sets of 2–5 options where seeing every option at once helps users compare and decide",
    "A quick view toggle above a list, such as table or cards, in the segmented appearance"
  ],
  "notFor": [
    {
      "when": "Users may select more than one option at once — then this is the wrong control",
      "instead": "[Checkbox](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/checkbox)"
    },
    {
      "when": "A single on/off setting that takes effect immediately",
      "instead": "[Switch](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/switch)"
    },
    {
      "when": "Long lists of 6 or more options, or a set that may grow over time",
      "instead": "[Select](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/select)"
    },
    {
      "when": "Switching between whole content views or sections — in any appearance",
      "instead": "[Tabs](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/tab-group)"
    }
  ],
  "rules": [
    {
      "id": "radio-group/label-the-group",
      "rule": "Always give the group a clear, visible label stating what the user is choosing — never leave it without one. Outside a form the container decides whether the label shows; where it does not, `aria-label` names the choice.",
      "check": "error"
    },
    {
      "id": "radio-group/stack-vertically",
      "rule": "Keep the group vertical, one option per row.",
      "why": "Each label aligns with its control, and the list is easy to scan.",
      "check": "error"
    },
    {
      "id": "radio-group/default-selection",
      "rule": "Pre-select a sensible default when a safe, common choice exists, so users can move faster. Leave the group unselected instead when the choice is sensitive or consequential and an assumed answer would be risky."
    },
    {
      "id": "radio-group/option-labels",
      "rule": "Write short, self-explanatory option labels in plain language."
    },
    {
      "id": "radio-group/segmented-for-quick-toggles",
      "rule": "Use the segmented (button) appearance, not a standard vertical radio group, for a compact horizontal set of two or three short values, such as a quick filter or a mode toggle (All / Active / Archived); from four values on, a [Select](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/select). Never use segment labels long enough to wrap or break the horizontal layout.",
      "why": "From four segments on, the row no longer holds short labels and reads as a switch between views rather than a choice of values.",
      "check": "error"
    },
    {
      "id": "radio-group/segment-icon-with-text",
      "rule": "Pair every icon in the segmented appearance with a text label — never rely on icon-only segments.",
      "check": "error",
      "covered": true
    },
    {
      "id": "radio-group/card-appearance",
      "rule": "Use the card appearance only when the options need more than a label to choose between them — a plan, a tariff, a delivery method.",
      "why": "When a plain label already says enough, the extra space buys nothing."
    },
    {
      "id": "radio-group/card-content",
      "rule": "Describe either every card or none, so they stay comparable, and keep card titles short enough not to truncate, with the detail in the description.",
      "check": "error"
    },
    {
      "id": "radio-group/no-interactive-card-description",
      "rule": "Never put a link or a button in a card's description.",
      "why": "It is referenced as the option's accessible description, so an interactive element there is reachable by keyboard but invisible to a screen reader.",
      "check": "error",
      "covered": true
    },
    {
      "id": "form-controls/required",
      "rule": "Set `required` on a mandatory control and explain the required-marking convention once per form. Never add your own required indicator — the label picks it up."
    },
    {
      "id": "form-controls/error-timing",
      "rule": "Never show a validation error before the user has interacted with the control — not on page load, not on focus alone, not while they are still typing. Don't add your own timing: the control shows its errors after the user has left it or changed its value, and on submit.",
      "check": "error"
    },
    {
      "id": "form-controls/message-never-silenced",
      "rule": "Keep a message on every error. Write your own where the built-in wording does not fit — it replaces the built-in one — but never set `error` to an empty string or hide the message part: the error styling alone says that something is wrong, not what.",
      "check": "error"
    },
    {
      "id": "form-controls/readonly-not-disabled",
      "rule": "Use `readonly` for a value the user can never change — a calculated total, an assigned id — and `disabled` only while it could become editable under some condition.",
      "why": "Disabled implies the value could be unlocked, and a disabled control submits nothing; a read-only one submits its value."
    },
    {
      "id": "form-controls/ai-suggested",
      "rule": "Set `ai` on a control whose value the system pre-filled, so users can tell it apart from their own entries; the state clears once they touch it."
    }
  ],
  "api": {
    "attributes": [
      {
        "name": "label",
        "property": "label",
        "type": "string",
        "default": "''",
        "description": "The radio group's label. Required for proper accessibility. If you need to display HTML, use the `label` slot\ninstead."
      },
      {
        "name": "name",
        "property": "name",
        "type": "null | string",
        "default": "null",
        "description": "The name of the radio group, submitted as a name/value pair with form data."
      },
      {
        "name": "orientation",
        "property": "orientation",
        "type": "'horizontal' | 'vertical'",
        "default": "'vertical'",
        "description": "The orientation in which to show radio items."
      },
      {
        "name": "readonly",
        "property": "readonly",
        "type": "boolean",
        "default": "false",
        "description": "Makes the radio group and all child radios readonly."
      },
      {
        "name": "value",
        "property": "defaultValue",
        "type": "string",
        "description": "The default value of the form control. Primarily used for resetting the form control."
      },
      {
        "name": "required",
        "property": "required",
        "type": "boolean",
        "default": "false",
        "description": "Ensures a child radio is checked before allowing the containing form to submit."
      },
      {
        "name": "with-label",
        "property": "withLabel",
        "type": "boolean",
        "default": "false",
        "description": "Only required for SSR. Set to `true` if you're slotting in a `label` element so the server-rendered markup includes the label before the component hydrates on the client."
      },
      {
        "name": "with-hint",
        "property": "withHint",
        "type": "boolean",
        "default": "false",
        "description": "Only required for SSR. Set to `true` if you're slotting in a `hint` element so the server-rendered markup includes the hint before the component hydrates on the client."
      },
      {
        "name": "appearance",
        "property": "appearance",
        "type": "'default' | 'button' | 'card'",
        "default": "'default'",
        "description": "The appearance of the radios in the group: `button` renders them as a segmented control, `card`\nas stacked cards carrying a title, a description and trailing chips."
      },
      {
        "name": "aria-label",
        "property": "ariaLabel",
        "type": "null | string",
        "default": "null",
        "description": "Accessible name for when no visible label is given. Mirrored onto the internal\n`role=\"radiogroup\"` node, where the role lives — the host is deliberately role-less, so a\nconsumer's aria-label would otherwise sit on an element assistive technology ignores.\n\nA visible label wins: the node references it with `aria-labelledby` while there is one, and\nonly then — accessible-name computation consults aria-labelledby first."
      },
      {
        "name": "error",
        "property": "error",
        "type": "null | string",
        "default": "null",
        "description": "Draws an error-style input with danger colored border and icon. Set to an empty string (or use the bare attribute `<ed-input error>`) to render error styling without a visible message; submission is still blocked with a localized fallback validation message. Set to a non-empty string to additionally display that message in the message area, above the hint, and use it as the validation message. Set to `null` (the default) or `undefined`, or remove the attribute, to clear the error."
      },
      {
        "name": "warning",
        "property": "warning",
        "type": "null | string",
        "default": "null",
        "description": "Draws a warning-style input with warning colored border and icon. Set to an empty string (or use the bare attribute `<ed-input warning>`) to render warning styling without a visible message. Set to a non-empty string to additionally display that message in the message area, above the hint. Warnings do not block form submission. Set to `null` (the default) or `undefined`, or remove the attribute, to clear the warning."
      },
      {
        "name": "ai",
        "property": "ai",
        "type": "boolean",
        "default": "false",
        "description": "Draws an ai-style input with AI colored border and icon. Suppressed visually once\n`hasInteracted` flips, but the property and attribute are preserved so the styling\nreturns after `formResetCallback` clears `hasInteracted`."
      },
      {
        "name": "hint",
        "property": "hint",
        "type": "string",
        "default": "''",
        "description": "The form control's hint text. If you need to display HTML, use the `hint` slot instead."
      },
      {
        "name": "disabled",
        "property": "disabled",
        "type": "boolean",
        "description": "Disables the form control. HTML treats a control as disabled when either its own `disabled` is\nset or an ancestor `<fieldset>` is disabled, so reading this reports the combined state while\nwriting it sets only this element's own. Keeping the two apart is what lets a fieldset be\nre-enabled without clearing a disabled state the consumer set in the meantime."
      },
      {
        "name": "dir",
        "property": "dir",
        "type": "string"
      },
      {
        "name": "lang",
        "property": "lang",
        "type": "string"
      }
    ],
    "properties": [
      {
        "name": "value",
        "type": "string",
        "description": "The current value of the radio group, submitted as a name/value pair with form data. A group with\nnothing selected reads `''`, as a native group's `RadioNodeList` does — never `null`."
      },
      {
        "name": "validationTarget",
        "type": "undefined | HTMLElement",
        "description": "We use the first available radio as the validationTarget similar to native HTML that shows the validation popup on\nthe first radio element."
      },
      {
        "name": "form",
        "type": "HTMLFormElement | null",
        "description": "By default, form controls are associated with the nearest containing `<form>` element. This attribute allows you\nto place the form control outside of a form and associate it with the form that has this `id`. The form must be in\nthe same document or shadow root for this to work."
      }
    ],
    "methods": [
      {
        "name": "setValue",
        "parameters": [
          {
            "name": "args",
            "type": "Parameters<EdFormAssociatedElement['setValue']>"
          }
        ],
        "description": "Only a checked radio is submitted (HTML, \"Constructing the entry list\": a radio button whose\ncheckedness is false is skipped), so a group with no selection contributes no entry at all —\neven though `value` reads `''`. The match is on values rather than the radios' `checked` flags,\nwhich are synced an update later, and it reads the attribute as well so a child that has not\nupgraded yet still counts."
      },
      {
        "name": "focus",
        "parameters": [
          {
            "name": "options",
            "type": "FocusOptions",
            "optional": true
          }
        ],
        "description": "Sets focus on the radio group."
      },
      {
        "name": "setCustomValidity",
        "parameters": [
          {
            "name": "message",
            "type": "string"
          }
        ],
        "description": "Do not use this when creating a \"Validator\". This is intended for end users of components.\nWe track manually defined custom errors so we don't clear them on accident in our validators."
      },
      {
        "name": "resetValidity",
        "description": "Reset validity is a way of removing manual custom errors and native validation."
      },
      {
        "name": "getPropertyDescriptor",
        "static": true,
        "parameters": [
          {
            "name": "name",
            "type": "PropertyKey"
          },
          {
            "name": "key",
            "type": "string | symbol"
          },
          {
            "name": "options",
            "type": "PropertyDeclaration"
          }
        ],
        "returns": "PropertyDescriptor | undefined",
        "description": "Wraps the accessor of reflected properties so they always hold a valid value, as a native\nreflected IDL attribute does (`button.type = undefined` reads `submit`):\n\n- A property that declares `useDefault` takes the first value set on an element for its\n  default. That value is its field initializer's: the constructor has finished before markup,\n  a framework or any other code can set anything. Every later `null` or `undefined` means what\n  a dropped prop means on a native element — the attribute is removed: with the attribute\n  there, it is removed and Lit's `useDefault` restores the default without writing it; without\n  one, the property is set to the default. A value set and cleared again before the element\n  updates still writes the default once, from the pending reflection.\n- A Boolean is coerced with `Boolean()`, so `undefined` is `false`.\n\nLit's `useDefault` keeps the initial default out of the DOM. Setting the default explicitly\nwrites it, as `button.type = 'submit'` writes `type`."
      }
    ],
    "events": [
      {
        "name": "input",
        "react": "onInput",
        "type": "InputEvent",
        "description": "Emitted when the radio group receives user input."
      },
      {
        "name": "change",
        "react": "onChange",
        "type": "Event",
        "description": "Emitted when the radio group's selected value changes."
      },
      {
        "name": "ed-invalid",
        "react": "onEdInvalid",
        "description": "Emitted when the form control has been checked for validity and its constraints aren't satisfied."
      }
    ],
    "slots": [
      {
        "name": "",
        "description": "The default slot where `<ed-radio>` elements are placed."
      },
      {
        "name": "label",
        "description": "The radio group's label. Required for proper accessibility. Alternatively, you can use the `label` attribute."
      },
      {
        "name": "hint",
        "description": "Text that describes how to use the radio group. Alternatively, you can use the `hint` attribute."
      }
    ],
    "cssProperties": [],
    "parts": [
      {
        "name": "form-control",
        "description": "The form control that wraps the label, input, and hint."
      },
      {
        "name": "form-control-label",
        "description": "The label's wrapper."
      },
      {
        "name": "base",
        "description": "The flex container holding the radios, and the sliding indicator when `appearance` is `button`."
      },
      {
        "name": "indicator",
        "description": "The filled pill behind the checked segment, which slides between them. Only rendered when `appearance` is `button`."
      },
      {
        "name": "message",
        "description": "The state message: an error, a warning, or the AI note."
      },
      {
        "name": "hint",
        "description": "The hint's wrapper."
      }
    ],
    "states": [
      {
        "name": "warning",
        "description": "Applied when the radio group carries the warning hint state."
      },
      {
        "name": "ai",
        "description": "Applied when the radio group carries the AI hint state."
      },
      {
        "name": "error",
        "description": "Applied when the radio group carries the error hint state."
      },
      {
        "name": "disabled",
        "description": "The control is disabled, by its own attribute or by an ancestor fieldset."
      },
      {
        "name": "required",
        "description": "The control is required."
      },
      {
        "name": "optional",
        "description": "The control is not required."
      },
      {
        "name": "invalid",
        "description": "The value fails constraint validation, whether or not the user has touched the control yet."
      },
      {
        "name": "valid",
        "description": "The value passes constraint validation."
      },
      {
        "name": "user-invalid",
        "description": "Invalid, and the user has interacted with the control. This is the one to style for an error: it behaves like the platform's `:user-invalid`, so an untouched field is not marked wrong before the user has had a chance to fill it in."
      },
      {
        "name": "user-valid",
        "description": "Valid, and the user has interacted with the control."
      },
      {
        "name": "dirty",
        "description": "The user has interacted with the control."
      }
    ]
  },
  "import": "import '@eurodata/eurodata-ui/dist/components/radio-group/radio-group.js';",
  "react": {
    "component": "EdRadioGroup",
    "import": "import EdRadioGroup from '@eurodata/eurodata-ui/dist/react/radio-group/index.js';"
  }
}
