# Toggle

A button that stays pressed, in default and outline variants and three sizes.

Docs: https://corsairui.vercel.app/docs/toggle

## Install

```bash
pnpm dlx shadcn@latest add @corsair-ui/toggle
```

Also adds: `utils`.
npm: `@radix-ui/react-toggle`, `class-variance-authority`, `clsx`, `tailwind-merge`.

## API

Built on Radix Toggle (https://www.radix-ui.com/primitives/docs/components/toggle); its props pass through.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `variant` | `"default" \| "outline"` | `"default"` | Plain or with a border. |
| `size` | `"sm" \| "default" \| "lg"` | `"default"` | Height. |

## Styling

Restyle it in the project that installs it: `className` on each part, the theme variables, and these attributes with arbitrary variants (`[&_[data-slot=…]]:…`, `data-[state=…]:…`).

data-slot: `toggle`

## Accessibility

- Announced with aria-pressed; icon-only toggles need an aria-label.

## Examples

On the docs page: Default, Outline with text, Sizes. The usage examples in the source comments below are the reference.

## Source

What `shadcn add` writes into the project:

### toggle.tsx

```tsx
"use client";

import * as TogglePrimitive from "@radix-ui/react-toggle";
import { cva, type VariantProps } from "class-variance-authority";
import type { ComponentProps } from "react";

import { cn } from "@/registry/default/lib/utils";

const toggleVariants = cva(
  [
    "inline-flex cursor-pointer items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap",
    "transition-[color,background-color,border-color,box-shadow] outline-none motion-reduce:transition-none",
    "hover:bg-muted hover:text-muted-foreground",
    "data-[state=on]:bg-accent data-[state=on]:text-accent-foreground",
    "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
    "aria-[invalid=true]:border-destructive aria-[invalid=true]:ring-destructive/20",
    "disabled:pointer-events-none disabled:opacity-50",
    "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
  ],
  {
    variants: {
      variant: {
        default: "bg-transparent",
        outline: "border-input hover:bg-accent hover:text-accent-foreground border bg-transparent",
      },
      size: {
        sm: "h-8 min-w-8 px-1.5",
        default: "h-9 min-w-9 px-2",
        lg: "h-10 min-w-10 px-2.5",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "default",
    },
  }
);

/**
 * A button that stays pressed (`aria-pressed`), e.g. bold in a toolbar. An
 * icon-only toggle needs an `aria-label`.
 */
function Toggle({
  className,
  variant,
  size,
  ...props
}: ComponentProps<typeof TogglePrimitive.Root> & VariantProps<typeof toggleVariants>) {
  return (
    <TogglePrimitive.Root
      data-slot="toggle"
      className={cn(toggleVariants({ variant, size, className }))}
      {...props}
    />
  );
}

export { Toggle, toggleVariants };
```
