Radio Group

Allows users to select a single option from a list of mutually exclusive choices.

	<script lang="ts">
  import { Label, RadioGroup } from "bits-ui";
</script>
 
<RadioGroup.Root class="flex flex-col gap-4 text-sm font-medium">
  <div
    class="group flex select-none items-center text-foreground transition-all"
  >
    <RadioGroup.Item
      id="amazing"
      value="amazing"
      class="size-5 shrink-0 cursor-default rounded-full border border-border-input bg-background transition-all duration-100 ease-in-out hover:border-dark-40 data-[state=checked]:border-6 data-[state=checked]:border-foreground"
    />
    <Label.Root for="amazing" class="pl-3">Amazing</Label.Root>
  </div>
  <div
    class="group flex select-none items-center text-foreground transition-all"
  >
    <RadioGroup.Item
      id="average"
      value="average"
      class="size-5 shrink-0 cursor-default rounded-full border border-border-input bg-background transition-all duration-100 ease-in-out hover:border-dark-40 data-[state=checked]:border-6 data-[state=checked]:border-foreground"
    />
    <Label.Root for="average" class="pl-3">Average</Label.Root>
  </div>
  <div
    class="group flex select-none items-center text-foreground transition-all"
  >
    <RadioGroup.Item
      id="terrible"
      value="terrible"
      class="size-5 shrink-0 cursor-default rounded-full border border-border-input bg-background transition-all duration-100 ease-in-out hover:border-dark-40 data-[state=checked]:border-6 data-[state=checked]:border-foreground"
    />
    <Label.Root for="terrible" class="pl-3">Terrible</Label.Root>
  </div>
</RadioGroup.Root>

Structure

	<script lang="ts">
	import { RadioGroup } from "bits-ui";
</script>
 
<RadioGroup.Root>
	<RadioGroup.Item>
		{#snippet children({ checked })}
			{#if checked}

			{/if}
		{/snippet}
	</RadioGroup.Item>
</RadioGroup.Root>

Reusable Components

It's recommended to use the RadioGroup primitives to create your own custom components that can be used throughout your application.

In the example below, we're creating a custom MyRadioGroup component that takes in an array of items and renders a radio group with those items along with a Label component for each item.

MyRadioGroup.svelte
	<script lang="ts">
	import { RadioGroup, Label, type WithoutChildrenOrChild, useId } from "bits-ui";
 
	type Item = {
		value: string;
		label: string;
		disabled?: boolean;
	};
 
	type Props = WithoutChildrenOrChild<RadioGroup.RootProps> & {
		items: Item[];
	};
 
	let { value = $bindable(""), ref = $bindable(null), items, ...restProps }: Props = $props();
</script>
 
<RadioGroup.Root bind:value bind:ref {...restProps}>
	{#each items as item}
		{@const id = useId()}
		<div>
			<RadioGroup.Item {id} value={item.value} disabled={item.disabled}>
				{#snippet children({ checked })}
					{#if checked}

					{/if}
				{/snippet}
			</RadioGroup.Item>
			<Label.Root for={id}>{item.label}</Label.Root>
		</div>
	{/each}
</RadioGroup.Root>

You can then use the MyRadioGroup component in your application like so:

+page.svelte
	<script lang="ts">
	import MyRadioGroup from "$lib/components/MyRadioGroup.svelte";
 
	const myItems = [
		{ value: "apple", label: "Apple" },
		{ value: "banana", label: "Banana" },
		{ value: "coconut", label: "Coconut", disabled: true },
	];
</script>
 
<MyRadioGroup items={myItems} name="favoriteFruit" />

Managing Value State

The value prop is used to determine which radio group item(s) are currently checked. Bits UI provides flexible options for controlling and synchronizing the Radio Group's value.

Two-Way Binding

Use the bind:value directive for effortless two-way synchronization between your local state and the Radio Group's internal state.

	<script lang="ts">
	import { RadioGroup } from "bits-ui";
	let myValue = $state<string>("");
</script>
 
<button onclick={() => (myValue = "apple")}> Apple </button>
 
<RadioGroup.Root bind:value={myValue}>
	<!-- ... -->
</RadioGroup.Root>

This setup enables toggling the Radio Group's value to "apple" via the custom button and ensures the local myValue state updates when the Radio Group changes through any internal means (e.g., clicking on an item's button).

Change Handler

You can also use the onValueChange prop to update local state when the Radio Group's value state changes. This is useful when you don't want two-way binding for one reason or another, or you want to perform additional logic when the Radio Group changes.

	<script lang="ts">
	import { RadioGroup } from "bits-ui";
	let myValue = $state<string>("");
</script>
 
<RadioGroup.Root
	value={myValue}
	onValueChange={(value) => {
		myValue = value;
		// additional logic here.
	}}
>
	<!-- ... -->
</RadioGroup.Root>

With HTML Forms

If you set the name prop on the RadioGroup.Root component, a hidden input element will be rendered to submit the value of the radio group to a form.

	<RadioGroup.Root name="favoriteFruit">
	<!-- ... -->
</RadioGroup.Root>

Disabling Items

You can disable a radio group item by setting the disabled prop to true.

	<RadioGroup.Item value="apple" disabled>Apple</RadioGroup.Item>

API Reference

RadioGroup.Root

The radio group component used to group radio items under a common name for form submission.

Property Type Description
value bindable prop
string

The value of the currently selected radio item. You can bind to this value to control the radio group's value from outside the component.

Default: undefined
onValueChange
function

A callback that is fired when the radio group's value changes.

Default: undefined
disabled
boolean

Whether or not the radio group is disabled. This prevents the user from interacting with it.

Default: false
required
boolean

Whether or not the radio group is required.

Default: false
name
string

The name of the radio group used in form submission. If provided, a hidden input element will be rendered to submit the value of the radio group.

Default: undefined
loop
boolean

Whether or not the radio group should loop through the items when navigating with the arrow keys.

Default: false
orientation
enum

The orientation of the radio group. This will determine how keyboard navigation will work within the component.

Default: 'vertical'
ref bindable prop
HTMLDivElement

The underlying DOM element being rendered. You can bind to this to get a reference to the element.

Default: undefined
children
Snippet

The children content to render.

Default: undefined
child
Snippet

Use render delegation to render your own element. See delegation docs for more information.

Default: undefined
Data Attribute Value Description
data-orientation
enum

The orientation of the radio group.

data-radio-group-root
''

Present on the root element.

RadioGroup.Item

An radio item, which must be a child of the RadioGroup.Root component.

Property Type Description
value required prop
string

The value of the radio item. This should be unique for each radio item in the group.

Default: undefined
disabled
boolean

Whether or not the radio item is disabled. This prevents the user from interacting with it.

Default: false
ref bindable prop
HTMLButtonElement

The underlying DOM element being rendered. You can bind to this to get a reference to the element.

Default: undefined
children
Snippet

The children content to render.

Default: undefined
child
Snippet

Use render delegation to render your own element. See delegation docs for more information.

Default: undefined
Data Attribute Value Description
data-disabled
''

Present when the radio item is disabled.

data-value
''

The value of the radio item.

data-state
enum

The radio item's checked state.

data-orientation
enum

The orientation of the parent radio group.

data-radio-group-item
''

Present on the radio item element.