Overview of the Phoenix and LiveView Headless Radio Component
The Mishka Chelekom Headless Radio
ships zero opinionated styling
- only a native
input type="radio"
wrapped in a label, full WAI-ARIA
semantics (native grouping, keyboard, form submission), and live paired-presence state
(
data-checked
/
data-unchecked
)
kept in sync across every radio sharing a
name
by the Radio
hook. Every part - root, input,
indicator
and label
- is addressable through a
*_class
attribute, so you style it entirely with your own Tailwind
classes while the accessibility and behavior keep working underneath.
Base UI Radio example (Phoenix headless)
<div role="radiogroup" aria-labelledby="baseui-radio-hero-label" class="flex flex-col items-start gap-1 text-neutral-950 dark:text-white" > <div class="text-sm font-bold" id="baseui-radio-hero-label"> Best apple </div> <.radio id="baseui-radio-hero-fuji" name="baseui-radio-hero" value="fuji-apple" checked class="flex items-center gap-2 text-sm font-normal text-neutral-950 dark:text-white" input_class="peer sr-only" indicator_class="flex size-4 shrink-0 items-center justify-center border rounded-full p-0 border-neutral-950 bg-white text-white dark:border-white dark:bg-neutral-950 dark:text-neutral-950 data-[checked]:bg-neutral-950 data-[checked]:text-white dark:data-[checked]:bg-white dark:data-[checked]:text-neutral-950 before:size-2 before:rounded-full before:bg-current data-[unchecked]:before:hidden peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-neutral-950 dark:peer-focus-visible:outline-white" > Fuji </.radio> <.radio id="baseui-radio-hero-gala" name="baseui-radio-hero" value="gala-apple" class="flex items-center gap-2 text-sm font-normal text-neutral-950 dark:text-white" input_class="peer sr-only" indicator_class="flex size-4 shrink-0 items-center justify-center border rounded-full p-0 border-neutral-950 bg-white text-white dark:border-white dark:bg-neutral-950 dark:text-neutral-950 data-[checked]:bg-neutral-950 data-[checked]:text-white dark:data-[checked]:bg-white dark:data-[checked]:text-neutral-950 before:size-2 before:rounded-full before:bg-current data-[unchecked]:before:hidden peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-neutral-950 dark:peer-focus-visible:outline-white" > Gala </.radio> <.radio id="baseui-radio-hero-granny" name="baseui-radio-hero" value="granny-smith-apple" class="flex items-center gap-2 text-sm font-normal text-neutral-950 dark:text-white" input_class="peer sr-only" indicator_class="flex size-4 shrink-0 items-center justify-center border rounded-full p-0 border-neutral-950 bg-white text-white dark:border-white dark:bg-neutral-950 dark:text-neutral-950 data-[checked]:bg-neutral-950 data-[checked]:text-white dark:data-[checked]:bg-white dark:data-[checked]:text-neutral-950 before:size-2 before:rounded-full before:bg-current data-[unchecked]:before:hidden peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-neutral-950 dark:peer-focus-visible:outline-white" > Granny Smith </.radio> </div>
Parts & data attributes
Each part carries a stable
data-part
and a structural
chelekom-radio__*
class you can target, plus live paired-presence state kept in sync by the
Radio
hook.
| Part | data-part | State / ARIA | Purpose |
|---|---|---|---|
| Root | (label element) | data-checked, data-unchecked, data-disabled, data-readonly, data-required | The label wrapping the whole control; carries the Radio hook. |
| Input | input | type="radio", native grouping | The native radio input driving keyboard and form value. |
| Indicator | indicator | data-checked, data-unchecked, aria-hidden | The selection dot, shown via data-checked. |
| Label | label | - | The visible text describing the option. |
Accessibility
Follows the
WAI-ARIA Radio pattern
: radios that share a
name
form a native group, so arrow keys move and select within the group and
Space
selects the focused radio.
readonly
blocks selection while keeping the radio focusable, since native radios have no
built-in readonly behavior.