Skip to main content
Vuetify0 is now in alpha!
Vuetify0 Logo
Theme
Mode
Palettes
Accessibility
Vuetify One
Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

Radio

A radio button for single-selection groups with roving focus and shared v-model state.

Usage

Anatomy

vue
<script setup lang="ts">
  import { Radio } from '@vuetify/v0'
</script>

<template>
  <Radio.Group>
    <Radio.Root>
      <Radio.Indicator />
    </Radio.Root>

    <Radio.Root>
      <Radio.Indicator />
    </Radio.Root>
  </Radio.Group>

  <!-- With form submission -->
  <Radio.Group>
    <Radio.Root>
      <Radio.Indicator />

      <Radio.HiddenInput />
    </Radio.Root>

    <Radio.Root>
      <Radio.Indicator />

      <Radio.HiddenInput />
    </Radio.Root>
  </Radio.Group>
</template>

Examples

Recipes

Form Integration

Pass the name prop on Radio.Group and every Radio.Root inside it renders a hidden native radio input automatically — the group’s name cascades to each Radio.Root unless the child sets its own. No Radio.HiddenInput placement is required:

vue
<template>
  <Radio.Group v-model="selected" name="size">
    <Radio.Root value="small">
      <Radio.Indicator />
      Small
    </Radio.Root>

    <Radio.Root value="large">
      <Radio.Indicator />
      Large
    </Radio.Root>
  </Radio.Group>
</template>

Radio.HiddenInput is exported as an internal building block for custom layouts, but auto-rendering via name is the only supported form integration path — placing Radio.HiddenInput as a child of a Radio.Root that already resolves a name (from itself or the parent Radio.Group) will produce two hidden inputs.

Styling with Data Attributes

Radio.Root exposes data attributes for CSS styling without conditional classes:

AttributeValuesNotes
data-statechecked, uncheckedReflects current visual state
data-disabledtruePresent only when disabled
vue
<template>
  <Radio.Root class="size-5 rounded-full border data-[state=checked]:border-primary data-[disabled]:opacity-50">
    <Radio.Indicator class="size-2.5 rounded-full bg-primary" />
  </Radio.Root>
</template>

Accessibility

The Radio components handle all ARIA attributes automatically:

  • role="radiogroup" on the Group

  • role="radio" on each Root

  • aria-checked reflects checked state

  • aria-disabled when radio is disabled

  • aria-required for form validation (set on Group)

  • aria-label from the label prop

  • Roving tabindex — only the selected radio (or first non-disabled if none selected) is tabbable

  • Space key selects the focused radio

  • Arrow keys navigate between radios

For custom implementations, use renderless mode and bind the attrs slot prop to your element:

vue
<template>
  <Radio.Root v-slot="{ attrs }" renderless>
    <div v-bind="attrs">
      <!-- Custom radio visual -->
    </div>
  </Radio.Root>
</template>

Arrow keys provide circular navigation within a radio group:

KeyAction
SpaceSelect focused radio
ArrowUp / ArrowLeftMove to previous radio
ArrowDown / ArrowRightMove to next radio

Navigation automatically skips disabled items and wraps around.

API Reference

The following API details are for all variations of the Radio component.
Was this page helpful?

Ctrl+/