Radio Button
Single-select radio groups — default, custom styled, card-style, list group, and inline vs stacked layouts.
All radio groups use native <input type="radio"> elements styled
via DaisyUI's radio class. Alpine.js is used only where reactive
state adds visible value — size/color pickers and the card-style selector.
Simple list groups are pure HTML so they work without JavaScript.
1 — Default
Stock DaisyUI radio in a fieldset with a
legend. No JS required. Stacked (default) and inline layouts shown side
by side, plus all six color tokens.
<!-- Stacked (default) -->
<fieldset class="fieldset">
<legend class="fieldset-legend">Billing frequency</legend>
<label class="fieldset-label cursor-pointer">
<input type="radio" name="frequency" value="weekly"
class="radio radio-sm radio-primary" checked />
<span class="text-sm">Weekly</span>
</label>
<label class="fieldset-label cursor-pointer">
<input type="radio" name="frequency" value="monthly"
class="radio radio-sm radio-primary" />
<span class="text-sm">Monthly</span>
</label>
</fieldset>
<!-- Inline -->
<fieldset class="fieldset">
<legend class="fieldset-legend">Size</legend>
<div class="flex flex-wrap gap-4">
<label class="flex items-center gap-2 cursor-pointer">
<input type="radio" name="size" value="sm"
class="radio radio-sm radio-primary" />
<span class="text-sm">Small</span>
</label>
<!-- … -->
</div>
</fieldset>
2 — Sizes
Five size steps via DaisyUI size modifiers. No custom CSS required —
all are Tailwind-composable with other radio-* tokens.
3 — With Description Text
Label + helper text pattern. The radio aligns to the first line of the label; the description sits beneath using standard Tailwind utility classes.
<fieldset class="fieldset gap-0">
<legend class="fieldset-legend mb-1">Shipping method</legend>
<label class="flex items-center gap-3 cursor-pointer py-2.5
border-b border-base-200 last:border-0">
<input type="radio" name="shipping" value="standard"
class="radio radio-sm radio-primary shrink-0" checked />
<span class="flex-1 min-w-0">
<span class="flex justify-between items-baseline gap-2">
<span class="text-sm font-medium">Standard Shipping</span>
<span class="text-sm font-semibold text-primary">Free</span>
</span>
<span class="text-xs text-base-content/50">5–7 business days</span>
</span>
</label>
<!-- repeat for each option … -->
</fieldset>
4 — Card-style
The entire card is the clickable label. Alpine tracks the selected
value so the card border and radio reflect the same state without
duplicating logic. The hidden native <input>
stays accessible via keyboard.
Compact — shipping method
Full card — pricing plan
<div x-data="{ selected: 'pro' }" class="grid grid-cols-3 gap-3">
<!-- Repeat this label for each plan -->
<label
class="relative flex flex-col gap-3 p-4 border rounded-[--radius-sm]
cursor-pointer transition-colors"
:class="selected === 'pro'
? 'border-primary bg-primary/5 ring-1 ring-primary/30'
: 'border-base-300 bg-base-100 hover:border-base-400'"
>
<input type="radio" name="plan" value="pro"
class="radio radio-sm radio-primary"
x-model="selected" />
<div>
<p class="font-semibold text-sm">Pro</p>
<p class="text-xl font-bold mt-0.5">
$19 <span class="text-sm font-normal text-base-content/50">/mo</span>
</p>
</div>
<ul class="flex flex-col gap-1">
<li class="flex items-center gap-1.5 text-xs text-base-content/70">
<span class="text-success">✓</span> 10 projects
</li>
<!-- … -->
</ul>
</label>
</div>
5 — Radio List Group
Each row is a full-width tappable area inside a bordered container —
the same pattern used in mobile settings UIs. Row highlight on selection
uses Alpine; the border container is a custom shell since DaisyUI's
menu is for navigation, not radio groups.
Default
With icon
<div x-data="{ selected: 'mentions' }">
<div class="border border-base-300 rounded-[--radius-sm] overflow-hidden
divide-y divide-base-200">
<label class="flex items-center gap-3 px-4 py-3 cursor-pointer transition-colors"
:class="selected === 'all' ? 'bg-primary/5' : 'bg-base-100 hover:bg-base-200'">
<input type="radio" name="notif" value="all"
class="radio radio-sm radio-primary"
x-model="selected" />
<span class="text-sm">All activity</span>
</label>
<!-- repeat for each option … -->
</div>
</div>
6 — States
Disabled (whole group and individual option), error with validation message, and a loading placeholder skeleton.
Error / required
Loading