# Toggle Group

A set of related toggles built on Radix Toggle Group, supporting single or multiple selection, keyboard roving focus, shared variant and size, and configurable item spacing.

- Category: Overlays & Navigation
- License: MIT
- Page: https://www.saasuji.com/components/toggle-group
- Install: npx shadcn@latest add https://www.saasuji.com/r/toggle-group.json

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| type (ToggleGroup) | `"single" | "multiple"` | — | Whether one item or several items can be pressed at the same time; required. |
| value (ToggleGroup) | `string | string[]` | — | Controlled pressed value or values, matching the group type. |
| defaultValue (ToggleGroup) | `string | string[]` | — | Item value or values pressed on first render. |
| onValueChange (ToggleGroup) | `((value: string) => void) | ((value: string[]) => void)` | — | Called when the pressed item or items change; the signature follows the group type. |
| disabled (ToggleGroup, ToggleGroupItem) | `boolean` | `false` | Prevents the group or a single item from being toggled. |
| rovingFocus (ToggleGroup) | `boolean` | `true` | Moves focus between items with the arrow keys using a single tab stop. |
| loop (ToggleGroup) | `boolean` | `true` | Wraps keyboard focus from the last item back to the first. |
| orientation (ToggleGroup) | `"horizontal" | "vertical"` | `"horizontal"` | Arrow-key direction for roving focus. |
| variant (ToggleGroup, ToggleGroupItem) | `"default" | "outline"` | `"default"` | Shared item style; the group provides it through context and an individual item can override it. |
| size (ToggleGroup, ToggleGroupItem) | `"default" | "sm" | "lg"` | `"default"` | Shared item size; the group provides it through context and an individual item can override it. |
| spacing (ToggleGroup) | `number` | `0` | Gap in pixels between items; 0 keeps rounded outer corners and shared borders. |
| value (ToggleGroupItem) | `string` | — | Unique value toggled on and off by the item; required. |
| asChild (ToggleGroupItem) | `boolean` | `false` | Renders the item as its child element instead of the default button. |
| className (ToggleGroup, ToggleGroupItem) | `string` | — | Additional classes merged onto the group or item. |
| children (ToggleGroup, ToggleGroupItem) | `React.ReactNode` | — | ToggleGroupItem children inside the group; text, icon, or both inside each item. |
| ...props (ToggleGroup) | `React.ComponentProps<typeof ToggleGroupPrimitive.Root>` | — | All remaining Radix Toggle Group root props are forwarded. |
| ...props (ToggleGroupItem) | `React.ComponentProps<typeof ToggleGroupPrimitive.Item>` | — | All remaining Radix Toggle Group item props are forwarded to the rendered button. |

## Source

```tsx
"use client"

import * as React from "react"
import { type VariantProps } from "class-variance-authority"
import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui"

import { cn } from "@/lib/utils"
import { toggleVariants } from "@/components/ui/toggle"

const ToggleGroupContext = React.createContext<
  VariantProps<typeof toggleVariants> & {
    spacing?: number
  }
>({
  size: "default",
  variant: "default",
  spacing: 0,
})

function ToggleGroup({
  className,
  variant,
  size,
  spacing = 0,
  children,
  ...props
}: React.ComponentProps<typeof ToggleGroupPrimitive.Root> &
  VariantProps<typeof toggleVariants> & {
    spacing?: number
  }) {
  return (
    <ToggleGroupPrimitive.Root
      data-slot="toggle-group"
      data-variant={variant}
      data-size={size}
      data-spacing={spacing}
      style={{ "--gap": spacing } as React.CSSProperties}
      className={cn(
        "group/toggle-group flex w-fit items-center gap-[--spacing(var(--gap))] rounded-md data-[spacing=default]:data-[variant=outline]:shadow-xs",
        className
      )}
      {...props}
    >
      <ToggleGroupContext.Provider value={{ variant, size, spacing }}>
        {children}
      </ToggleGroupContext.Provider>
    </ToggleGroupPrimitive.Root>
  )
}

function ToggleGroupItem({
  className,
  children,
  variant,
  size,
  ...props
}: React.ComponentProps<typeof ToggleGroupPrimitive.Item> &
  VariantProps<typeof toggleVariants>) {
  const context = React.useContext(ToggleGroupContext)

  return (
    <ToggleGroupPrimitive.Item
      data-slot="toggle-group-item"
      data-variant={context.variant || variant}
      data-size={context.size || size}
      data-spacing={context.spacing}
      className={cn(
        toggleVariants({
          variant: context.variant || variant,
          size: context.size || size,
        }),
        "w-auto min-w-0 shrink-0 px-3 focus:z-10 focus-visible:z-10",
        "data-[spacing=0]:rounded-none data-[spacing=0]:shadow-none data-[spacing=0]:first:rounded-l-md data-[spacing=0]:last:rounded-r-md data-[spacing=0]:data-[variant=outline]:border-l-0 data-[spacing=0]:data-[variant=outline]:first:border-l",
        className
      )}
      {...props}
    >
      {children}
    </ToggleGroupPrimitive.Item>
  )
}

export { ToggleGroup, ToggleGroupItem }

```
