Skip to content

Toggle

A pressable button that toggles between pressed and unpressed states.

Source Code

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" => {
        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.

PropTypeDefaultDescription
childrenunknownContent 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.
defaultPressedbooleanfalseInitial pressed state.
disabledbooleanfalseDisables interaction and applies muted styling.
onPressedChange(pressed: boolean) => voidCalled when the pressed state changes.

ToggleGroup

PropTypeDefaultDescription
type"single" | "multiple""single"Selection mode.
defaultValuestring | string[]Initial selected value(s).
orientation"horizontal" | "vertical""horizontal"Layout direction for keyboard navigation.
loopbooleantrueWrap keyboard focus at ends.
disabledbooleanfalseDisable the entire group.
onValueChange(value: string[]) => voidCalled when the selection changes.
childrenunknownToggleGroup.Item children.
classstringAdditional CSS classes.
classNamestringAlias for class.

ToggleGroup.Item

PropTypeDefaultDescription
valuestringUnique item value.
variant"default" | "outline""default"Visual variant.
size"sm" | "default" | "lg""default"Size of the item.
disabledbooleanfalseDisables this item.
childrenunknownContent rendered inside the item.
classstringAdditional CSS classes.
classNamestringAlias 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:

AttributeElementDescription
data-statetoggle"on" when pressed, "off" when not pressed.
data-disabledtogglePresent when toggle is disabled.
aria-pressedtoggle"true" or "false".

Events

The toggle emits custom DOM events from the root element.

Outbound

EventDetailDescription
toggle:change{ pressed: boolean }Fired when the pressed state changes.

Inbound

EventDetailDescription
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 } }),
);