Radio
v0.0.10
mix mishka.ui.gen.headless radio
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)
<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.
Attributes
| Name | Type | Default | Values | Required | Description |
|---|---|---|---|---|---|
id
|
string
| — | — | Yes | Id of the native input (the label derives {id}-root) |
name
|
string
| — | — | No | Shared name forms the native radio group |
value
|
string
| — | — | No | This radio's submitted value |
checked
|
boolean
|
false
| — | No | Whether this radio is selected |
disabled
|
boolean
|
false
| — | No | Ignore interaction (data-disabled) |
readonly
|
boolean
|
false
| — | No | Block selection but stay focusable (data-readonly) |
required
|
boolean
|
false
| — | No | Require a selection for form submit (data-required) |
class
|
any
| — | — | No | Extra classes for the root |
input_class
|
any
| — | — | No | Extra classes for the native input |
indicator_class
|
any
| — | — | No | Extra classes for the indicator |
label_class
|
any
| — | — | No | Extra classes for the label |
rest
|
global
| — | — | No | — |
Slots
| Name | Required | Description |
|---|---|---|
indicator
| No | Visual content of the indicator (e.g. a center dot) |
inner_block
| Yes | The radio label |
Options
Each option takes one or more of its values, separated by commas.
| Option | Values |
|---|---|
--type
|
radio
|
--module
| A module name of your own |
What it generates
mix mishka.ui.gen.headless radio