Toggle

A control element that switches between two states, providing a binary choice.

••••
	<script lang="ts">
  import { Toggle } from "bits-ui";
  import LockKeyOpen from "phosphor-svelte/lib/LockKeyOpen";
 
  let unlocked = $state(false);
  const code = $derived(unlocked ? "B1T5" : "••••");
</script>
 
<div
  class="min-h-input flex h-full w-[176px] items-center gap-2 rounded-card-sm border border-border bg-background-alt py-1 pl-[18px] pr-1.5 shadow-mini"
>
  <div
    class="text-end font-alt text-[19px] tracking-[13.87px] {unlocked
      ? 'text-foreground'
      : 'text-muted-foreground'}"
  >
    {code}
  </div>
  <Toggle.Root
    aria-label="toggle code visibility"
    class="inline-flex size-10 items-center justify-center rounded-[9px] bg-background-alt transition-all hover:bg-muted active:scale-98 active:bg-dark-10 data-[state=on]:bg-muted data-[state=off]:text-foreground-alt data-[state=on]:text-foreground active:data-[state=on]:bg-dark-10"
    bind:pressed={unlocked}
  >
    <LockKeyOpen class="size-6" />
  </Toggle.Root>
</div>

Structure

	<script lang="ts">
	import { Toggle } from "bits-ui";
</script>
 
<Toggle.Root />

Managing Pressed State

Bits UI offers several approaches to manage and synchronize the Toggle's pressed state, catering to different levels of control and integration needs.

1. Two-Way Binding

For seamless state synchronization, use Svelte's bind:pressed directive. This method automatically keeps your local state in sync with the component's internal state.

	<script lang="ts">
	import { Toggle } from "bits-ui";
	let myPressed = $state(true);
</script>
 
<button onclick={() => (myPressed = false)}> un-press </button>
 
<Toggle.Root bind:pressed={myPressed} />

Key Benefits

  • Simplifies state management
  • Automatically updates myPressed when the switch changes (e.g., via clicking on the toggle)
  • Allows external control (e.g., pressing/toggling via a separate button/programmatically)

2. Change Handler

For more granular control or to perform additional logic on state changes, use the onPressedChange prop. This approach is useful when you need to execute custom logic alongside state updates.

	<script lang="ts">
	import { Toggle } from "bits-ui";
	let myPressed = $state(false);
</script>
 
<Toggle.Root
	checked={myPressed}
	onPressedChange={(p) => {
		myPressed = p;
		// additional logic here.
	}}
/>

Use Cases

  • Implementing custom behaviors on pressed/unpressed
  • Integrating with external state management solutions
  • Triggering side effects (e.g., logging, data fetching)

3. Fully Controlled

For complete control over the component's pressed state, use the controlledPressed prop. This approach requires you to manually manage the checked state, giving you full control over when and how the component responds to change events.

To implement controlled state:

  1. Set the controlledPressed prop to true on the Toggle.Root component.
  2. Provide a pressed prop to Toggle.Root, which should be a variable holding the current state.
  3. Implement an onPressedChange handler to update the state when the internal state changes.
	<script lang="ts">
	import { Toggle } from "bits-ui";
	let myPressed = $state(false);
</script>
 
<Toggle.Root controlledPressed pressed={myPressed} onPressedChange={(p) => (myPressed = p)}>
	<!-- ... -->
</Toggle.Root>

When to Use

  • Implementing complex checked/unchecked logic
  • Coordinating multiple UI elements
  • Debugging state-related issues

API Reference

Toggle.Root

The toggle button.

Property Type Description
pressed $bindable
boolean

Whether or not the toggle button is pressed.

Default: false
onPressedChange
function

A callback function called when the pressed state of the toggle changes.

Default: undefined
controlledPressed
boolean

Whether or not the pressed state is controlled or not. If true, the component will not update the pressed state internally, instead it will call onPressedChange when it would have otherwise, and it is up to you to update the pressed prop that is passed to the component.

Default: false
disabled
boolean

Whether or not the switch is disabled.

Default: false
ref $bindable
HTMLButtonElement

The underlying DOM element being rendered. You can bind to this to get a reference to the element.

Default: undefined
children
Snippet

The children content to render.

Default: undefined
child
Snippet

Use render delegation to render your own element. See Child Snippet docs for more information.

Default: undefined
Data Attribute Value Description
data-state
enum

Whether the toggle is in the on or off state.

data-disabled
''

Present when the toggle is disabled.

data-toggle-root
''

Present on the root element.