Skip to content

ToggleButton

A button pressed on or off.

Solidtype_heroui.Toggle_button is Kobalte’s toggle button with the classes HeroUI’s own toggleButtonVariants gives, and the state HeroUI’s styles read: data-selected while it is on, and the hover, press and focus React Aria shows. Inside a Toggle_button_group it is the group’s button of its id.

toggle_button_usage.mlx
module Toggle_button = Solidtype_heroui.Toggle_button
let make () = <Toggle_button><Icons.Heart /> "Like"</Toggle_button>
toggle_button_variants.mlx
module Toggle_button = Solidtype_heroui.Toggle_button
let make () =
<div class_="flex items-center gap-3">
<Toggle_button><Icons.Heart /> "Default"</Toggle_button>
<Toggle_button variant=`ghost><Icons.Heart /> "Ghost"</Toggle_button>
</div>

An icon alone is named by aria_label.

toggle_button_icon_only.mlx
module Toggle_button = Solidtype_heroui.Toggle_button
let make () =
<div class_="flex items-center gap-3">
<Toggle_button is_icon_only=true aria_label="Like">
<Icons.Heart />
</Toggle_button>
<Toggle_button is_icon_only=true aria_label="Bookmark" variant=`ghost>
<Icons.Bookmark />
</Toggle_button>
</div>
toggle_button_sizes.mlx
module Toggle_button = Solidtype_heroui.Toggle_button
let make () =
<div class_="flex flex-col gap-6">
<div class_="flex items-center gap-3">
<Toggle_button size=`sm><Icons.Heart /> "Small"</Toggle_button>
<Toggle_button size=`md><Icons.Heart /> "Medium"</Toggle_button>
<Toggle_button size=`lg><Icons.Heart /> "Large"</Toggle_button>
</div>
<div class_="flex items-center gap-3">
<Toggle_button is_icon_only=true aria_label="Like" size=`sm>
<Icons.Heart />
</Toggle_button>
<Toggle_button is_icon_only=true aria_label="Like" size=`md>
<Icons.Heart />
</Toggle_button>
<Toggle_button is_icon_only=true aria_label="Like" size=`lg>
<Icons.Heart />
</Toggle_button>
</div>
</div>
toggle_button_disabled.mlx
module Toggle_button = Solidtype_heroui.Toggle_button
let make () =
<div class_="flex items-center gap-3">
<Toggle_button is_disabled=true><Icons.Heart /> "Like"</Toggle_button>
<Toggle_button default_selected=true is_disabled=true>
<Icons.Heart_fill /> "Like"
</Toggle_button>
</div>

is_selected gives its state, and on_change is called with the new one. A function of its state as its children, React’s render prop, is not taken: the content reads the signal the page keeps, as here.

Status: Not selected

toggle_button_controlled.mlx
module S = Solidtype.Solid
module Jsx = Solidtype.Jsx
module Toggle_button = Solidtype_heroui.Toggle_button
(* The button's state is the page's signal, which its content reads too, as
React's render prop reads the button's. *)
let make () =
let selected, set_selected = S.create_signal false in
<div class_="flex flex-col gap-4">
<Toggle_button
is_selected=(fun () -> S.get selected) on_change=(S.set set_selected)>
(fun () ->
if S.get selected then Jsx.element <Icons.Heart_fill />
else Jsx.element <Icons.Heart />)
(fun () -> Jsx.string (if S.get selected then "Liked" else "Like"))
</Toggle_button>
<p class_="text-sm text-muted">
"Status: "
<span class_="font-medium">
(fun () ->
Jsx.string (if S.get selected then "Selected" else "Not selected"))
</span>
</p>
</div>

class_ is added after HeroUI’s classes.

toggle_button_tailwind.mlx
module Toggle_button = Solidtype_heroui.Toggle_button
let make () =
<Toggle_button
class_="gap-2 rounded-full border border-border/80 bg-surface px-4 \
text-foreground shadow-sm data-[selected=true]:border-accent/30 \
data-[selected=true]:bg-accent-soft \
data-[selected=true]:text-accent-soft-foreground \
[&_svg]:text-muted data-[selected=true]:[&_svg]:text-accent">
<Icons.Heart /> "Save article"
</Toggle_button>

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

@layer components {
.toggle-button {
@apply bg-purple-500 text-white;
}
.toggle-button--icon-only {
@apply rounded-lg;
}
}
  • .toggle-button, and its sizes .toggle-button--sm, .toggle-button--md, .toggle-button--lg
  • .toggle-button--default, .toggle-button--ghost
  • .toggle-button--icon-only
  • Selected: [data-selected="true"]
  • Hover: :hover or [data-hovered="true"]
  • Pressed: :active or [data-pressed="true"]
  • Focus: :focus-visible or [data-focus-visible="true"]
  • Disabled: :disabled or [data-disabled="true"]

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

React solidtype Type Default Description
variant variant [ `default | `ghost ] `default Its look
size size [ `sm | `md | `lg ] `md, or its group’s Its size
isIconOnly is_icon_only bool false Whether it shows an icon alone
id id string Its key in a group
isSelected is_selected bool Whether it is on, while given
defaultSelected default_selected bool false Whether it is on at first
onChange on_change bool -> unit Called with its new state
isDisabled is_disabled bool false, or its group’s Whether it is disabled
onPress on_click Dom.mouseEvent -> unit Called as it is clicked
aria-label aria_label string Its name, where it shows an icon alone
className class_ string Added after HeroUI’s classes
children children elements Its content

Original HeroUI documentation: ToggleButton.

The same HeroUI ToggleButton twice, under the same props: in solidtype on the left, in React on the right. Below them, every attribute of the two buttons: a marked row is one they disagree on, and a dimmed row is a framework’s own, which no style reads. React Aria writes tabindex="0" on the button, which a button has anyway; Kobalte marks a button that is on with an empty data-pressed, which HeroUI’s styles, reading data-pressed="true" for a press, never match.

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