Radio

v0.0.10

v0.0.10StableHeadlessStatelessAccessibleJSApache-2.0
Installation mix mishka.ui.gen.headless radio
Source View Source

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)

Base UI Radio example (Phoenix headless)

Best apple
heex
<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.

Partdata-partState / ARIAPurpose
Root(label element)data-checked, data-unchecked, data-disabled, data-readonly, data-requiredThe label wrapping the whole control; carries the Radio hook.
Inputinputtype="radio", native groupingThe native radio input driving keyboard and form value.
Indicatorindicatordata-checked, data-unchecked, aria-hiddenThe selection dot, shown via data-checked.
Labellabel-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.