Forms & Inputs
Radio Group
Owns single selection across its nana-radio / nana-radio-button children. Implements the ARIA radiogroup keyboard pattern — arrow keys move and select, with roving tabindex — shares one size/disabled, and takes part in native forms through name/value.
Both child flavours are imported for you, so a group works with whichever the markup uses.
Preview
Section titled “Preview”<nana-radio-group label="Plan" name="plan" value="pro">
<nana-radio value="free">Free</nana-radio>
<nana-radio value="pro">Pro</nana-radio>
<nana-radio value="team" disabled>Team</nana-radio>
</nana-radio-group> Installation
Section titled “Installation”npm install @nana-tec/ui-componentsImport
Section titled “Import”import "@nana-tec/ui-components/radio-group";Already registered if you imported @nana-tec/ui-components/radio.
Basic usage
Section titled “Basic usage”<nana-radio-group label="Plan" name="plan" value="pro"> <nana-radio value="free">Free</nana-radio> <nana-radio value="pro">Pro</nana-radio></nana-radio-group>React and Svelte ship the same group as RadioGroup — see
Radio for both frameworks’ props.
value is the single selected value, and it is what the group submits. The
group writes it back onto the children as checked, so it stays the one source
of truth no matter which child the user clicked or arrowed to.
<nana-radio-group value="pro"> <nana-radio value="free">Free</nana-radio> <nana-radio value="pro">Pro</nana-radio></nana-radio-group>Only one nana-change fires per selection. The group swallows the child’s own
event and re-emits its own with the same detail.value, so a listener on the
group never sees a duplicate.
Shared state
Section titled “Shared state”size and disabled are set on the group and reach every child.
<nana-radio-group label="Delivery" size="sm" disabled>
<nana-radio value="standard">Standard</nana-radio>
<nana-radio value="express" checked>Express</nana-radio>
</nana-radio-group> A group-level disabled deliberately does not overwrite a child’s own
disabled. It is applied at the group instead — the row container takes
pointer-events: none and the group carries aria-disabled — so an option
disabled on its own stays disabled when the group is re-enabled.
Horizontal
Section titled “Horizontal”orientation="horizontal" lays the options out in a row, which is what turns
nana-radio-button children into a segmented control.
<nana-radio-group
label="Billing period"
orientation="horizontal"
value="monthly"
>
<nana-radio-button value="monthly">Monthly</nana-radio-button>
<nana-radio-button value="yearly">Yearly</nana-radio-button>
<nana-radio-button value="lifetime">Lifetime</nana-radio-button>
</nana-radio-group> Help text and errors
Section titled “Help text and errors”help-text sits beneath the options. Setting error replaces it with a
role="alert" message and flags every child invalid, which is what turns the
buttons red.
<nana-radio-group
label="Notifications"
name="notify"
value=""
help-text="Choose how we reach you."
>
<nana-radio
value="email"
label="Email"
description="Updates to your inbox"
></nana-radio>
<nana-radio
value="sms"
label="SMS"
description="Texts to your phone"
></nana-radio>
</nana-radio-group>
<nana-radio-group
label="Seat count"
name="seats"
required
error="Choose a billing period."
>
<nana-radio-button value="1">1 seat</nana-radio-button>
<nana-radio-button value="5">5 seats</nana-radio-button>
</nana-radio-group> Selecting an option clears error, so a message you set yourself disappears on
the next interaction.
The group is a form-associated custom element: it submits name=value, and
form.reset() returns it to no selection. With required and nothing selected
it reports valueMissing against the message “Please select an option.”, so
:invalid and reportValidity() work the way they do on a native control. A
browser restoring a back-navigated form sets the group back from its submitted
value.
<form> <nana-radio-group label="Plan" name="plan" required> <nana-radio value="free">Free</nana-radio> <nana-radio value="pro">Pro</nana-radio> </nana-radio-group> <button type="submit">Continue</button></form>Keyboard
Section titled “Keyboard”| Key | Does |
|---|---|
↓ → | Select the next option, wrapping |
↑ ← | Select the previous option, wrapping |
Space Enter | Select the focused option |
Arrow keys move and select, following the ARIA radiogroup pattern, and only
enabled options take part. Exactly one option is tabbable — the selected one, or
the first enabled option when nothing is selected — so Tab moves past the
group rather than through every radio in it.
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
disabled | disabled | boolean | false | Disable every child |
error | error | string | undefined | — | Error message shown beneath the group (also flags children invalid) |
helpText | help-text | string | undefined | — | Helper text shown beneath the group |
label | label | string | undefined | — | Group label |
name | name | string | '' | Form field name |
orientation | orientation | RadioGroupOrientation | 'vertical' | Lay items out in a column (default) or a row |
required | required | boolean | false | Require a selection for form validation |
size | size | RadioSize | undefined | — | Size applied to every child |
value | value | string | '' | Selected value |
Events
| Event | Description |
|---|---|
nana-change | Fired on selection (detail.value) |
Slots
| Slot | Description |
|---|---|
(default) | nana-radio / nana-radio-button children |
CSS parts
| Part | Description |
|---|---|
::part(legend) | The group label |
::part(items) | The layout container |
CSS custom properties
| Property | Description |
|---|---|
--nana-radio-group-gap | Gap between options |
Accessibility
Section titled “Accessibility”- The host carries
role="radiogroup"and each childrole="radio"with a livearia-checked. - The group is
aria-disabledas a whole whendisabled, and the legend shows a danger-coloured asterisk whenrequired. - Errors render in a
role="alert", so a message that appears after submit is announced.