Installation
Install the dependencies
pnpm add cn class-variance-authority github:sveltery/baseCopy the component
Copy the following files into src/lib/components/ui/toggle.
<script lang="ts">
import { Toggle as Primitive } from '@sveltery/base/toggle';
import { cn } from 'cn';
import type { ToggleProps } from './types.js';
import { toggleVariants } from './variants.js';
let { pressed = $bindable(), class: classProp, variant = 'default', size = 'default', ...props }: ToggleProps = $props();
</script>
<Primitive data-slot="toggle" bind:pressed {...props} class={cn(toggleVariants({ variant, size }), classProp)} />import type { ToggleProps as BaseToggleProps } from '@sveltery/base/toggle';
import type { ToggleVariants } from './variants.js';
export type ToggleProps = BaseToggleProps & ToggleVariants;
export type { ToggleState } from '@sveltery/base/toggle';// Adapted from shadcn-ui/ui d75a96ab; MIT: packages/ui/THIRD_PARTY_NOTICES.md.
import { cva } from 'class-variance-authority';
import type { VariantProps } from 'class-variance-authority';
export const toggleVariants = cva("hover:text-foreground aria-pressed:bg-muted focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[state=on]:bg-muted gap-1 rounded-lg text-sm font-medium transition-all [&_svg:not([class*='size-'])]:size-4 group/toggle inline-flex items-center justify-center whitespace-nowrap outline-none hover:bg-muted focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0", {
variants: {
variant: { default: 'bg-transparent', outline: 'border-input hover:bg-muted border bg-transparent' },
size: { default: 'h-8 min-w-8 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2', sm: "h-7 min-w-7 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5", lg: 'h-9 min-w-9 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2' },
},
defaultVariants: { variant: 'default', size: 'default' },
});
export type ToggleVariants = VariantProps<typeof toggleVariants>;export { default as Toggle } from './Toggle.svelte';
export { toggleVariants } from './variants.js';
export type { ToggleVariants } from './variants.js';
export type { ToggleProps, ToggleState } from './types.js';Update the import paths
Change the imports to match your project setup.
Usage
<script lang="ts">
import { Toggle } from '$lib/components/ui/toggle';
</script><Toggle aria-label="Toggle italic">Italic</Toggle>Pressed state
pressed holds the state. Pass it to start the toggle on, or bind it to read and write it.
<script lang="ts">
let bold = $state(false);
</script>
<Toggle aria-label="Toggle bold" bind:pressed={bold}>Bold</Toggle>Outline
<Toggle variant="outline" aria-label="Toggle italic">Italic</Toggle>Sizes
size is sm, default or lg.
<Toggle size="sm" aria-label="Toggle small">Small</Toggle>
<Toggle size="lg" aria-label="Toggle large">Large</Toggle>Disabled
<Toggle disabled aria-label="Toggle disabled">Disabled</Toggle>API reference
Toggle is styled on top of the Sveltery Base Toggle primitive, which owns its pressed state, keyboard behavior and accessibility. toggleVariants returns the class string for variant and size. See the Base UI Toggle documentation for the behavior it ports.