Back to catalog
Component detail entry
Forms
@vean/ui
SToggle

Toggle

Toggle belongs to the Forms category. Start with demos and usage, then use the API tables to finish integration and styling decisions.

Use the quick jump panel to reach overview, usage, demos, and API first, then continue through the full page.

Quick jump

Related components

If you are composing interactions in the same family, these components usually pair well together.

Toggle

Overview

A two-state button that toggles between pressed (on) and unpressed (off) states, reflecting its state via aria-pressed and data-state. Use it for an immediate, exclusive on/off switch such as a formatting tool or a filter chip; when the choice belongs to a form that needs explicit submission, prefer SCheckbox instead.

Usage

Features

  • 🎚 modelValue / defaultValue — controlled and uncontrolled modes backed by useControllableState
  • ♿ aria-pressed + data-state (on/off) dual reflection, axe-clean
  • ⌨️ Keyboard operable — Enter and Space toggle via native button behavior
  • 🎨 3 variants (outline/soft/ghost) × 6 sizes × 8 colors × 4 shapes via toggleVariants
  • 🧩 Full SButton prop surface (icon slots, asChild, loading via button props) through Aria Toggle
  • 📦 Slot props expose modelValue / pressed / state / disabled for custom content
  • 🚫 Disabled state with disabled + aria-disabled and guarded click handling

Demos

Basic

API

Aria Layer

1

Toggle

11 Props1 Emits
Props
PropTypeDefaultDescription
class
ClassValue
—
Additional class names applied to the root element.
color
ThemeColor
—
Theme color of the component.
size
ThemeSize
—
Visual size of the component.
variant
ToggleVariant
—
Visual variant of the component.
shape
ToggleShape
—
Shape of the component.
defaultValue
boolean
—
The pressed state of the toggle when it is initially rendered.
modelValue
boolean
—
The controlled pressed state of the toggle. Can be bound with v-model.
type
ButtonType
'button'
The type of the button element. Can be one of 'button', 'submit', or 'reset'.
disabled
boolean
—
Whether the component is disabled.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
Emits
Emit NameParametersDescription
update:modelValue
boolean
Event handler called when the pressed state changes.

Notes

Architecture and benchmark differences

VeanUI builds the toggle from the Aria Toggle (useControllableState + Button base + aria-pressed/data-state reflection + disabled-guarded click) and a thin UI wrapper SToggle that only computes toggleVariants classes and forwards update:modelValue. The data-state attribute drives the pressed styling through UnoCSS data-[state=on]:* selectors, keeping state and visuals decoupled. toggle is a Radix/shadcn-native pattern; the other benchmark libraries express the same interaction through button-plus-state or segmented controls.

CapabilityVeanUIAnt DesignElement PlusMantineNaive UIshadcn Toggle
Aria/styled split✅————✅
Pressed/unpressed state✅————✅
Controlled/uncontrolled✅————✅
aria-pressed + data-state✅————✅
Variants (outline/soft/ghost)✅————✅
Sizes/shapes (6 sizes × 4)✅—————
Keyboard (Enter/Space)✅————✅
Disabled✅————✅
Axe-clean✅—————
Pressed-state icon animation➕✅————

Cautions

  • An icon-only toggle has no accessible name — pass aria-label (or use a visible label) to stay axe-clean.
  • The pressed state is reflected by aria-pressed and data-state; style the pressed look with data-[state=on]:* utilities or the built-in variants.
  • Enter/Space toggling relies on the native button behavior of the Button base.
  • For exclusive multi-choice, compose toggles with SToggleGroup instead of managing state by hand.

FAQ

Controlled or uncontrolled?

Pass modelValue with v-model for a controlled value, or defaultValue to let the toggle own its state internally. Both are supported via useControllableState.

How do I build an icon-only toggle?

Put an icon in the default slot and add aria-label (e.g. aria-label="Bold"). The toggleVariants base already neutralizes svg pointer events and gives icons a default size-4.

What is the difference between SToggle and SButton?

SToggle is a stateful button — it remembers whether it is pressed and reflects that via aria-pressed/data-state with pressed styling; SButton is stateless and only emits clicks.

How do I build a group of toggles?

Use SToggleGroup — it manages single/multiple selection and the associated aria-pressed state for you.

Changelog

Version history is grouped by release so you can quickly see what changed for this component across published versions.

v0.23.1

2026-05-19

Compare release

Fix

fix class binding

Scope: toggleAuthors: soybeanjsView commit7b9c4

Fix

fix class binding

Scope: toggleAuthors: soybeanjsView commit7b9c4

v0.15.0

2026-04-26

Compare release

Fix

add shape prop to ToggleProps and update forwardedProps

Scope: toggleAuthors: soybeanjsView commit63f21

Fix

add shape prop to ToggleProps and update forwardedProps

Scope: toggleAuthors: soybeanjsView commit63f21