Toggle
A two-state button that can be either on or off.
A pressable button that toggles between pressed and unpressed states.
Toggle is backed by @areia/slots and wires aria-pressed, data-state, and toggle change events.
import { ilha } from "ilha";
import { Toggle } from "areia";
export default ilha.render(() => (
<Toggle variant="outline">Bold</Toggle>
));Import
import { Toggle, ToggleGroup } from "areia";
Usage
Use Toggle with optional variant, size, and defaultPressed. It is a single-element primitive — a <button> with data-slot="toggle".
import { ilha } from "ilha";
import { Toggle } from "areia";
export default ilha.render(() => (
<Toggle variant="outline">Italic</Toggle>
));Examples
Variants
import { ilha } from "ilha";
import { Toggle } from "areia";
export default ilha.render(() => (
<div class="flex items-center gap-2">
<Toggle>Default</Toggle>
<Toggle variant="outline">Outline</Toggle>
</div>
));Sizes
import { ilha } from "ilha";
import { Toggle } from "areia";
export default ilha.render(() => (
<div class="flex items-center gap-2">
<Toggle size="sm" variant="outline">
Small
</Toggle>
<Toggle size="default" variant="outline">
Default
</Toggle>
<Toggle size="lg" variant="outline">
Large
</Toggle>
</div>
));Disabled
import { ilha } from "ilha";
import { Toggle } from "areia";
export default ilha.render(() => (
<div class="flex items-center gap-2">
<Toggle disabled>Disabled</Toggle>
<Toggle variant="outline" disabled>
Disabled
</Toggle>
</div>
));Pressed State
Use defaultPressed to set the initial pressed state.
import { ilha } from "ilha";
import { Toggle } from "areia";
export default ilha.render(() => (
<div class="flex items-center gap-2">
<Toggle defaultPressed>Pressed</Toggle>
<Toggle variant="outline" defaultPressed>
Pressed
</Toggle>
</div>
));Toggle Group
Use ToggleGroup when multiple toggles belong together as a single control.
import { ilha } from "ilha";
import { ToggleGroup } from "areia";
export default ilha.render(() => (
<ToggleGroup type="single" defaultValue="center">
<ToggleGroup.Item value="left" variant="outline">
Left
</ToggleGroup.Item>
<ToggleGroup.Item value="center" variant="outline">
Center
</ToggleGroup.Item>
<ToggleGroup.Item value="right" variant="outline">
Right
</ToggleGroup.Item>
</ToggleGroup>
));Use type="multiple" to allow more than one item to be pressed at a time.
import { ilha } from "ilha";
import { ToggleGroup } from "areia";
export default ilha.render(() => (
<ToggleGroup type="multiple" defaultValue={["bold"]}>
<ToggleGroup.Item value="bold" variant="outline">
Bold
</ToggleGroup.Item>
<ToggleGroup.Item value="italic" variant="outline">
Italic
</ToggleGroup.Item>
<ToggleGroup.Item value="underline" variant="outline">
Underline
</ToggleGroup.Item>
</ToggleGroup>
));Change Events
Use onPressedChange to respond to state changes.
import { ilha } from "ilha";
import { Toggle } from "areia";
export default ilha.state("bold", false).render(({ state }) => (
<div class="flex flex-col items-start gap-3">
<Toggle
variant="outline"
onPressedChange={(pressed) => {
state.bold(pressed);
}}
>
Bold
</Toggle>
<p class="text-sm text-areia-subtle">
Bold is:{" "}
<span class="font-medium text-areia-default">
{state.bold() ? "On" : "Off"}
</span>
</p>
</div>
));API Reference
Toggle
Root component that manages the toggle state.
| Prop | Type | Default | Description |
|---|---|---|---|
children |
unknown |
— | Content rendered inside the toggle button. |
variant |
"default" | "outline" |
"default" |
Visual variant. default is filled, outline is bordered. |
size |
"sm" | "default" | "lg" |
"default" |
Size of the toggle. |
defaultPressed |
boolean |
false |
Initial pressed state. |
disabled |
boolean |
false |
Disables interaction and applies muted styling. |
onPressedChange |
(pressed: boolean) => void |
— | Called when the pressed state changes. |
ToggleGroup
| Prop | Type | Default | Description |
|---|---|---|---|
type |
"single" | "multiple" |
"single" |
Selection mode. |
defaultValue |
string | string[] |
— | Initial selected value(s). |
orientation |
"horizontal" | "vertical" |
"horizontal" |
Layout direction for keyboard navigation. |
loop |
boolean |
true |
Wrap keyboard focus at ends. |
disabled |
boolean |
false |
Disable the entire group. |
onValueChange |
(value: string[]) => void |
— | Called when the selection changes. |
children |
unknown |
— | ToggleGroup.Item children. |
class |
string |
— | Additional CSS classes. |
className |
string |
— | Alias for class. |
ToggleGroup.Item
| Prop | Type | Default | Description |
|---|---|---|---|
value |
string |
— | Unique item value. |
variant |
"default" | "outline" |
"default" |
Visual variant. |
size |
"sm" | "default" | "lg" |
"default" |
Size of the item. |
disabled |
boolean |
false |
Disables this item. |
children |
unknown |
— | Content rendered inside the item. |
class |
string |
— | Additional CSS classes. |
className |
string |
— | Alias for class. |
ToggleGroup.Separator
Visual divider between toggle items. Accepts standard div attributes plus class and className.
Slots
Toggle renders a single data slot:
toggle
The root receives state attributes from the slot controller:
| Attribute | Element | Description |
|---|---|---|
data-state |
toggle | "on" when pressed, "off" when not pressed. |
data-disabled |
toggle | Present when toggle is disabled. |
aria-pressed |
toggle | "true" or "false". |
Events
The toggle emits custom DOM events from the root element.
Outbound
| Event | Detail | Description |
|---|---|---|
toggle:change |
{ pressed: boolean } |
Fired when the pressed state changes. |
Inbound
| Event | Detail | Description |
|---|---|---|
toggle:set |
{ value: boolean } |
Set the pressed state programmatically. |
const toggle = document.querySelector('[data-slot="toggle"]')!;
toggle.addEventListener("toggle:change", (e) => {
console.log("Pressed:", e.detail.pressed);
});
// Set pressed state programmatically
toggle.dispatchEvent(
new CustomEvent("toggle:set", { detail: { value: true } }),
);