Radio Group
---import { RadioGroup, RadioGroupItem } from "@/components/starwind/radio-group";import { Label } from "@/components/starwind/label";---
<RadioGroup name="demo-radio" defaultValue="option-1" legend="Choose an option"> <div class="flex gap-2 items-center"> <RadioGroupItem id="option-1" aria-label="Option 1" value="option-1" /> <Label for="option-1">Option 1</Label> </div> <div class="flex gap-2 items-center"> <RadioGroupItem id="option-2" aria-label="Option 2" value="option-2" /> <Label for="option-2">Option 2</Label> </div> <div class="flex gap-2 items-center"> <RadioGroupItem id="option-3" aria-label="Option 3" value="option-3" /> <Label for="option-3">Option 3</Label> </div></RadioGroup>import { RadioGroup, RadioGroupItem } from "@/components/starwind/radio-group";import { Label } from "@/components/starwind/label";
export function Example() { return ( <> <RadioGroup name="demo-radio" defaultValue="option-1" legend="Choose an option"> <div className="flex gap-2 items-center"> <RadioGroupItem id="option-1" aria-label="Option 1" value="option-1" /> <Label htmlFor="option-1">Option 1</Label> </div> <div className="flex gap-2 items-center"> <RadioGroupItem id="option-2" aria-label="Option 2" value="option-2" /> <Label htmlFor="option-2">Option 2</Label> </div> <div className="flex gap-2 items-center"> <RadioGroupItem id="option-3" aria-label="Option 3" value="option-3" /> <Label htmlFor="option-3">Option 3</Label> </div> </RadioGroup> </> );}Installation
pnpx starwind@latest add radio-groupnpx starwind@latest add radio-groupyarn dlx starwind@latest add radio-groupUsage
---import { RadioGroup, RadioGroupItem } from "@/components/starwind/radio-group";import { Label } from "@/components/starwind/label";---
<RadioGroup name="demo-radio" defaultValue="option-1" legend="Choose an option"> <div class="flex gap-2 items-center"> <RadioGroupItem id="option-1" aria-label="Option 1" value="option-1" /> <Label for="option-1">Option 1</Label> </div> <div class="flex gap-2 items-center"> <RadioGroupItem id="option-2" aria-label="Option 2" value="option-2" /> <Label for="option-2">Option 2</Label> </div> <div class="flex gap-2 items-center"> <RadioGroupItem id="option-3" aria-label="Option 3" value="option-3" /> <Label for="option-3">Option 3</Label> </div></RadioGroup>import { RadioGroup, RadioGroupItem } from "@/components/starwind/radio-group";import { Label } from "@/components/starwind/label";
export function Example() { return ( <> <RadioGroup name="demo-radio" defaultValue="option-1" legend="Choose an option"> <div className="flex gap-2 items-center"> <RadioGroupItem id="option-1" aria-label="Option 1" value="option-1" /> <Label htmlFor="option-1">Option 1</Label> </div> <div className="flex gap-2 items-center"> <RadioGroupItem id="option-2" aria-label="Option 2" value="option-2" /> <Label htmlFor="option-2">Option 2</Label> </div> <div className="flex gap-2 items-center"> <RadioGroupItem id="option-3" aria-label="Option 3" value="option-3" /> <Label htmlFor="option-3">Option 3</Label> </div> </RadioGroup> </> );}Composition
Place each radio item inside the group:
RadioGroup├── RadioGroupItem└── RadioGroupItemVariants
---import { RadioGroup, RadioGroupItem } from "@/components/starwind/radio-group";import { Label } from "@/components/starwind/label";---
<RadioGroup name="variant-radio" legend="Default" defaultValue="default-1"> <div class="flex gap-2 items-center"> <RadioGroupItem id="default-1" aria-label="Default Option 1" value="default-1" variant="default" /> <Label for="default-1">Default Option 1</Label> </div> <div class="flex gap-2 items-center"> <RadioGroupItem id="default-2" aria-label="Default Option 2" value="default-2" variant="default" /> <Label for="default-2">Default Option 2</Label> </div></RadioGroup>
<RadioGroup name="variant-primary" legend="Primary" defaultValue="primary-1"> <div class="flex gap-2 items-center"> <RadioGroupItem id="primary-1" aria-label="Primary Option 1" value="primary-1" variant="primary" /> <Label for="primary-1">Primary Option 1</Label> </div> <div class="flex gap-2 items-center"> <RadioGroupItem id="primary-2" aria-label="Primary Option 2" value="primary-2" variant="primary" /> <Label for="primary-2">Primary Option 2</Label> </div></RadioGroup>
<RadioGroup name="variant-secondary" legend="Secondary" defaultValue="secondary-1"> <div class="flex gap-2 items-center"> <RadioGroupItem id="secondary-1" aria-label="Secondary Option 1" value="secondary-1" variant="secondary" /> <Label for="secondary-1">Secondary Option 1</Label> </div> <div class="flex gap-2 items-center"> <RadioGroupItem id="secondary-2" aria-label="Secondary Option 2" value="secondary-2" variant="secondary" /> <Label for="secondary-2">Secondary Option 2</Label> </div></RadioGroup>
<RadioGroup name="variant-info" legend="Info" defaultValue="info-1"> <div class="flex gap-2 items-center"> <RadioGroupItem id="info-1" aria-label="Info Option 1" value="info-1" variant="info" /> <Label for="info-1">Info Option 1</Label> </div> <div class="flex gap-2 items-center"> <RadioGroupItem id="info-2" aria-label="Info Option 2" value="info-2" variant="info" /> <Label for="info-2">Info Option 2</Label> </div></RadioGroup>
<RadioGroup name="variant-success" legend="Success" defaultValue="success-1"> <div class="flex gap-2 items-center"> <RadioGroupItem id="success-1" aria-label="Success Option 1" value="success-1" variant="success" /> <Label for="success-1">Success Option 1</Label> </div> <div class="flex gap-2 items-center"> <RadioGroupItem id="success-2" aria-label="Success Option 2" value="success-2" variant="success" /> <Label for="success-2">Success Option 2</Label> </div></RadioGroup>
<RadioGroup name="variant-warning" legend="Warning" defaultValue="warning-1"> <div class="flex gap-2 items-center"> <RadioGroupItem id="warning-1" aria-label="Warning Option 1" value="warning-1" variant="warning" /> <Label for="warning-1">Warning Option 1</Label> </div> <div class="flex gap-2 items-center"> <RadioGroupItem id="warning-2" aria-label="Warning Option 2" value="warning-2" variant="warning" /> <Label for="warning-2">Warning Option 2</Label> </div></RadioGroup>
<RadioGroup name="variant-error" legend="Error" defaultValue="error-1"> <div class="flex gap-2 items-center"> <RadioGroupItem id="error-1" aria-label="Error Option 1" value="error-1" variant="error" /> <Label for="error-1">Error Option 1</Label> </div> <div class="flex gap-2 items-center"> <RadioGroupItem id="error-2" aria-label="Error Option 2" value="error-2" variant="error" /> <Label for="error-2">Error Option 2</Label> </div></RadioGroup>import { RadioGroup, RadioGroupItem } from "@/components/starwind/radio-group";import { Label } from "@/components/starwind/label";
export function Example() { return ( <> <RadioGroup name="variant-radio" legend="Default" defaultValue="default-1"> <div className="flex gap-2 items-center"> <RadioGroupItem id="default-1" aria-label="Default Option 1" value="default-1" variant="default" /> <Label htmlFor="default-1">Default Option 1</Label> </div> <div className="flex gap-2 items-center"> <RadioGroupItem id="default-2" aria-label="Default Option 2" value="default-2" variant="default" /> <Label htmlFor="default-2">Default Option 2</Label> </div> </RadioGroup>
<RadioGroup name="variant-primary" legend="Primary" defaultValue="primary-1"> <div className="flex gap-2 items-center"> <RadioGroupItem id="primary-1" aria-label="Primary Option 1" value="primary-1" variant="primary" /> <Label htmlFor="primary-1">Primary Option 1</Label> </div> <div className="flex gap-2 items-center"> <RadioGroupItem id="primary-2" aria-label="Primary Option 2" value="primary-2" variant="primary" /> <Label htmlFor="primary-2">Primary Option 2</Label> </div> </RadioGroup>
<RadioGroup name="variant-secondary" legend="Secondary" defaultValue="secondary-1"> <div className="flex gap-2 items-center"> <RadioGroupItem id="secondary-1" aria-label="Secondary Option 1" value="secondary-1" variant="secondary" /> <Label htmlFor="secondary-1">Secondary Option 1</Label> </div> <div className="flex gap-2 items-center"> <RadioGroupItem id="secondary-2" aria-label="Secondary Option 2" value="secondary-2" variant="secondary" /> <Label htmlFor="secondary-2">Secondary Option 2</Label> </div> </RadioGroup>
<RadioGroup name="variant-info" legend="Info" defaultValue="info-1"> <div className="flex gap-2 items-center"> <RadioGroupItem id="info-1" aria-label="Info Option 1" value="info-1" variant="info" /> <Label htmlFor="info-1">Info Option 1</Label> </div> <div className="flex gap-2 items-center"> <RadioGroupItem id="info-2" aria-label="Info Option 2" value="info-2" variant="info" /> <Label htmlFor="info-2">Info Option 2</Label> </div> </RadioGroup>
<RadioGroup name="variant-success" legend="Success" defaultValue="success-1"> <div className="flex gap-2 items-center"> <RadioGroupItem id="success-1" aria-label="Success Option 1" value="success-1" variant="success" /> <Label htmlFor="success-1">Success Option 1</Label> </div> <div className="flex gap-2 items-center"> <RadioGroupItem id="success-2" aria-label="Success Option 2" value="success-2" variant="success" /> <Label htmlFor="success-2">Success Option 2</Label> </div> </RadioGroup>
<RadioGroup name="variant-warning" legend="Warning" defaultValue="warning-1"> <div className="flex gap-2 items-center"> <RadioGroupItem id="warning-1" aria-label="Warning Option 1" value="warning-1" variant="warning" /> <Label htmlFor="warning-1">Warning Option 1</Label> </div> <div className="flex gap-2 items-center"> <RadioGroupItem id="warning-2" aria-label="Warning Option 2" value="warning-2" variant="warning" /> <Label htmlFor="warning-2">Warning Option 2</Label> </div> </RadioGroup>
<RadioGroup name="variant-error" legend="Error" defaultValue="error-1"> <div className="flex gap-2 items-center"> <RadioGroupItem id="error-1" aria-label="Error Option 1" value="error-1" variant="error" /> <Label htmlFor="error-1">Error Option 1</Label> </div> <div className="flex gap-2 items-center"> <RadioGroupItem id="error-2" aria-label="Error Option 2" value="error-2" variant="error" /> <Label htmlFor="error-2">Error Option 2</Label> </div> </RadioGroup> </> );}Sizes
Set the radio indicator scale once on RadioGroup. RadioGroupItem no longer accepts size. Labels are separate components outside the Radio Group’s styled scope, so size each Label independently when you want its typography to match.
---import { RadioGroup, RadioGroupItem } from "@/components/starwind/radio-group";import { Label } from "@/components/starwind/label";---
<RadioGroup size="sm" name="size-sm" legend="Small" defaultValue="sm-1"> <div class="flex gap-2 items-center"> <RadioGroupItem id="sm-1" aria-label="Small Option 1" value="sm-1" /> <Label for="sm-1" size="sm">Small Option 1</Label> </div> <div class="flex gap-2 items-center"> <RadioGroupItem id="sm-2" aria-label="Small Option 2" value="sm-2" /> <Label for="sm-2" size="sm">Small Option 2</Label> </div></RadioGroup>
<RadioGroup size="md" name="size-md" legend="Medium" defaultValue="md-1"> <div class="flex gap-2 items-center"> <RadioGroupItem id="md-1" aria-label="Medium Option 1" value="md-1" /> <Label for="md-1" size="md">Medium Option 1</Label> </div> <div class="flex gap-2 items-center"> <RadioGroupItem id="md-2" aria-label="Medium Option 2" value="md-2" /> <Label for="md-2" size="md">Medium Option 2</Label> </div></RadioGroup>
<RadioGroup size="lg" name="size-lg" legend="Large" defaultValue="lg-1"> <div class="flex gap-2 items-center"> <RadioGroupItem id="lg-1" aria-label="Large Option 1" value="lg-1" /> <Label for="lg-1" size="lg">Large Option 1</Label> </div> <div class="flex gap-2 items-center"> <RadioGroupItem id="lg-2" aria-label="Large Option 2" value="lg-2" /> <Label for="lg-2" size="lg">Large Option 2</Label> </div></RadioGroup>import { RadioGroup, RadioGroupItem } from "@/components/starwind/radio-group";import { Label } from "@/components/starwind/label";
export function Example() { return ( <> <RadioGroup size="sm" name="size-sm" legend="Small" defaultValue="sm-1"> <div className="flex gap-2 items-center"> <RadioGroupItem id="sm-1" aria-label="Small Option 1" value="sm-1" /> <Label htmlFor="sm-1" size="sm">Small Option 1</Label> </div> <div className="flex gap-2 items-center"> <RadioGroupItem id="sm-2" aria-label="Small Option 2" value="sm-2" /> <Label htmlFor="sm-2" size="sm">Small Option 2</Label> </div> </RadioGroup>
<RadioGroup size="md" name="size-md" legend="Medium" defaultValue="md-1"> <div className="flex gap-2 items-center"> <RadioGroupItem id="md-1" aria-label="Medium Option 1" value="md-1" /> <Label htmlFor="md-1" size="md">Medium Option 1</Label> </div> <div className="flex gap-2 items-center"> <RadioGroupItem id="md-2" aria-label="Medium Option 2" value="md-2" /> <Label htmlFor="md-2" size="md">Medium Option 2</Label> </div> </RadioGroup>
<RadioGroup size="lg" name="size-lg" legend="Large" defaultValue="lg-1"> <div className="flex gap-2 items-center"> <RadioGroupItem id="lg-1" aria-label="Large Option 1" value="lg-1" /> <Label htmlFor="lg-1" size="lg">Large Option 1</Label> </div> <div className="flex gap-2 items-center"> <RadioGroupItem id="lg-2" aria-label="Large Option 2" value="lg-2" /> <Label htmlFor="lg-2" size="lg">Large Option 2</Label> </div> </RadioGroup> </> );}Orientation
Vertical (Default)
Horizontal
---import { RadioGroup, RadioGroupItem } from "@/components/starwind/radio-group";import { Label } from "@/components/starwind/label";---
<h3>Vertical (Default)</h3><RadioGroup name="orientation-vertical" legend="Vertical options" orientation="vertical" defaultValue="vertical-1"> <div class="space-y-2"> <div class="flex items-center gap-2"> <RadioGroupItem id="vertical-1" aria-label="Vertical option 1" value="vertical-1" /> <Label for="vertical-1">Vertical option 1</Label> </div> <div class="flex items-center gap-2"> <RadioGroupItem id="vertical-2" aria-label="Vertical option 2" value="vertical-2" /> <Label for="vertical-2">Vertical option 2</Label> </div> <div class="flex items-center gap-2"> <RadioGroupItem id="vertical-3" aria-label="Vertical option 3" value="vertical-3" /> <Label for="vertical-3">Vertical option 3</Label> </div> </div></RadioGroup>
<h3>Horizontal</h3><RadioGroup name="orientation-horizontal" legend="Horizontal options" orientation="horizontal" defaultValue="horizontal-1"> <div class="flex items-center gap-2"> <RadioGroupItem id="horizontal-1" aria-label="Horizontal option 1" value="horizontal-1" /> <Label for="horizontal-1">Horizontal option 1</Label> </div> <div class="flex items-center gap-2"> <RadioGroupItem id="horizontal-2" aria-label="Horizontal option 2" value="horizontal-2" /> <Label for="horizontal-2">Horizontal option 2</Label> </div> <div class="flex items-center gap-2"> <RadioGroupItem id="horizontal-3" aria-label="Horizontal option 3" value="horizontal-3" /> <Label for="horizontal-3">Horizontal option 3</Label> </div></RadioGroup>import { RadioGroup, RadioGroupItem } from "@/components/starwind/radio-group";import { Label } from "@/components/starwind/label";
export function Example() { return ( <> <h3>Vertical (Default)</h3> <RadioGroup name="orientation-vertical" legend="Vertical options" orientation="vertical" defaultValue="vertical-1"> <div className="space-y-2"> <div className="flex items-center gap-2"> <RadioGroupItem id="vertical-1" aria-label="Vertical option 1" value="vertical-1" /> <Label htmlFor="vertical-1">Vertical option 1</Label> </div> <div className="flex items-center gap-2"> <RadioGroupItem id="vertical-2" aria-label="Vertical option 2" value="vertical-2" /> <Label htmlFor="vertical-2">Vertical option 2</Label> </div> <div className="flex items-center gap-2"> <RadioGroupItem id="vertical-3" aria-label="Vertical option 3" value="vertical-3" /> <Label htmlFor="vertical-3">Vertical option 3</Label> </div> </div> </RadioGroup>
<h3>Horizontal</h3> <RadioGroup name="orientation-horizontal" legend="Horizontal options" orientation="horizontal" defaultValue="horizontal-1"> <div className="flex items-center gap-2"> <RadioGroupItem id="horizontal-1" aria-label="Horizontal option 1" value="horizontal-1" /> <Label htmlFor="horizontal-1">Horizontal option 1</Label> </div> <div className="flex items-center gap-2"> <RadioGroupItem id="horizontal-2" aria-label="Horizontal option 2" value="horizontal-2" /> <Label htmlFor="horizontal-2">Horizontal option 2</Label> </div> <div className="flex items-center gap-2"> <RadioGroupItem id="horizontal-3" aria-label="Horizontal option 3" value="horizontal-3" /> <Label htmlFor="horizontal-3">Horizontal option 3</Label> </div> </RadioGroup> </> );}Accessibility adjustment
Give each Runtime radio an explicit accessible name. The styled radio uses a focusable role="radio" element while its hidden input handles native form participation.
Event Handling
The RadioGroup component emits a starwind:value-change event when a radio option is selected. This can be listened to in order to update your UI based on the event.detail.value property.
Radio Group Event Test
---import { RadioGroup, RadioGroupItem } from "@/components/starwind/radio-group";import { Label } from "@/components/starwind/label";---
<div class="space-y-4"> <h3 class="text-lg font-medium">Radio Group Event Test</h3>
<RadioGroup id="event-test" name="event-test" legend="Choose an option"> <div class="flex gap-2"> <RadioGroupItem id="event-1" aria-label="Option One" value="one" /> <Label for="event-1">Option One</Label> </div> <div class="flex gap-2"> <RadioGroupItem id="event-2" aria-label="Option Two" value="two" /> <Label for="event-2">Option Two</Label> </div> <div class="flex gap-2"> <RadioGroupItem id="event-3" aria-label="Option Three" value="three" /> <Label for="event-3">Option Three</Label> </div> </RadioGroup>
<div id="event-output" class="text-muted-foreground text-sm"> Selected value: <span class="text-foreground font-medium">none</span> </div></div>
<script> const root = document.querySelector<HTMLElement>("#event-test"); const output = document.querySelector<HTMLElement>("#event-output span");
root?.addEventListener("starwind:value-change", (event) => { const { value } = (event as CustomEvent<{ value: string }>).detail; if (output) output.textContent = value; });</script>import { useState } from "react";import { Label } from "@/components/starwind/label";import { RadioGroup, RadioGroupItem } from "@/components/starwind/radio-group";
export function Example() { const [value, setValue] = useState<string | null>(null);
return ( <div className="space-y-4"> <h3 className="text-lg font-medium">Radio Group Event Test</h3> <RadioGroup name="event-test" legend="Choose an option" onValueChange={(nextValue) => setValue(nextValue)} > {["one", "two", "three"].map((option) => ( <div key={option} className="flex gap-2"> <RadioGroupItem id={"event-" + option} aria-label={"Option " + option} value={option} /> <Label htmlFor={"event-" + option}>Option {option}</Label> </div> ))} </RadioGroup> <div className="text-muted-foreground text-sm"> Selected value: <span className="text-foreground font-medium">{value ?? "none"}</span> </div> </div> );}Size Migration
| Before | After |
|---|---|
<RadioGroup><RadioGroupItem size="sm" /></RadioGroup> | <RadioGroup size="sm"><RadioGroupItem /></RadioGroup> |
External Label components remain independently sizeable.
API Reference
Styled Component API
These props are added or materially changed by the installed styled component. Standard HTML attributes remain available through the inherited interfaces noted below. Expand a prop to see named type definitions and framework-specific imports. Follow the Primitive and Runtime links for lower-level behavior props.
Radio Group
Inherits div attributes. Omits `defaultValue` and `onChange`.
Contains the following additional props:
defaultValue string —
- Description
- Sets the initial value when the component is uncontrolled.
- Classification
- Primitive override
- Primitive prop
- radio-group.Root.defaultValue
legend string —
- Description
- Provides accessible text for the grouped choices.
- Classification
- Wrapper prop
orientation "vertical" | "horizontal" "vertical"
- Description
- Selects the horizontal or vertical layout direction.
- Classification
- Styled variant
- Primitive prop
- radio-group.Root.orientation
size "sm" | "md" | "lg" "md"
- Description
- Selects the component's visual size.
- Classification
- Wrapper prop
value string —
- Description
- Controls or identifies the component value.
- Classification
- Primitive override
- Type imports
- React
import type { RadioGroupValue } from "@starwind-ui/react"; - Primitive prop
- radio-group.Root.value
Radio Group Item
Inherits span attributes. Omits `defaultChecked` and `onChange`.
Contains the following additional props:
defaultChecked boolean —
- Description
- Sets the initial checked state when the choice is uncontrolled.
- Classification
- Primitive override
- Primitive prop
- radio.Root.defaultChecked
variant "default" | "primary" | "secondary" | "info" | "success" | "warning" | "error" "default"
- Description
- Selects the component's visual variant.
- Classification
- Styled variant
Primitive And Runtime API
Use these references when you need the lower-level behavior APIs behind Radio Group.
Primitive API
Runtime API
- Radio primitive
createRadiofrom@starwind-ui/runtime/radio- Radio Group primitive
createRadioGroupfrom@starwind-ui/runtime/radio-group
Changelog
View version history v3.0.2 12 releases
v3.0.2
- Radio Group items now use the neutral
defaultvariant whenvariantis omitted.
v3.0.1
- Named the generated aggregate default export so React and Astro tooling can identify the installed component cleanly.
v3.0.0
- Moved radio indicator sizing from
RadioGroupItemtoRadioGroup, withmdas the default. - Migration:
<RadioGroupItem size="sm" />becomes<RadioGroup size="sm"><RadioGroupItem /></RadioGroup>. Keepsizeon externalLabelcomponents when desired.
v2.0.0
- Rebuilt Radio Group on Starwind Runtime for radio ownership, form participation, keyboard navigation, and value details.
- See the Radio Primitive and Radio Group Primitive for the underlying unstyled anatomy and behavior API.
v1.2.6
- Refactor tailwind variants functions into separate
variants.tsfile
v1.2.4
- Add
starwind:initevent listener to enable initialization of additional Radio Groups loaded after an initial page load, such as when using server islands
v1.2.3
- add
aria-invalidstyling
v1.2.2
- Removed debug logging statements
v1.2.1
- Add named slot “icon” to
RadioGroupItemto enable easy icon swapping
v1.2.0
- style and focus state updates
v1.1.0
- Add
data-slotattribute to enable global styling updates
v1.0.0
- Initial release with starwind v1.7.0