Radio

One choice from a few options shown together, side by side or as selectable rows.

StableSince 1.0.0
On this page

Import

import { Radio, RadioGroup } from '@envsemble/envui';

Usage

A RadioGroup holds Radio options and is a native <fieldset>: its label, the legend, names the choice, or aria-label where it has none.

  • Each Radio has a value, which the group reports and a form submits, its label, and an optional description, a short muted line read with its name.
  • Uncontrolled: defaultValue, which a form reset returns to.
  • Controlled: value and onValueChange; null chooses none.
  • Without either, no option is chosen until people choose one.
  • Set name in a form; without it the group takes a unique generated one.
  • description under the options, and error, such as for a required group left empty, describe the group, as on a field.
ProjectAccess.tsx
import { useState } from 'react';
import { Radio, RadioGroup } from '@envsemble/envui';

export default function ProjectAccess() {
  const [access, setAccess] = useState('team');
  return (
    <RadioGroup label="Access" name="access" value={access} onValueChange={setAccess}>
      <Radio value="team" label="Team" />
      <Radio value="private" label="Only me" />
      <Radio value="link" label="Anyone with the link" />
    </RadioGroup>
  );
}

Orientation

orientation is horizontal, the default, radios before their labels side by side, which wrap onto more lines, or vertical, connected selectable rows that fill the width, for options with a description, as the VisibilityRows example shows.

<RadioGroup orientation="vertical" label="Visibility" name="visibility" defaultValue="team">
  <Radio value="team" label="Team" description="Everyone at Northwind can open it." />
  <Radio value="private" label="Private" description="Only the people you invite." />
</RadioGroup>

Required and disabled

required asks for a choice before the form submits, through native constraint validation. Pass the message as error and move focus to the group when a form is refused, as the RequiredChoice example does. disabled disables every option: the group keeps its choice visible, but can't be focused or changed. Say where to change it in a sentence beside it.

<RadioGroup label="Access" value="team" disabled aria-describedby={reason}>
  <Radio value="team" label="Team" />
  <Radio value="private" label="Private" />
</RadioGroup>
<Text id={reason} variant="body-sm">
  This folder takes its access from Northwind launch. Change it there.
</Text>

Composition

The parts are the group, env-radio-group, with data-orientation and its legend, env-radio-group > legend; each option, env-radio, the label around the radio and its text; the description, env-radio-description; and the native radio, env-radio-input. A Radio's className and style reach its root, and ref and the other native props the input, so a form library can register and focus it.

Accessibility

You provide

  • A label for the group, or aria-label.
  • A name for a group in a form.
  • Focus on the group when a form is refused.

envUI provides

  • A native <fieldset> named by its <legend>, and native radios sharing one name.
  • Each option's label and description as its name, and its position, such as 2 of 3.
  • The focus ring, and options 2.75 rem tall on touch screens.

Props

RadioGroup

A set of options to choose exactly one from: a native fieldset whose legend names the group, with Radio options inline or as selectable rows.

PropTypeDescription
ref
Ref<HTMLFieldSetElement>
The group's fieldset.
label
ReactNode
The group's visible name, such as Visibility, as the fieldset's legend above the options. It names the group for assistive technology; without it, use aria-label or aria-labelledby.
value
stringnull
The value of the chosen option in a controlled group, or null for none; update it from onValueChange.
defaultValue
string
The value of the option an uncontrolled group starts with; a native form reset returns to it. Without value or defaultValue, no option is chosen until people choose one.
onValueChange
(value: string) => void
Receives the value of the option people choose.
description
ReactNode
Lasting guidance under the options, such as what the choice changes, linked to the group as its description.
error
ReactNode
A message under the options that says how to correct the choice, such as for a required group left empty; it joins the group's description, after the description.
name
string
The name every radio of the group submits its value under. Set it in a form; without it the group takes a unique generated name, so its radios still work as one group.
requiredDefault false
boolean
Require a choice before the form submits, through native constraint validation.
orientationDefault 'horizontal'
'horizontal''vertical'
How the options are laid out: horizontal, radios before their labels side by side that wrap onto more lines; or vertical, connected selectable rows that fill the width, with the label and description at the start and the radio at the end, for options that need explaining.
disabledDefault false
boolean
Disable every option of the group; a disabled group can't be focused or changed.

Also accepts the native props of <fieldset>, such as ref, className and aria-* attributes.

Radio

One option of a RadioGroup: a native radio input with its label, and an optional description.

PropTypeDescription
ref
Ref<HTMLInputElement>
The native radio input, so that a form library can register it and focus it; the other native props reach it too.
className
string
The option's class, on its root element, the label around the radio and the text.
style
CSSProperties
Styles of the root element.
valuerequired
string
The value the group reports and a form submits when this option is chosen.
labelrequired
ReactNode
The option's visible name, such as Private; pressing it chooses the option.
description
ReactNode
A short, muted line under the label that helps people choose, such as Only the people you invite. It is part of the option's label, so it is read with its name.

Also accepts the native props of <input>, such as ref, className and aria-* attributes.

Part names

Each part's class and state attributes are public and versioned, for an application's CSS to style.

RadioGroup

env-radio-group
The group of radios.
env-radio-group-description
The description under the options.
env-radio-group-error
The error under the options.
data-orientation
horizontal · vertical

Radio

env-radio
One radio with its label.
env-radio-description
A radio's description.
env-radio-input
The native input.
data-orientation
horizontal · vertical

Color properties

Each sets a color of one instance, through style or CSS; its hover, focus and press follow it. They are public and versioned.

--env-radio-container
The row's fill in a vertical group; the state layers lie over it.
--env-radio-content
The label, and the color of a row's state layers.
--env-radio-selected
The dot and ring of the chosen option.

Changelog

1.0.0

RadioGroup's variant is orientation: inline is horizontal and rows is vertical; Radio's detail is description. className and style style a Radio's root rather than the input, which keeps ref and the other native props. A focused radio shows the focus ring. The classes follow the component: env-radio-options is env-radio-group with [data-orientation], env-radio-option and the inline label are env-radio, env-radio-control is env-radio-input and env-radio-detail env-radio-description.

1.0.0-prerelease.6

Colors under the pointer and while pressed change with --env-motion-ease-enter, rather than easing in slowly, so hover and press show from the first frame.

The group's legend takes the size, weight and muted color of a field's floated label. In a vertical group, the chosen row's label keeps the text color, its choice shown by the selection's fill and the filled radio, and on a dialog, a popover or a muted or raised card or Surface, the rows take a faint neutral tint, so they keep their shape there.

Beside a label that wraps or has a description, the radio sits on the middle of its first line rather than across both lines.

The group's error shows the error icon, as a field's does.

1.0.0-prerelease.5

RadioGroup takes description and error, as a field does, and a controlled value of null chooses none.

The chosen row of a group in rows takes the selection's fill and text, as a selected list row and Select's chosen option do, rather than the hover fill.