Getting StartedInstall and bootstrap headless foundations 4
LayoutHeadless structural primitives for expandable and container patterns 6
OverlayHeadless modal and floating layer behavior 3
FeedbackHeadless notification and status communication patterns 5
FormHeadless input and selection contracts 17
UtilityReusable action, identity, and clipboard behavior 6
NavigationHeadless trails, trees, menus, and command surfaces 7

Headless radio

Headless radio keeps the native <input type="radio"> element in place and adds a stable contract for checked, readonly, invalid, and focus-visible styling.

  • Native single-choice behavior through shared name values.
  • Readonly support that stays focusable while reverting user changes.
  • Consistent data-* hooks for custom wrappers and visual systems.

Installation

Import only the radio primitive when the surrounding layout and labels belong to your app.

Primitive import

ts
import { TngRadio } from '@tailng-ui/primitives';

Basic usage

The directive attaches directly to a native radio input, but you almost always want a clickable label or fieldset around it so the group stays readable and easy to target.

Minimal attachment

html
<input tngRadio name="plan" value="starter" />

Recommended grouped pattern

html
<fieldset class="radio-group">
  <legend>Billing plan</legend>
  <label class="radio-row">
    <input tngRadio name="billing-plan" value="starter" />
    <span>Starter</span>
  </label>
  <label class="radio-row">
    <input tngRadio name="billing-plan" value="pro" [checked]="true" />
    <span>Pro</span>
  </label>
</fieldset>

Style variants

The same headless radio behavior rendered inside a plain CSS shell and a Tailwind utility shell.

Billing plan shell (Plain-CSS)

Billing plan

Selected: pro

Accessibility baseline

  • Use a shared name so browsers enforce single-selection semantics.
  • Wrap related radios in a <fieldset> and <legend> when the label belongs to the group.
  • data-focus-visible keeps keyboard-only focus styling straightforward.