Forms · astro-ui · Toggle

Toggle

Two-state button with aria-pressed — SSR-controlled.

Toggle is a semantic <button type=“button”> that carries aria-pressed. State is server-rendered: pass pressed for SSR-controlled state (e.g. a filter that is on for the initial page load), and flip the attribute with your own one-line script when the user clicks. Styles mirror Button: default (muted fill when pressed) and outline (primary fill) variants at three sizes.

Features

  • Semantic button + aria-pressed (correct pressed semantics, no div hacks)
  • SSR-controlled state via the pressed prop
  • default / outline variants at sm / md / lg
  • Zero JS — flip aria-pressed with a one-line app script

Usage

---
import { Toggle } from "astro-ui";
---

<Toggle ariaLabel="Bold"><strong>B</strong></Toggle>

<script>
  document.querySelectorAll(".aui-toggle").forEach((btn) => {
    btn.addEventListener("click", () => {
      const on = btn.getAttribute("aria-pressed") === "true";
      btn.setAttribute("aria-pressed", String(!on));
      btn.classList.toggle("aui-toggle--pressed", !on);
    });
  });
</script>

Demos

Variants

<Toggle variant="default" ariaLabel="Bold">B</Toggle>
<Toggle variant="outline" ariaLabel="Italic">I</Toggle>
<Toggle variant="outline" pressed ariaLabel="Underline">U</Toggle>

Sizes

<Toggle size="sm">Sm</Toggle>
<Toggle size="md">Md</Toggle>
<Toggle size="lg">Lg</Toggle>

Bookmark

<Toggle id="bookmark-btn" ariaLabel="Bookmark">
  <svg viewBox="0 0 24 24" width="1em" height="1em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M19 21l-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/>
  </svg>
</Toggle>

<script>
  const btn = document.getElementById("bookmark-btn");
  const icon = btn?.querySelector("svg");
  btn?.addEventListener("click", () => {
    const on = btn.getAttribute("aria-pressed") === "true";
    btn.setAttribute("aria-pressed", String(!on));
    btn.classList.toggle("aui-toggle--pressed", !on);
    btn.setAttribute("aria-label", !on ? "Bookmarked" : "Bookmark");
    icon?.setAttribute("fill", !on ? "currentColor" : "none");
  });
</script>
<!-- click to bookmark: flips aria-pressed, the pressed style, and the icon fill -->

API

Props

PropTypeDefaultDescription
pressedbooleanfalseSSR state — maps to aria-pressed and the pressed styling.
variant"default" | "outline""default"Visual style.
size"sm" | "md" | "lg""md"Scale of the button.
disabledbooleanfalseDisables the toggle.
classstring—Merged via cn(); Tailwind classes welcome.
idstring—Element id.
ariaLabelstring—Accessible name.

Accessibility

Implemented accessibility features — semantics, ARIA wiring, and keyboard behavior that ship with the component.

  • aria-pressed announces the on/off state
  • :focus-visible ring

FAQ

Where's the click handling?

Nowhere — Toggle is SSR-only. Flip aria-pressed (and toggle the aui-toggle--pressed class) in a one-line app script; see the usage example.

Changelog

Version history mentioning Toggle.

v0.1.0 — 2026-11-11
added
  • Forms (18): Autocomplete, Combobox, Label, Field, Input, InputGroup, Textarea, Select, Checkbox, Radio, Switch, Toggle, ToggleGroup, RadioGroup, Rating, Slider, DatePicker, TimePicker.