Radio Group
Basic example
Radio Groups are built using a combination of the RadioGroup
, RadioGroupOption
, RadioGroupLabel
, and RadioGroupDescription
components:
<script>
import {
RadioGroup,
RadioGroupLabel,
RadioGroupOption,
RadioGroupDescription,
} from "@rgossiaux/svelte-headlessui";
let plan = "startup";
</script>
<RadioGroup value={plan} on:change={(e) => (plan = e.detail)}>
<RadioGroupLabel>Plan</RadioGroupLabel>
<RadioGroupOption value="startup" let:checked>
<span class:checked>Startup</span>
</RadioGroupOption>
<RadioGroupOption value="business" let:checked>
<span class:checked>Business</span>
</RadioGroupOption>
<RadioGroupOption value="enterprise" let:checked>
<span class:checked>Enterprise</span>
</RadioGroupOption>
</RadioGroup>
<style>
.checked {
/* Your styles here */
}
</style>
Styling
See here for some general notes on styling the components in this library.
Checked option
To style the selected RadioGroupOption
, you can use the checked
slot prop that it provides, which tells you whether or not that option is the currently selected one. You can use this state to conditionally apply whatever styles you wish.
<script>
import {
RadioGroup,
RadioGroupLabel,
RadioGroupOption,
} from "@rgossiaux/svelte-headlessui";
let plan = "startup";
</script>
<RadioGroup value={plan} on:change={(e) => (plan = e.detail)}>
<RadioGroupLabel>Plan</RadioGroupLabel>
<!-- Use the `checked` slot prop to conditionally style the checked item -->
<RadioGroupOption value="startup" let:checked>
<span class:checked>Startup</span>
</RadioGroupOption>
<!-- ... -->
</RadioGroup>
<style>
.checked {
/* Your styles here */
}
</style>
Active options
RadioGroupOption
s can also be in an active
state if they are focused with either the mouse or the keyboard. Itβs a good idea to add styles specifically for this state.
<script>
import {
RadioGroup,
RadioGroupLabel,
RadioGroupOption,
} from "@rgossiaux/svelte-headlessui";
let plan = "startup";
</script>
<RadioGroup value={plan} on:change={(e) => (plan = e.detail)}>
<RadioGroupLabel>Plan</RadioGroupLabel>
<!-- Use both `active` and `checked` slot props
to differentiate between the active and checked states -->
<RadioGroupOption value="startup" let:active let:checked>
<span class:active class:checked>Startup</span>
</RadioGroupOption>
<!-- ... -->
</RadioGroup>
<style>
.active {
/* Your styles here */
}
.checked {
/* Your styles here */
}
</style>
Using the Label and Description components
You can use the RadioGroupLabel
and RadioGroupDescription
components to label and describe each RadioGroupOption
, as well as the RadioGroup
itself. These components will automatically link with their relevant ancestor components via the aria-labelledby
and aria-describedby
attributes, improving the semantics and accessibility of your component.
By default, RadioGroupLabel
renders a <label>
element and RadioGroupDescription
renders a <p>
. These can be customized using the as
prop, as described in the API docs below.
<script>
import {
RadioGroup,
RadioGroupLabel,
RadioGroupOption,
RadioGroupDescription,
} from "@rgossiaux/svelte-headlessui";
let plan = "startup";
</script>
<RadioGroup value={plan} on:change={(e) => plan = e.detail}>
<!-- This Label is for the `RadioGroup` -->
<RadioGroupLabel>Plan</RadioGroupLabel>
<RadioGroupOption value="startup" let:checked>
<RadioGroupLabel as="span" class:checked>Startup</span>
<RadioGroupDescription as="span" class:checked>
Up to 5 active job postings
</RadioGroupDescription>
</RadioGroupOption>
<!-- ... -->
</RadioGroup>
<style>
/* WARNING: This is just for demonstration.
Using :global() in this way can be risky. */
:global(.checked) {
/* Your styles here */
}
</style>
Using with HTML forms
If you add the name
prop to your listbox, hidden input
elements will be rendered and kept in sync with your selected value.
<script>
import {
RadioGroup,
RadioGroupLabel,
RadioGroupOption,
RadioGroupDescription,
} from "@rgossiaux/svelte-headlessui";
const plans = ['startup', 'business', 'enterprise']
let selectedPlan = plans[0];
</script>
<RadioGroup value={selectedPlan} on:change={(e) => (selectedPlan = e.detail)} name="plan">
<RadioGroupLabel>Plan</RadioGroupLabel>
{#each plans as plan}
<RadioGroupOption value={plan} let:checked>
<span>{plan}</span>
</RadioGroupOption>
{/each}
</RadioGroup>
This lets you use a radio group inside a native HTML <form>
and make traditional form submissions as if your radio group was a native HTML form control.
Basic values like strings will be rendered as a single hidden input containing that value, but complex values like objects will be encoded into multiple inputs using a square bracket notation for the names.
<input type="hidden" name="plan" value="startup" />
Accessibility notes
Mouse interaction
Clicking a RadioGroupOption
will select it.
Keyboard interaction
Command | Description |
---|---|
<ArrowDown> / <ArrowRight> when RadioGroup is focused |
Focuses and checks the next RadioGroupOption |
<ArrowUp> / <ArrowLeft> when RadioGroup is focused |
Focuses and checks the previous RadioGroupOption |
<Space> when RadioGroup is focused |
Checks the current RadioGroupOption if it is not already checked |
Other
All relevant ARIA attributes are automatically managed.
For a full reference on all accessibility features implemented in RadioGroup
, see the ARIA spec on Radio Groups.
Component API
RadioGroup
The main Radio Group component.
Prop | Default | Type | Description |
---|---|---|---|
as |
div |
string |
The element the RadioGroup should render as |
disabled |
false |
boolean |
Whether the RadioGroup and all of its RadioGroupOption s are disabled |
value |
β | T | undefined |
The currently selected value in the RadioGroup |
name |
β | string |
The name used when using this component inside a form. |
This component also dispatches a custom event, which is listened to using the Svelte on:
directive:
Event name | Type of event .detail |
Description |
---|---|---|
change |
T |
Dispatched when a RadioGroupOption is selected; the event detail contains the value of the selected option |
RadioGroupOption
The wrapper component for each selectable option.
Prop | Default | Type | Description |
---|---|---|---|
as |
div |
string |
The element the RadioGroupOption should render as |
disabled |
false |
boolean |
Whether the RadioGroupOption is disabled |
value |
β | T | undefined |
The value of the RadioGroupOption ; the type should match the type of the value prop in the RadioGroup |
Slot prop | Type | Description |
---|---|---|
active |
boolean |
Whether the option is active (using the mouse or keyboard) |
checked |
boolean |
Whether the option is the checked option |
disabled |
boolean |
Whether the option is disabled |
RadioGroupLabel
Renders an element that is linked to its nearest RadioGroup
or RadioGroupOption
ancestor component via the aria-labelledby
attribute and an autogenerated id.
Prop | Default | Type | Description |
---|---|---|---|
as |
label |
string |
The element the RadioGroupLabel should render as |
If the RadioGroupLabel
is labeling a RadioGroupOption
(instead of the RadioGroup
), it will also have these slot props available:
Slot prop | Type | Description |
---|---|---|
active |
boolean |
Whether the corresponding option is active (using the mouse or keyboard) |
checked |
boolean |
Whether the corresponding option is the checked option |
disabled |
boolean |
Whether the corresponding option is disabled |
RadioGroupDescription
Renders an element that is linked to its nearest RadioGroup
or RadioGroupOption
ancestor component via the aria-describedby
attribute and an autogenerated id.
Prop | Default | Type | Description |
---|---|---|---|
as |
a |
string |
The element the RadioGroupDescription should render as |
If the RadioGroupDescription
is describing a RadioGroupOption
(instead of the RadioGroup
), it will also have these slot props available:
Slot prop | Type | Description |
---|---|---|
active |
boolean |
Whether the corresponding option is active (using the mouse or keyboard) |
checked |
boolean |
Whether the corresponding option is the checked option |
disabled |
boolean |
Whether the corresponding option is disabled |