Skip to content

Radio Group

A radio group, HeroUI's on Kobalte's.

Solidtype_heroui.Radio_group is Kobalte’s radio group in HeroUI’s anatomy: the group, each Radio, Radio.Content, the clickable label that holds Kobalte’s input, Radio.Control and Radio.Indicator. A Label in the group names it and a Description describes it; a Description in a radio describes that radio’s input. Its state is declared as React Aria writes it: Space chooses a radio and the arrow keys move the choice, and Enter presses a radio’s content as React Aria’s does, though it chooses nothing.

Plan selection
Choose the plan that suits you best
Includes 100 messages per month
Includes 200 messages per month
Unlimited messages
radio_group_usage.mlx
module Radio_group = Solidtype_heroui.Radio_group
module Radio = Solidtype_heroui.Radio
module Label = Solidtype_heroui.Label
module Description = Solidtype_heroui.Description
let make () =
<Radio_group default_value="premium">
<Label>"Plan selection"</Label>
<Description>"Choose the plan that suits you best"</Description>
<Radio value="basic">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Basic Plan"
</Radio.Content>
<Description>"Includes 100 messages per month"</Description>
</Radio>
<Radio value="premium">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Premium Plan"
</Radio.Content>
<Description>"Includes 200 messages per month"</Description>
</Radio>
<Radio value="business">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Business Plan"
</Radio.Content>
<Description>"Unlimited messages"</Description>
</Radio>
</Radio_group>
For side projects
Advanced reporting
Up to 10 teammates
radio_group_horizontal.mlx
module Radio_group = Solidtype_heroui.Radio_group
module Radio = Solidtype_heroui.Radio
module Label = Solidtype_heroui.Label
module Description = Solidtype_heroui.Description
let make () =
<div class_="flex flex-col gap-4">
<Label>"Subscription plan"</Label>
<Radio_group default_value="pro" orientation=`horizontal>
<Radio value="starter">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Starter"
</Radio.Content>
<Description>"For side projects"</Description>
</Radio>
<Radio value="pro">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Pro"
</Radio.Content>
<Description>"Advanced reporting"</Description>
</Radio>
<Radio value="teams">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Teams"
</Radio.Content>
<Description>"Up to 10 teammates"</Description>
</Radio>
</Radio_group>
</div>

Primary variant

Standard styling with default background
Another option with primary styling

Secondary variant

Lower emphasis variant for use in surfaces
Another option with secondary styling
radio_group_variants.mlx
module Radio_group = Solidtype_heroui.Radio_group
module Radio = Solidtype_heroui.Radio
module Label = Solidtype_heroui.Label
module Description = Solidtype_heroui.Description
let make () =
<div class_="flex flex-col gap-8">
<div class_="flex flex-col gap-2">
<p class_="text-sm font-medium text-muted">"Primary variant"</p>
<Radio_group default_value="option1" variant=`primary>
<Radio value="option1">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Option 1"
</Radio.Content>
<Description>"Standard styling with default background"</Description>
</Radio>
<Radio value="option2">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Option 2"
</Radio.Content>
<Description>"Another option with primary styling"</Description>
</Radio>
</Radio_group>
</div>
<div class_="flex flex-col gap-2">
<p class_="text-sm font-medium text-muted">"Secondary variant"</p>
<Radio_group default_value="option1" variant=`secondary>
<Radio value="option1">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Option 1"
</Radio.Content>
<Description>
"Lower emphasis variant for use in surfaces"
</Description>
</Radio>
<Radio value="option2">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Option 2"
</Radio.Content>
<Description>"Another option with secondary styling"</Description>
</Radio>
</Radio_group>
</div>
</div>
Subscription plan
Plan changes are temporarily paused while we roll out updates.
For side projects and small teams
Advanced reporting and analytics
Share access with up to 10 teammates
radio_group_disabled.mlx
module Radio_group = Solidtype_heroui.Radio_group
module Radio = Solidtype_heroui.Radio
module Label = Solidtype_heroui.Label
module Description = Solidtype_heroui.Description
let make () =
<Radio_group is_disabled=true default_value="pro">
<Label>"Subscription plan"</Label>
<Description>
"Plan changes are temporarily paused while we roll out updates."
</Description>
<Radio value="starter">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Starter"
</Radio.Content>
<Description>"For side projects and small teams"</Description>
</Radio>
<Radio value="pro">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Pro"
</Radio.Content>
<Description>"Advanced reporting and analytics"</Description>
</Radio>
<Radio value="teams">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Teams"
</Radio.Content>
<Description>"Share access with up to 10 teammates"</Description>
</Radio>
</Radio_group>
Subscription plan
For side projects and small teams
Advanced reporting and analytics
Share access with up to 10 teammates

Selected plan: pro

radio_group_controlled.mlx
module S = Solidtype.Solid
module Jsx = Solidtype.Jsx
module Radio_group = Solidtype_heroui.Radio_group
module Radio = Solidtype_heroui.Radio
module Label = Solidtype_heroui.Label
module Description = Solidtype_heroui.Description
let make () =
let value, set_value = S.create_signal "pro" in
<div class_="flex flex-col gap-4">
<Radio_group value=(fun () -> S.get value) on_change=(S.set set_value)>
<Label>"Subscription plan"</Label>
<Radio value="starter">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Starter"
</Radio.Content>
<Description>"For side projects and small teams"</Description>
</Radio>
<Radio value="pro">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Pro"
</Radio.Content>
<Description>"Advanced reporting and analytics"</Description>
</Radio>
<Radio value="teams">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Teams"
</Radio.Content>
<Description>"Share access with up to 10 teammates"</Description>
</Radio>
</Radio_group>
<p class_="text-sm text-muted">
"Selected plan: "
<span class_="font-medium">(fun () -> Jsx.string (S.get value))</span>
</p>
</div>
Subscription plan
For side projects and small teams
Advanced reporting and analytics
Share access with up to 10 teammates

Last chosen plan: pro

radio_group_uncontrolled.mlx
module S = Solidtype.Solid
module Jsx = Solidtype.Jsx
module Radio_group = Solidtype_heroui.Radio_group
module Radio = Solidtype_heroui.Radio
module Label = Solidtype_heroui.Label
module Description = Solidtype_heroui.Description
let make () =
let selection, set_selection = S.create_signal "pro" in
<div class_="flex flex-col gap-4">
<Radio_group default_value="pro" on_change=(S.set set_selection)>
<Label>"Subscription plan"</Label>
<Radio value="starter">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Starter"
</Radio.Content>
<Description>"For side projects and small teams"</Description>
</Radio>
<Radio value="pro">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Pro"
</Radio.Content>
<Description>"Advanced reporting and analytics"</Description>
</Radio>
<Radio value="teams">
<Radio.Content>
<Radio.Control><Radio.Indicator /></Radio.Control> "Teams"
</Radio.Content>
<Description>"Share access with up to 10 teammates"</Description>
</Radio>
</Radio_group>
<p class_="text-sm text-muted">
"Last chosen plan: "
<span class_="font-medium">(fun () -> Jsx.string (S.get selection))</span>
</p>
</div>

HeroUI’s In Surface, until Surface is ported; Validation and Delivery & Payment, which need a form and FieldError; Custom Indicator, whose indicator is a render prop; and Render Function, which needs render.

Each part’s class_ is added after HeroUI’s classes, and HeroUI’s state attributes are Tailwind’s data-[...] variants, as in React.

Billing cycle
Choose how often you are charged.
radio_group_tailwind.mlx
module Radio_group = Solidtype_heroui.Radio_group
module Radio = Solidtype_heroui.Radio
module Label = Solidtype_heroui.Label
module Description = Solidtype_heroui.Description
module For = Solidtype.For
let options =
[|
("monthly", "Monthly", "$12 billed every month");
("yearly", "Yearly", "$120 billed once a year");
|]
let content =
"group flex w-full items-start gap-3 rounded-xl border border-success/10 \
bg-success-soft/30 px-4 py-3 transition-colors \
data-[focus-visible=true]:ring-2 data-[focus-visible=true]:ring-success/15 \
data-[hovered=true]:bg-success-soft-hover \
data-[selected=true]:border-success/30 data-[selected=true]:bg-success-soft \
data-[selected=true]:data-[hovered=true]:bg-success-soft-hover"
let control =
"mt-0.5 size-5 shrink-0 rounded-full border border-border bg-default \
shadow-none group-data-[pressed=true]:scale-95 \
group-data-[selected=true]:border-transparent \
group-data-[selected=true]:bg-success \
group-data-[selected=true]:group-data-[pressed=true]:bg-success-hover"
let indicator =
"before:rounded-full before:bg-default \
group-data-[selected=true]:before:scale-50 \
group-data-[selected=true]:before:bg-success-foreground \
group-data-[selected=true]:group-data-[pressed=true]:before:scale-[0.57]"
let make () =
<Radio_group
class_="w-full max-w-sm gap-3 **:data-[slot=radio]:mt-0"
default_value="yearly"
variant=`secondary>
<Label class_="font-medium text-foreground">"Billing cycle"</Label>
<Description>"Choose how often you are charged."</Description>
<For each=(fun () -> options)>
(fun (value, label, about) _ ->
<Radio value=(fun () -> value)>
<Radio.Content class_=(fun () -> content)>
<Radio.Control class_=(fun () -> control)>
<Radio.Indicator class_=(fun () -> indicator) />
</Radio.Control>
<div class_="flex flex-col gap-0.5">
<span
class_="font-medium text-foreground \
group-data-[selected=true]:text-success-soft-foreground">
(fun () -> Solidtype.Jsx.string label)
</span>
<Description
class_="group-data-[selected=true]:text-success-soft-foreground/80">
(fun () -> Solidtype.Jsx.string about)
</Description>
</div>
</Radio.Content>
</Radio>)
</For>
</Radio_group>

HeroUI’s classes are global, so a stylesheet restyles every one, as with HeroUI in React:

@layer components {
.radio-group {
@apply gap-2;
}
.radio__control {
@apply border-2 border-accent;
}
}
  • .radio-group, with .radio-group--primary and .radio-group--secondary
  • .radio, .radio__content, .radio__control, .radio__indicator

A disabled radio is styled by [data-disabled="true"] on .radio: there is no .radio--disabled.

  • Selected: [data-selected="true"] or [aria-checked="true"]
  • Hover: :hover or [data-hovered="true"]
  • Focus: :focus-visible or [data-focus-visible="true"]
  • Pressed: :active or [data-pressed="true"]
  • Disabled: :disabled or [data-disabled="true"]
  • Invalid: [data-invalid="true"] or [aria-invalid="true"]

Each prop beside the name HeroUI’s React component gives it. A tag is the string React takes.

React solidtype Type Default Description
value value string The value chosen, controlled
defaultValue default_value string none The value chosen at first
onChange on_change string -> unit Called as the choice changes
orientation orientation [ `horizontal | `vertical ] `vertical Its direction
variant variant [ `primary | `secondary ] `primary Visual style
isDisabled is_disabled bool false Whether every radio is disabled
isInvalid is_invalid bool false Whether it is invalid
className class_ string Added after HeroUI’s classes
onBlur on_blur Dom.focusEvent -> unit Called once focus leaves it for an element outside it
children children elements Its label, description and radios
isReadOnly is_read_only bool false Whether it keeps its choice
isRequired is_required bool false Whether a form requires it
name name string Its name in a form
render props — Not yet
React solidtype Type Default Description
value value string required The value it chooses
isDisabled is_disabled bool false Whether it is disabled
aria-label aria_label string Its name where no text names it
className class_ string Added after HeroUI’s classes
children children elements Its content and description
render props — Not yet

Radio.Content, Radio.Control and Radio.Indicator

Section titled “Radio.Content, Radio.Control and Radio.Indicator”
React solidtype Type Description
className class_ string Added after HeroUI’s class
children children elements What it holds; optional on the indicator

Original HeroUI documentation: Radio Group.

The same HeroUI RadioGroup twice, under the same props: in solidtype on the left, in React on the right. Below them, every attribute of the two first contents: a marked row is one they disagree on, and a dimmed row is a framework’s own, which no style reads. A description is Kobalte’s <div> where React Aria’s is a <span>; each is the one its input is described by.

solidtype — OCaml, on Solid and Kobalte
Plan
For side projects
Advanced reporting
React — TypeScript, on React Aria
attributesolidtypeReact