Skip to content

feat(Radio): add new component#92

Merged
johnleider merged 11 commits intomasterfrom
feat/radio
Jan 13, 2026
Merged

feat(Radio): add new component#92
johnleider merged 11 commits intomasterfrom
feat/radio

Conversation

@johnleider
Copy link
Copy Markdown
Member

Summary

  • Add headless Radio component with compound pattern (Group, Root, Indicator, HiddenInput)
  • Single-selection via createSingle composable with roving tabindex
  • Full keyboard navigation (arrow keys with circular wrap, space to select)
  • Form integration with auto hidden inputs when name prop provided
  • SSR-safe focus management using element refs instead of DOM queries
  • Add el property to SingleTicket for direct element ref registration

Components

Component Purpose
Radio.Group Container providing single-selection context
Radio.Root Individual radio button with ARIA attributes
Radio.Indicator Visual checked/unchecked state indicator
Radio.HiddenInput Native radio for form submission

Accessibility

  • role="radiogroup" / role="radio"
  • aria-checked, aria-disabled, aria-required, aria-label
  • Roving tabindex (only selected/first item tabbable)
  • Arrow key navigation skips disabled items

Test plan

  • 58 tests covering selection, keyboard nav, disabled state, SSR, form integration
  • Lint, typecheck, full test suite passing

- Add Radio compound component (Group, Root, Indicator, HiddenInput)
- Uses createSingle for single-selection with roving tabindex
- Add isTabbable to SingleTicket for roving tabindex pattern
- Override register/onboard in createSingle to attach isTabbable
- Add Radio to API popover whitelist
- Add documentation page with examples
- Add IN_BROWSER guard around document.querySelector in arrow key
  navigation to prevent SSR errors
- Add ariaRequired prop to RadioGroup for form validation accessibility
- Remove redundant isNullOrUndefined check in RadioHiddenInput
- Add comprehensive arrow key navigation tests (8 new tests)
- Document aria-required in accessibility section
Replace document.querySelector with registered element refs for
arrow key navigation. Fixes disabled radios being tabbable.
@johnleider johnleider self-assigned this Jan 13, 2026
@johnleider johnleider added this to the v0.1.0 milestone Jan 13, 2026
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Jan 13, 2026

Open in StackBlitz

commit: 811a0bc

- Add RadioTicket interface extending SingleTicket with el property
- Remove `as any` casts now that el is properly typed
- Standardize prop naming convention (_name instead of nameProp)
- Remove redundant comments
Remove unsafe double type assertion in RadioRoot element ref handling.
Add 14 tests covering edge cases: empty group, dynamic items, inherent
mandatory behavior, aria-invalid, renderless indicator, object
serialization, and form attribute association.
Radio groups are inherently mandatory - selection can only be changed,
not cleared. Reword section to focus on mandatory="force" which is the
only meaningful option (auto-selects first item on mount).
Update API generator to extract @example tags from component prop/slot
JSDoc. Add examples to Radio component for disabled, mandatory, label,
name, value, form, aria-invalid props and default slots.
- Auto-detect Vue vs TypeScript for Shiki highlighting
- Wrap component examples in <template> tags for proper syntax highlighting
- Use v-on:click instead of @click to avoid JSDoc tag parsing issues
@johnleider johnleider changed the title feat(Radio): add headless radio component feat(Radio): add new component Jan 13, 2026
@johnleider johnleider merged commit 1a15037 into master Jan 13, 2026
12 of 13 checks passed
@johnleider johnleider deleted the feat/radio branch January 13, 2026 21:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant