Toggle

PreviousNext

A pill-shaped button group where only one option is active at a time, with animated color transitions

Active: Our selection

'use client';
import { useState } from 'react';

import { Toggle } from '@/ui/Toggle';

export function ToggleDemo() {
  const [active, setActive] = useState(0);
  const labels = ['Our selection', 'Exclusive Collection', 'Safari'];

  return (
    <div className="space-y-16">
      <Toggle
        aria-label="Choose a collection"
        items={[
          { color: 'saffron', label: 'Our selection', id: 'id1' },
          { color: 'ultramarine', label: 'Exclusive Collection', id: 'id2' },
          { color: 'sienna', label: 'Safari', id: 'id3' },
        ]}
        index={active}
        onClick={setActive}
      />
      <p className="text-b3">Active: {labels[active]}</p>
    </div>
  );
}

Installation

npx shadcn@latest add https://develop.trident-ui.pro.clubmed/r/toggle.json

Usage

import { Toggle } from '@/ui/Toggle';
 
export function Component() {
  const [active, setActive] = useState(0);
 
  return (
    <Toggle
      index={active}
      onClick={setActive}
      items={[
        { color: 'saffron', label: 'Our selection', id: 'selection' },
        { color: 'ultramarine', label: 'Exclusive Collection', id: 'exclusive' },
        { color: 'sienna', label: 'Safari', id: 'safari' },
      ]}
    />
  );
}

Small size

Use size="small" for a compact variant suited to inline or space-constrained contexts.

Active: Year

'use client';
import { useState } from 'react';

import { Toggle } from '@/ui/Toggle';

export function ToggleSmallDemo() {
  const [active, setActive] = useState(0);
  const labels = ['Year', 'Month'];

  return (
    <div className="space-y-16">
      <Toggle
        aria-label="Choose a period"
        size="small"
        items={[
          { color: 'saffron', label: 'Year', id: 'id1' },
          { color: 'saffron', label: 'Month', id: 'id2' },
        ]}
        index={active}
        onClick={setActive}
      />
      <p className="text-b3">Active: {labels[active]}</p>
    </div>
  );
}

API Reference

Toggle

PropTypeDefaultDescription
itemsItem[][]Required. Array of items to display as buttons.
indexnumber0The index of the currently active item.
onClick(index: number) => voidundefinedCallback fired with the index of the clicked item.
size'default' | 'small''default'Controls button padding and text size. small uses compact padding for inline use.
classNamestringundefinedAdditional CSS classes for the outer container.

Item

PropTypeDefaultDescription
idstring—Required. Unique identifier for the item.
colorColors—Required. Background color applied when the item is active.
labelReactNode—Required. The label rendered inside the button.
classNamestringundefinedAdditional CSS classes for the button.

All other standard button HTML attributes are also accepted per item.

Notes

  • Renders nothing when items is empty
  • Each button exposes aria-pressed for accessibility
  • The active pill background transitions smoothly using a CSS custom property --toggle-color
  • The index prop syncs with an internal useState, so the component works both controlled and uncontrolled