Join our Discord Community

Shadcn Toggle

React toggle for two-state buttons for formatting controls and feature toggles. Built with TypeScript and Tailwind CSS for Next.js using Radix UI.

Toggle state issues?

Join our Discord community for help from other developers.


Ever clicked a bold button in an editor and wondered if it actually worked? You click, nothing visible happens, then you type and realize formatting isn't active. That's the frustration toggles solve—they stay pressed when active, so you always know what state you're in. This shadcn/ui toggle makes binary controls feel obvious and reliable in your React applications.

Basic toggle button

Simple bold formatting toggle:

Loading component...

Clean pressed/unpressed states with visual feedback. This free open source React component handles all the accessibility requirements and keyboard navigation for two-state controls. Built with TypeScript for full type safety while styled with Tailwind CSS to match your design system in Next.js applications.

npx shadcn@latest add toggle

Why toggles improve user experience

Here's the thing—regular buttons leave users guessing about state. Click a "Bold" button and nothing visible changes until you start typing. That's cognitive overhead. Toggles eliminate that uncertainty by showing exactly what's active right now.

Toggles solve real interface problems:

  • State visibility - Users instantly see what's active without testing
  • Persistent feedback - Button stays pressed while feature is on
  • Less cognitive load - No guessing about current state in JavaScript applications
  • Familiar pattern - Everyone knows how toggle buttons work from text editors
  • Space efficient - One button handles both on and off states
  • Immediate response - Visual feedback happens instantly on interaction

Common patterns you'll actually use

Text formatting group

Multiple toggles working together:

Loading component...

Rich text toolbar

Complete editor toolbar with grouped toggles:

Loading component...

Look, toggles shine in toolbars and formatting controls where users need instant visual feedback. Text formatting is the classic use case, but they work great for view modes, filter states, or any feature that's either on or off.

Built on Radix UI with full TypeScript support and Tailwind CSS styling. The accessibility stuff is handled for you—ARIA attributes, keyboard navigation, screen reader support.

API Reference

Toggle

A two-state button component.

PropTypeDefaultDescription
pressedboolean-The controlled pressed state of the toggle
defaultPressedbooleanfalseThe default pressed state (uncontrolled)
onPressedChange(pressed: boolean) => void-Event handler called when the pressed state changes
disabledbooleanfalseWhen true, prevents the user from interacting with the toggle
variant"default" | "outline""default"The visual style variant
size"default" | "sm" | "lg""default"The size of the toggle
classNamestring-Additional CSS classes

Data Attributes

The toggle automatically applies data attributes for styling:

AttributeValuesDescription
[data-state]"on" | "off"Indicates whether the toggle is pressed
[data-disabled]Present when disabledApplied when the toggle is disabled

Size Variants

SizeDescription
smSmaller toggle for compact toolbars
defaultStandard size for most use cases
lgLarger toggle for primary actions

Style Variants

VariantDescription
defaultFilled style with solid background when pressed
outlineOutlined style with border emphasis

Keyboard Navigation

The toggle supports full keyboard interaction:

KeyDescription
SpaceActivates/deactivates the toggle
EnterActivates/deactivates the toggle

Accessibility Features

Built-in accessibility support includes:

  • ARIA attributes - Proper aria-pressed state communication
  • Keyboard support - Space and Enter keys toggle state
  • Focus management - Clear focus indicators
  • Screen reader support - State changes are announced
  • Semantic button - Uses proper button semantics
  • Label association - Connects with aria-label or external labels

Styling Examples

The toggle component supports different variants and sizes. Check the preview examples above to see various styling options in action, including outline variants, different sizes, and text labels.

Common use cases

Toggles work great for these scenarios:

  • Text formatting - Bold, italic, underline controls
  • View modes - List vs grid, expanded vs collapsed
  • Filter states - Show/hide categories, active filters
  • Feature flags - Enable/disable functionality
  • Layout options - Sidebar visibility, panel states
  • Tool selection - Active drawing tools, editing modes
  • Status indicators - Favorite, bookmark, follow states

Things to watch out for

Make pressed states obvious. The default styling is good, but double-check your design system. Users shouldn't have to guess whether a toggle is active—especially in light/dark mode switches.

Group related toggles logically. Bold/italic/underline together, alignment controls together. Don't scatter related functionality across your toolbar.

Handle async operations properly. If your toggle triggers a server request, disable it during the operation and handle failures gracefully. Nothing worse than a toggle that appears to work but silently fails.

Test with keyboard navigation. Tab order should make sense, and Space/Enter should work consistently across all your toggles.

Works well with

Toggles fit naturally in Button toolbars—mix regular buttons with toggles for actions vs state controls.

Wrap toggle groups in Card components for settings panels. Use Separator to visually group related toggles in complex toolbars.

Badge components are useful for showing counts when toggles filter content. Tooltip helps with icon-only toggles.

For text editors, combine with Textarea for the actual content area, or Input for inline editing modes.

Quick guidelines

  • Use aria-label or visible text for clarity
  • Make pressed states visually obvious
  • Group related toggles together
  • Keep consistent sizing within groups
  • Choose clear icons that represent the action
  • Persist state appropriately (session vs permanent)
  • Show loading during async operations
  • Revert state on errors

Questions you might have