Search

Jump to any page.

Actions

Toggle

Two-state button for formatting and view options.

pnpm dlx shadcn@latest add @paragon/toggle
Brings in@base-ui/reactclass-variance-authoritycn
registry/paragon/ui/toggle.tsx
"use client"

import { Toggle as TogglePrimitive } from "@base-ui/react/toggle"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "cn"

const toggleVariants = cva(
  [
    "group/toggle inline-flex shrink-0 items-center justify-center gap-1.5 rounded-[calc(var(--radius-button)-2px)] text-sm font-medium whitespace-nowrap text-muted-foreground outline-none select-none",
    "[transition:background-color_var(--duration-base)_var(--ease-paragon),color_var(--duration-base)_var(--ease-paragon),box-shadow_var(--duration-base)_var(--ease-paragon),scale_var(--duration-slow)_var(--ease-spring)]",
    "hover:bg-foreground/5 hover:text-foreground active:scale-[0.96] active:[transition-duration:var(--duration-fast)] motion-reduce:active:scale-100",
    "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:outline-solid",
    "data-pressed:bg-foreground/8 data-pressed:text-foreground",
    "disabled:pointer-events-none disabled:opacity-45",
    "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
  ],
  {
    variants: {
      variant: {
        default: "bg-transparent",
        outline: "border border-input bg-transparent data-pressed:border-foreground/30",
      },
      size: {
        sm: "h-8 min-w-8 px-2.5 text-[0.8125rem] [&_svg:not([class*='size-'])]:size-3.5",
        default: "h-9 min-w-9 px-3",
        lg: "h-[2.625rem] min-w-[2.625rem] px-3.5 text-[0.9375rem]",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "default",
    },
  }
)

/** A two-state button, for formatting and view options. Springs when pressed, like Button. */
function Toggle({
  className,
  variant = "default",
  size = "default",
  ...props
}: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {
  return <TogglePrimitive data-slot="toggle" className={cn(toggleVariants({ variant, size, className }))} {...props} />
}

export { Toggle, toggleVariants }