Skip to content

Checkbox

A checkbox, HeroUI's on Kobalte's.

Solidtype_heroui.Checkbox is Kobalte’s checkbox in HeroUI’s anatomy: the field, Checkbox.Content, the clickable label that holds Kobalte’s input, Checkbox.Control, Checkbox.Indicator with HeroUI’s own check and dash, and HeroUI’s Label. Its state is declared as React Aria writes it.

HeroUI’s examples.

checkbox_usage.mlx
module Checkbox = Solidtype_heroui.Checkbox
let make () =
<Checkbox name="basic-terms">
<Checkbox.Content>
<Checkbox.Control><Checkbox.Indicator /></Checkbox.Control>
"Accept terms and conditions"
</Checkbox.Content>
</Checkbox>

Primary variant

Standard styling with default background

Secondary variant

Lower emphasis variant for use in surfaces
checkbox_variants.mlx
module Checkbox = Solidtype_heroui.Checkbox
module Description = Solidtype_heroui.Description
let make () =
<div class_="flex flex-col gap-4">
<div class_="flex flex-col gap-2">
<p class_="text-sm font-medium text-muted">"Primary variant"</p>
<Checkbox name="primary" variant=`primary>
<Checkbox.Content>
<Checkbox.Control><Checkbox.Indicator /></Checkbox.Control>
"Primary checkbox"
</Checkbox.Content>
<Description>"Standard styling with default background"</Description>
</Checkbox>
</div>
<div class_="flex flex-col gap-2">
<p class_="text-sm font-medium text-muted">"Secondary variant"</p>
<Checkbox name="secondary" variant=`secondary>
<Checkbox.Content>
<Checkbox.Control><Checkbox.Indicator /></Checkbox.Control>
"Secondary checkbox"
</Checkbox.Content>
<Description>"Lower emphasis variant for use in surfaces"</Description>
</Checkbox>
</div>
</div>
checkbox_rounded.mlx
module Checkbox = Solidtype_heroui.Checkbox
module Label = Solidtype_heroui.Label
let make () =
<div class_="flex flex-col gap-6">
<div class_="flex flex-col gap-3">
<Label class_="text-muted">"Rounded checkboxes"</Label>
<Checkbox
class_="[&_[data-slot='checkbox-default-indicator--checkmark']]:size-2"
name="small-rounded">
<Checkbox.Content>
<Checkbox.Control class_="size-3 rounded-full before:rounded-full">
<Checkbox.Indicator />
</Checkbox.Control>
"Small size"
</Checkbox.Content>
</Checkbox>
</div>
<div class_="flex flex-col gap-3">
<Checkbox name="default-rounded">
<Checkbox.Content>
<Checkbox.Control class_="size-4 rounded-full before:rounded-full">
<Checkbox.Indicator />
</Checkbox.Control>
"Default size"
</Checkbox.Content>
</Checkbox>
</div>
<div class_="flex flex-col gap-3">
<Checkbox name="large-rounded">
<Checkbox.Content>
<Checkbox.Control class_="size-5 rounded-full before:rounded-full">
<Checkbox.Indicator />
</Checkbox.Control>
"Large size"
</Checkbox.Content>
</Checkbox>
</div>
<div class_="flex flex-col gap-3">
<Checkbox
class_="[&_[data-slot='checkbox-default-indicator--checkmark']]:size-4"
name="xl-rounded">
<Checkbox.Content>
<Checkbox.Control class_="size-6 rounded-full before:rounded-full">
<Checkbox.Indicator />
</Checkbox.Control>
"Extra large size"
</Checkbox.Content>
</Checkbox>
</div>
</div>
This feature is coming soon
checkbox_disabled.mlx
module Checkbox = Solidtype_heroui.Checkbox
module Description = Solidtype_heroui.Description
let make () =
<Checkbox is_disabled=true>
<Checkbox.Content>
<Checkbox.Control><Checkbox.Indicator /></Checkbox.Control>
"Premium Feature"
</Checkbox.Content>
<Description>"This feature is coming soon"</Description>
</Checkbox>

HeroUI’s label names the checkbox by its id, which the port’s checkbox does not take yet; here the checkbox is named as the label is.

checkbox_external_label.mlx
module Checkbox = Solidtype_heroui.Checkbox
module Label = Solidtype_heroui.Label
(* HeroUI's label names the checkbox by its id, which the port's checkbox
does not take yet: it is named as the label is. *)
let make () =
<div class_="flex items-center gap-3">
<Checkbox aria_label="Send me marketing emails">
<Checkbox.Content>
<Checkbox.Control><Checkbox.Indicator /></Checkbox.Control>
</Checkbox.Content>
</Checkbox>
<Label>"Send me marketing emails"</Label>
</div>
Get notified when someone mentions you in a comment
checkbox_description.mlx
module Checkbox = Solidtype_heroui.Checkbox
module Description = Solidtype_heroui.Description
let make () =
<Checkbox name="description-notifications">
<Checkbox.Content>
<Checkbox.Control><Checkbox.Indicator /></Checkbox.Control>
"Email notifications"
</Checkbox.Content>
<Description>
"Get notified when someone mentions you in a comment"
</Description>
</Checkbox>
checkbox_default_selected.mlx
module Checkbox = Solidtype_heroui.Checkbox
let make () =
<Checkbox default_selected=true>
<Checkbox.Content>
<Checkbox.Control><Checkbox.Indicator /></Checkbox.Control>
"Enable email notifications"
</Checkbox.Content>
</Checkbox>
You must accept the terms to continue
checkbox_invalid.mlx
module Checkbox = Solidtype_heroui.Checkbox
module Field_error = Solidtype_heroui.Field_error
let make () =
<Checkbox is_invalid=true is_required=true name="agreement">
<Checkbox.Content>
<Checkbox.Control><Checkbox.Indicator /></Checkbox.Control>
"I agree to the terms"
</Checkbox.Content>
<Field_error>"You must accept the terms to continue"</Field_error>
</Checkbox>

Status: Enabled

checkbox_controlled.mlx
module Checkbox = Solidtype_heroui.Checkbox
module S = Solidtype.Solid
let make () =
let selected, set_selected = S.create_signal true in
<div class_="flex flex-col gap-3">
<Checkbox
is_selected=(fun () -> S.get selected) on_change=(S.set set_selected)>
<Checkbox.Content>
<Checkbox.Control><Checkbox.Indicator /></Checkbox.Control>
"Email notifications"
</Checkbox.Content>
</Checkbox>
<p class_="text-sm text-muted">
"Status: "
<span class_="font-medium">
(fun () ->
Solidtype.Jsx.string
(if S.get selected then "Enabled" else "Disabled"))
</span>
</p>
</div>
Shows indeterminate state (dash icon)
checkbox_indeterminate.mlx
module Checkbox = Solidtype_heroui.Checkbox
module S = Solidtype.Solid
module Description = Solidtype_heroui.Description
let make () =
let indeterminate, set_indeterminate = S.create_signal true in
let selected, set_selected = S.create_signal false in
<Checkbox
is_indeterminate=(fun () -> S.get indeterminate)
is_selected=(fun () -> S.get selected)
on_change=(fun v ->
S.set set_selected v;
S.set set_indeterminate false)>
<Checkbox.Content>
<Checkbox.Control><Checkbox.Indicator /></Checkbox.Control> "Select all"
</Checkbox.Content>
<Description>"Shows indeterminate state (dash icon)"</Description>
</Checkbox>
checkbox_form.mlx
module Button = Solidtype_heroui.Button
module Checkbox = Solidtype_heroui.Checkbox
type form_data
external prevent_default : Dom.event -> unit = "preventDefault" [@@mel.send]
external target : Dom.event -> Dom.element = "target" [@@mel.get]
external form_data : Dom.element -> form_data = "FormData" [@@mel.new]
external entries : form_data -> (string * string) array = "from"
[@@mel.scope "Array"]
external alert : string -> unit = "alert"
let submit e =
prevent_default e;
let lines =
form_data (target e)
|> entries
|> Array.map (fun (key, value) -> key ^ ": " ^ value)
|> Array.to_list |> String.concat "\n"
in
alert ("Form submitted with:\n" ^ lines)
let item ?(selected = false) ~name ~text () =
<Checkbox
default_selected=(fun () -> selected) name=(fun () -> name) value="on">
<Checkbox.Content>
<Checkbox.Control><Checkbox.Indicator /></Checkbox.Control>
(fun () -> Solidtype.Jsx.string text)
</Checkbox.Content>
</Checkbox>
let make () =
<form class_="flex flex-col gap-4" on_submit=submit>
<div class_="flex flex-col gap-3">
(fun () ->
Solidtype.Jsx.element
(item ~name:"notifications" ~text:"Enable notifications" ()))
(fun () ->
Solidtype.Jsx.element
(item ~selected:true ~name:"newsletter"
~text:"Subscribe to newsletter" ()))
(fun () ->
Solidtype.Jsx.element
(item ~name:"marketing" ~text:"Receive marketing updates" ()))
</div>
<Button class_="mt-4" size=`sm type_=`submit variant=`primary>
"Submit"
</Button>
</form>

HeroUI’s children read the checkbox’s state through a render prop; here the page keeps the state, which the checkbox is controlled by.

Please read and accept the terms
checkbox_render_props.mlx
module Checkbox = Solidtype_heroui.Checkbox
module S = Solidtype.Solid
module Description = Solidtype_heroui.Description
(* HeroUI's children read the checkbox's state through a render prop; here
the page keeps the state, which the checkbox controls. *)
let make () =
let selected, set_selected = S.create_signal false in
<Checkbox
is_selected=(fun () -> S.get selected) on_change=(S.set set_selected)>
<Checkbox.Content>
<Checkbox.Control><Checkbox.Indicator /></Checkbox.Control>
(fun () ->
Solidtype.Jsx.string
(if S.get selected then "Terms accepted" else "Accept terms"))
</Checkbox.Content>
<Description>
(fun () ->
Solidtype.Jsx.string
(if S.get selected then "Thank you for accepting"
else "Please read and accept the terms"))
</Description>
</Checkbox>

HeroUI’s Render Function example gives a part render, React’s way to swap the element it renders, which a Solid component has no need of.

HeroUI draws each icon only while the box is checked, through a render prop; HeroUI’s styles show an indicator’s content only then, so here it is given as it is.

checkbox_custom_indicator.mlx
module Checkbox = Solidtype_heroui.Checkbox
(* HeroUI draws each icon only while the box is checked, by a render prop;
HeroUI's styles show an indicator's content only then, so it is given as it
is. *)
let make () =
<div class_="flex gap-4">
<Checkbox default_selected=true name="heart">
<Checkbox.Content>
<Checkbox.Control>
<Checkbox.Indicator>
<svg fill="currentColor" view_box="0 0 24 24">
<path
d="M12.62 20.81c-.34.12-.9.12-1.24 0C8.48 19.82 2 15.69 2 8.69 \
2 5.6 4.49 3.1 7.56 3.1c1.82 0 3.43.88 4.44 2.24a5.53 5.53 \
0 0 1 4.44-2.24C19.51 3.1 22 5.6 22 8.69c0 7-6.48 \
11.13-9.38 12.12Z"
fill="currentColor"
/>
</svg>
</Checkbox.Indicator>
</Checkbox.Control>
"Heart"
</Checkbox.Content>
</Checkbox>
<Checkbox default_selected=true name="plus">
<Checkbox.Content>
<Checkbox.Control>
<Checkbox.Indicator>
<svg fill="none" view_box="0 0 24 24">
<path
d="M6 12H18"
stroke="currentColor"
stroke_linecap="round"
stroke_linejoin="round"
stroke_width="3"
/>
<path
d="M12 18V6"
stroke="currentColor"
stroke_linecap="round"
stroke_linejoin="round"
stroke_width="3"
/>
</svg>
</Checkbox.Indicator>
</Checkbox.Control>
"Plus"
</Checkbox.Content>
</Checkbox>
<Checkbox is_indeterminate=true name="indeterminate">
<Checkbox.Content>
<Checkbox.Control>
<Checkbox.Indicator>
<svg stroke="currentColor" stroke_width="3" view_box="0 0 24 24">
<line x1="21" x2="3" y1="12" y2="12" />
</svg>
</Checkbox.Indicator>
</Checkbox.Control>
"Indeterminate"
</Checkbox.Content>
</Checkbox>
</div>

class_ is added after HeroUI’s classes.

checkbox_tailwind.mlx
module Checkbox = Solidtype_heroui.Checkbox
let make () =
<Checkbox>
<Checkbox.Content>
<Checkbox.Control class_="bg-success-soft before:bg-success">
<Checkbox.Indicator
class_="**:data-[slot=checkbox-default-indicator--checkmark]:text-success-foreground"
/>
</Checkbox.Control>
"Custom styled checkbox"
</Checkbox.Content>
</Checkbox>

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

@layer components {
.checkbox__control {
@apply rounded-full;
}
}
  • .checkbox, .checkbox__content, .checkbox__control, .checkbox__indicator
  • Variants: .checkbox--primary, .checkbox--secondary
  • Selected: [data-selected="true"] or [aria-checked="true"]
  • Indeterminate: [data-indeterminate="true"]
  • Invalid: [data-invalid="true"] or [aria-invalid="true"]
  • Hover: :hover or [data-hovered="true"]
  • Focus: :focus-visible or [data-focus-visible="true"]
  • Disabled: [data-disabled="true"]
  • Pressed: :active or [data-pressed="true"]

Each prop beside the name HeroUI’s React component gives it.

React solidtype Type Default Description
variant variant [ `primary | `secondary ] `primary Visual style
isSelected is_selected bool Whether it is checked, controlled
defaultSelected default_selected bool false Whether it starts checked
isIndeterminate is_indeterminate bool false Whether it shows the dash
onChange on_change bool -> unit Called as it is toggled
isDisabled is_disabled bool false Whether it 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 content, and its control
isReadOnly is_read_only bool false Whether it keeps its state
isRequired is_required bool false Whether a form requires it
name name string Its name in a form
value value string Its value in a form, while it is checked
aria-label aria_label string Its name where no label names it

Checkbox.Content, Checkbox.Control and Checkbox.Indicator

Section titled “Checkbox.Content, Checkbox.Control and Checkbox.Indicator”
React solidtype Type Description
className class_ string Added after HeroUI’s class
children children elements What it holds; the indicator’s own mark when given

Original HeroUI documentation: Checkbox.

The same HeroUI Checkbox twice, under the same props: in solidtype on the left, in React on the right. Below them, every attribute of the two contents: a marked row is one they disagree on, and a dimmed row is a framework’s own, which no style reads.

solidtype — OCaml, on Solid and Kobalte
React — TypeScript, on React Aria
attributesolidtypeReact