Skip to content
Corsair UI
Browse the docs

ComponentsNo. 61 of 109

Toggle Group

A set of toggles with single or multiple selection, joined or spaced apart.

Installation

pnpm dlx shadcn@latest add @corsair-ui/toggle-group

No setup needed: the CLI finds @corsair-ui in the shadcn registry directory. The files land in your project as source: edit them like your own code. More in Installation.

Also adds
utilstoggle
npm
@radix-ui/react-toggle@radix-ui/react-toggle-groupclass-variance-authorityclsxtailwind-merge

Examples

Single

Arrow keys move between the items.

Multiple

Active: bold

Spaced apart

API

PropTypeDefault
type

One pressed item at a time, or any number.

"single" | "multiple"—
spacing

0 joins the items into one bar.

0 | 1 | 20

Built on Radix Toggle Group; every prop it takes is passed through.

Accessibility

  • A toolbar with one tab stop; arrow keys move between items.
  • Give the group an aria-label.

Compatibility

Tailwind CSS
3.4 and 4, both checked in CI
React
19
Rendering
Client component ("use client")

Source

1 file, installed as source you own
toggle-group.tsxView on GitHub
"use client";

import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
import type { VariantProps } from "class-variance-authority";
import { createContext, useContext, type ComponentProps } from "react";

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

type ToggleGroupStyle = VariantProps<typeof toggleVariants> & {
  /** 0 joins the items into one bar; 1 and 2 space them apart. */
  spacing?: 0 | 1 | 2;
};

const ToggleGroupContext = createContext<ToggleGroupStyle>({
  variant: "default",
  size: "default",
  spacing: 0,
});

/**
 * A set of toggles: `type="single"` works like a radio group that can be
 * cleared, `type="multiple"` like checkboxes. Give it an `aria-label`.
 */
function ToggleGroup({
  className,
  variant,
  size,
  spacing = 0,
  children,
  ...props
}: ComponentProps<typeof ToggleGroupPrimitive.Root> & ToggleGroupStyle) {
  return (
    <ToggleGroupPrimitive.Root
      data-slot="toggle-group"
      data-variant={variant ?? "default"}
      data-size={size ?? "default"}
      data-spacing={spacing}
      className={cn(
        "flex w-fit items-center rounded-md data-[spacing=1]:gap-1 data-[spacing=2]:gap-2",
        className
      )}
      {...props}
    >
      <ToggleGroupContext.Provider value={{ variant, size, spacing }}>
        {children}
      </ToggleGroupContext.Provider>
    </ToggleGroupPrimitive.Root>
  );
}

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

  return (
    <ToggleGroupPrimitive.Item
      data-slot="toggle-group-item"
      data-variant={itemVariant ?? "default"}
      data-size={itemSize ?? "default"}
      data-spacing={context.spacing}
      className={cn(
        toggleVariants({ variant: itemVariant, size: itemSize }),
        "w-auto min-w-0 shrink-0 px-3 focus:z-10 focus-visible:z-10",
        // Joined: only the outer corners are rounded and borders do not double up.
        "data-[spacing=0]:rounded-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 };