Radio

Stable v1.0.2

Radio buttons grouped by v-model the normal way, with custom value bindings and slot support if a plain text label isn't enough.

Interactive Playground

Experiment with states, sizes, and themes for the Radio group component.

Configuration
Small (sm)
Primary
Identity
States
Select Shipping Method
v-model:"standard"
Live Source Code
<div class="flex flex-col gap-2">
  <Radio
    v-for="opt in options"
    :key="opt.value"
    v-model="shippingMethod"
    :value="opt.value"
    :label="opt.label"
    
  />
</div>

<!-- Override a single radio's id, e.g. to target it from an external <label for> -->
<Radio v-model="shippingMethod" value="standard" label="Standard Shipping" id="custom-shipping-standard" />

Implementation Examples

System Role (Numeric ID)
Value: 2 (Type: number)

1. Numeric ID Mapping

Radios natively handle strict type matching. Binding numeric IDs to the value prop works flawlessly without casting.

<Radio
  v-for="role in roleOptions"
  :key="role.value"
  v-model="roleValue"
  :value="role.value"
  :label="role.label"
  variant="success"
/>
Inline Layout
Value: "pro"

2. Horizontal Grouping

Since the Radio wrapper is an inline-flex element, you can easily stack them horizontally using a simple Flexbox gap layout.

<div class="flex flex-row flex-wrap items-center gap-6">
  <Radio v-model="planValue" value="basic" label="Basic" />
  <Radio v-model="planValue" value="pro" label="Professional" variant="warning" />
  <Radio v-model="planValue" value="enterprise" label="Enterprise" />
</div>

3. Advanced Card Layouts

Because the visual radio handles its own state internally, you can place it inside massive, highly stylized label cards without breaking accessibility.

<label
  class="flex cursor-pointer items-start gap-3 rounded-xl border-2 p-4 transition-all hover:bg-main/5"
  :class="planValue === 'monthly' ? 'border-primary bg-primary/5' : 'border-main'"
>
  <Radio v-model="planValue" value="monthly" class="mt-1" />
  <div class="flex flex-col">
    <span class="font-bold text-main">Monthly Billing</span>
    <span class="mt-0.5 text-xs text-muted">Pay as you go. Access to standard features.</span>
    <span class="mt-2 text-lg font-black text-main"
      >$29<span class="text-sm font-normal text-muted">/mo</span></span
    >
  </div>
</label>

<label
  class="relative flex cursor-pointer items-start gap-3 overflow-hidden rounded-xl border-2 p-4 transition-all hover:bg-main/5"
  :class="planValue === 'yearly' ? 'border-primary bg-primary/5' : 'border-main'"
>
  <div class="absolute top-0 right-0 rounded-bl-lg bg-success px-2 py-1 text-[10px] font-bold text-white">
    Save 20%
  </div>
  <Radio v-model="planValue" value="yearly" class="mt-1" />
  <div class="flex flex-col">
    <span class="font-bold text-main">Annual Billing</span>
    <span class="mt-0.5 text-xs text-muted">Billed upfront. Access to all premium tools.</span>
    <span class="mt-2 text-lg font-black text-main"
      >$278<span class="text-sm font-normal text-muted">/yr</span></span
    >
  </div>
</label>

API Reference

Props

Name
Type
Default
Description
v-model
any
undefined
The shared bound value for the radio group.
id
string
undefined
Overrides the auto-generated element id (useId()), e.g. for an external <label for> or test hooks.
value
any
(Required)
The specific value this radio button represents. Assigned to v-model when selected.
name
string
Generated ID
Native HTML name attribute. Used to group native radios.
label
string
undefined
The text label displayed next to the radio button.
size
"xs" | "sm" | "md" | "lg" | "xl"
"sm"
Dimensional size of the component icon and text.
variant
string
"primary"
Color theme applied to the selected icon.
disabled
boolean
false
Disables user interaction and lowers opacity.
required
boolean
false
Appends a red asterisk to the label.
error
string | boolean | string[]
false
Applies red error styling and displays error message(s) below the radio.

Events

Event Name
Payload Signature
Description
@change
(value: any, event: Event)
Fired when the radio button is selected. Emits its value and the native DOM event.