Skip to main content
Light Dark System

Radio Group

<zn-radio-group> | ZnRadioGroup
Since 1.0 experimental

Short summary of the component’s intended use.

Option 1 Option 2 Option 3
<zn-radio-group label="Select an option">
  <zn-radio value="1">Option 1</zn-radio>
  <zn-radio value="2">Option 2</zn-radio>
  <zn-radio value="3">Option 3</zn-radio>
</zn-radio-group>

Examples

Basic Radio Group

Use the label attribute to give the radio group an accessible label. For labels that contain HTML, use the label slot instead. A basic radio group lays out multiple radio items vertically.

Initiate outbound transfers Approve outbound transfers Export transactions
<zn-radio-group label="Financial products permissions" name="a">
  <zn-radio value="initiate-outbound">Initiate outbound transfers</zn-radio>
  <zn-radio value="approve-outbound">Approve outbound transfers </zn-radio>
  <zn-radio value="export">Export transactions</zn-radio>
</zn-radio-group>

Initial Values

Use the value attribute to set the initial selection.

Credit Card Debit Card Bank Transfer
<zn-radio-group label="Select a payment method" value="credit-card">
  <zn-radio value="credit-card">Credit Card</zn-radio>
  <zn-radio value="debit-card">Debit Card</zn-radio>
  <zn-radio value="bank-transfer">Bank Transfer</zn-radio>
</zn-radio-group>

Help Text

Add descriptive help text to a radio group with the help-text attribute. For help texts that contain HTML, use the help-text slot instead.

Initiate outbound transfers Approve outbound transfers Export transactions
Initiate outbound transfers Approve outbound transfers Export transactions
Outbound transfers require separate initiators and approvers
<zn-radio-group label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers" name="a">
  <zn-radio value="initiate-outbound">Initiate outbound transfers</zn-radio>
  <zn-radio value="approve-outbound">Approve outbound transfers </zn-radio>
  <zn-radio value="export">Export transactions</zn-radio>
</zn-radio-group>
<br>
<zn-radio-group label="Financial products permissions" name="b">
  <zn-radio value="initiate-outbound">Initiate outbound transfers</zn-radio>
  <zn-radio value="approve-outbound">Approve outbound transfers </zn-radio>
  <zn-radio value="export">Export transactions</zn-radio>
  <div slot="help-text">Outbound transfers require <strong>separate</strong> initiators and approvers</div>
</zn-radio-group>

Label with Tooltip

Use the label-tooltip attribute to add text that appears in a tooltip triggered by an info icon next to the label.

Initiate outbound transfers Approve outbound transfers Export transactions
<zn-radio-group name="a" label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers" label-tooltip="These apply to cash account only">
  <zn-radio value="initiate-outbound">Initiate outbound transfers</zn-radio>
  <zn-radio value="approve-outbound">Approve outbound transfers </zn-radio>
  <zn-radio value="export">Export transactions</zn-radio>
</zn-radio-group>

Sizes

Use the size attribute to change a radio group’s size. This size will be applied to all child radios in the group. Size medium is the default.

Option 1 Option 2 Option 3
Option 1 Option 2 Option 3
Option 1 Option 2 Option 3
<zn-radio-group label="Small size" size="small" name="size-small">
  <zn-radio value="option-1">Option 1</zn-radio>
  <zn-radio value="option-2">Option 2</zn-radio>
  <zn-radio value="option-3">Option 3</zn-radio>
</zn-radio-group>
<br />
<zn-radio-group label="Medium size" size="medium" name="size-medium">
  <zn-radio value="option-1">Option 1</zn-radio>
  <zn-radio value="option-2">Option 2</zn-radio>
  <zn-radio value="option-3">Option 3</zn-radio>
</zn-radio-group>
<br />
<zn-radio-group label="Large size" size="large" name="size-large">
  <zn-radio value="option-1">Option 1</zn-radio>
  <zn-radio value="option-2">Option 2</zn-radio>
  <zn-radio value="option-3">Option 3</zn-radio>
</zn-radio-group>

Horizontal Radio Group

Use the horizontal attribute to lay out multiple radio items horizontally.

Manage transfers Export transactions
<zn-radio-group name="a" id="permissions" label="Financial products permissions" horizontal>
  <zn-radio value="manage-transfers">Manage transfers</zn-radio>
  <zn-radio value="export">Export transactions</zn-radio>
</zn-radio-group>

<style>
  zn-radio-group[id="permissions"] {
    container-type: inline-size;
    container-name: permissions;
  }

  @container permissions (max-width: 400px) {
    zn-radio-group[id="permissions"]::part(form-control-input) {
      flex-direction: column;
    }
  }
</style>

Contained Radio Group

Use the contained attribute to draw a card-like container around each radio item in the radio group. This style is useful for giving more emphasis to the list of options.

This option can be combined with the horizontal attribute.

Initiate outbound transfers Approve outbound transfers Export transactions

Initiate outbound transfers Approve outbound transfers
<zn-radio-group name="a" label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers" contained>
  <zn-radio value="initiate-outbound">Initiate outbound transfers</zn-radio>
  <zn-radio value="approve-outbound">Approve outbound transfers </zn-radio>
  <zn-radio value="export">Export transactions</zn-radio>
</zn-radio-group>
<br/>
<br/>
<zn-radio-group name="b" label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers" contained horizontal>
  <zn-radio value="initiate-outbound">Initiate outbound transfers</zn-radio>
  <zn-radio value="approve-outbound">Approve outbound transfers </zn-radio>
</zn-radio-group>

Disabling Options

Radios can be disabled by adding the disabled attribute to the respective options inside the radio group.

Initiate outbound transfers Approve outbound transfers Export transactions
<zn-radio-group name="a" label="Financial products permissions" help-text="Exporting is currently disabled for all users">
  <zn-radio value="initiate-outbound">Initiate outbound transfers</zn-radio>
  <zn-radio value="approve-outbound">Approve outbound transfers </zn-radio>
  <zn-radio value="export" disabled>Export transactions</zn-radio>
</zn-radio-group>

Form Integration

Radio group components work seamlessly with standard HTML forms. The radio group’s name attribute determines the key in the form data, and the selected radio’s value becomes the value.

Engineering Design Marketing Sales
Junior Mid-level Senior
Submit Reset
<form id="radio-form">
  <zn-radio-group name="department" label="Department" value="engineering" required>
    <zn-radio value="engineering">Engineering</zn-radio>
    <zn-radio value="design">Design</zn-radio>
    <zn-radio value="marketing">Marketing</zn-radio>
    <zn-radio value="sales">Sales</zn-radio>
  </zn-radio-group>
  <br />
  <zn-radio-group name="level" label="Experience level" value="mid" required>
    <zn-radio value="junior">Junior</zn-radio>
    <zn-radio value="mid">Mid-level</zn-radio>
    <zn-radio value="senior">Senior</zn-radio>
  </zn-radio-group>
  <br />
  <zn-button type="submit" variant="primary">Submit</zn-button>
  <zn-button type="reset">Reset</zn-button>
</form>

<script type="module">
  const form = document.getElementById('radio-form');

  form.addEventListener('submit', (e) => {
    e.preventDefault();
    const formData = new FormData(form);
    const data = Object.fromEntries(formData);
    alert('Form submitted!\n\n' + JSON.stringify(data, null, 2));
  });
</script>

Validation

Set the required attribute to make selecting an option mandatory. If a value has not been selected, it will prevent the form from submitting and display an error message.

Option 1 Option 2 Option 3
Submit
<form class="validation">
  <zn-radio-group name="a" label="Select one option" required>
    <zn-radio value="option-1">Option 1</zn-radio>
    <zn-radio value="option-2">Option 2</zn-radio>
    <zn-radio value="option-3">Option 3</zn-radio>
  </zn-radio-group>
  <br />
  <zn-button type="submit" variant="primary">Submit</zn-button>
</form>

<script type="module">
  const form = document.querySelector('.validation');

  // Wait for controls to be defined before attaching form listeners
  await Promise.all([
    customElements.whenDefined('zn-radio-group'),
  ]).then(() => {
    form.addEventListener('submit', event => {
      event.preventDefault();
      alert('All fields are valid!');
    });
  });
</script>

Custom Validity

Use the setCustomValidity() method to set a custom validation message. This will prevent the form from submitting and make the browser display the error message you provide. To clear the error, call this function with an empty string.

I’m not the right choice You must choose me I won’t work either
Submit
<form class="custom-validity">
  <zn-radio-group name="a" label="Select the second option" required>
    <zn-radio value="option-1">I'm not the right choice</zn-radio>
    <zn-radio value="option-2">You must choose me</zn-radio>
    <zn-radio value="option-3">I won't work either</zn-radio>
  </zn-radio-group>
  <br />
  <zn-button type="submit" variant="primary">Submit</zn-button>
</form>

<script type="module">
  const form = document.querySelector('.custom-validity');
  const radioGroup = form.querySelector('zn-radio-group');
  const errorMessage = 'You must choose the second option';

  // Set initial validity as soon as the element is defined
  customElements.whenDefined('zn-radio').then(() => {
    radioGroup.setCustomValidity(errorMessage);
  });

  // Update validity when a selection is made
  form.addEventListener('zn-change', () => {
    const isValid = radioGroup.value === 'option-2';
    radioGroup.setCustomValidity(isValid ? '' : errorMessage);
  });

  // Wait for controls to be defined before attaching form listeners
  await Promise.all([
    customElements.whenDefined('zn-radio-group'),
  ]).then(() => {
    form.addEventListener('submit', event => {
      event.preventDefault();
      alert('All fields are valid!');
    });
  });
</script>

Programmatic Control

You can control the radio group programmatically using its methods and properties:

Option 1 Option 2 Option 3 Option 4
Focus Set Value to Option 3 Check Validity Get Form
<div class="form-spacing">
  <zn-radio-group id="programmatic-radio" label="Programmatic control" name="programmatic">
    <zn-radio value="option-1">Option 1</zn-radio>
    <zn-radio value="option-2">Option 2</zn-radio>
    <zn-radio value="option-3">Option 3</zn-radio>
    <zn-radio value="option-4">Option 4</zn-radio>
  </zn-radio-group>

  <div style="margin-top: 1rem; display: flex; gap: 0.5rem; flex-wrap: wrap;">
    <zn-button id="focus-btn" size="small">Focus</zn-button>
    <zn-button id="set-value-btn" size="small">Set Value to Option 3</zn-button>
    <zn-button id="check-validity-btn" size="small">Check Validity</zn-button>
    <zn-button id="get-form-btn" size="small">Get Form</zn-button>
  </div>
</div>

<script type="module">
  const radioGroup = document.getElementById('programmatic-radio');

  document.getElementById('focus-btn').addEventListener('click', () => radioGroup.focus());
  document.getElementById('set-value-btn').addEventListener('click', () => {
    radioGroup.value = 'option-3';
  });
  document.getElementById('check-validity-btn').addEventListener('click', () => {
    alert('Valid: ' + radioGroup.checkValidity());
  });
  document.getElementById('get-form-btn').addEventListener('click', () => {
    const form = radioGroup.getForm();
    alert('Form: ' + (form ? form.id || 'Form found (no ID)' : 'Not in a form'));
  });
</script>

Keyboard Navigation

The radio group component supports comprehensive keyboard navigation:

  • Tab - Move focus to/from the radio group (focuses the checked radio, or the first radio if none are checked)
  • Arrow Up/Left - Select the previous radio in the group (wraps around to the last option)
  • Arrow Down/Right - Select the next radio in the group (wraps around to the first option)
  • Space - Select the currently focused radio

Customizing Label Position

Use CSS parts to customize the way form controls are drawn. This example uses CSS grid to position the label to the left of the control.

Engineering Design Marketing
<zn-radio-group class="label-on-left" label="Department" name="dept-custom">
  <zn-radio value="engineering">Engineering</zn-radio>
  <zn-radio value="design">Design</zn-radio>
  <zn-radio value="marketing">Marketing</zn-radio>
</zn-radio-group>

<style>
  .label-on-left {
    --label-width: 5rem;
  }

  .label-on-left::part(form-control) {
    display: grid;
    grid: auto / var(--label-width) 1fr;
    gap: var(--zn-spacing-3x-small) var(--zn-spacing-medium);
    align-items: start;
  }

  .label-on-left::part(form-control-label) {
    text-align: right;
    padding-top: 0.25rem;
  }

  .label-on-left::part(form-control-help-text) {
    grid-column-start: 2;
  }
</style>

Importing

If you’re using the autoloader or the traditional loader, you can ignore this section. Otherwise, feel free to use any of the following snippets to cherry pick this component.

To import this component from the CDN using a script tag:

<script type="module" src="https://cdn.jsdelivr.net/npm/@kubex/zinc@1.0.66/dist/components/radio-group/radio-group.js"></script>

To import this component from the CDN using a JavaScript import:

import 'https://cdn.jsdelivr.net/npm/@kubex/zinc@1.0.66/dist/components/radio-group/radio-group.js';

To import this component using a bundler:

import '@kubex/zinc/dist/components/radio-group/radio-group.js';

Slots

Name Description
(default) The default slot.
example An example slot.

Learn more about using slots.

Properties

Name Description Reflects Type Default
label The radio group’s label. Required for proper accessibility. If you need to display HTML, use the label slot instead. string ''
labelTooltip
label-tooltip
Text that appears in a tooltip next to the label. If you need to display HTML in the tooltip, use the label-tooltip slot instead. string ''
helpText
help-text
The radio groups’ help text. If you need to display HTML, use the help-text slot instead. string ''
name The name of the radio group, submitted as a name/value pair with form data. string ''
value The current value of the radio group, submitted as a name/value pair with form data. string ''
size The radio group’s size. This size will be applied to all child radios 'small' | 'medium' | 'large' 'medium'
horizontal The checkbox group’s orientation. Changes the group’s layout from the default (vertical) to horizontal. boolean false
contained The checkbox group’s style. Changes the group’s style from the default (plain) style to the ‘contained’ style. This style will be applied to all child checkboxes. boolean false
form By default, form controls are associated with the nearest containing <form> element. This attribute allows you to place the form control outside a form and associate it with the form that has this id. The form must be in the same document or shadow root for this to work. string ''
required Ensures a child radio is checked before allowing the containing form to submit. boolean false
validationMessage Gets the validation message - -
updateComplete A read-only promise that resolves when the component has finished updating.

Learn more about attributes and properties.

Events

Name React Event Description Event Detail
zn-event-name Emitted as an example. -

Learn more about events.

Methods

Name Description Arguments
checkValidity() Checks for validity but does not show a validation message. Returns true when valid and false when invalid. -
getForm() Gets the associated form, if one exists. -
reportValidity() Checks for validity and shows the browser’s validation message if the control is invalid. -
setCustomValidity() Sets a custom validation message. Pass an empty string to restore validity. message:

Learn more about methods.

Custom Properties

Name Description Default
--example An example CSS custom property.

Learn more about customizing CSS custom properties.

Parts

Name Description
base The component’s base wrapper.

Learn more about customizing CSS parts.

Dependencies

This component automatically imports the following dependencies.

  • <zn-example>