Tessina UI
Tessina UI
GitHubIntroduction
InstallationUsageTheming
Components
ButtonIconButtonLinkSpinnerBadgeAvatarStatusChipShortcutSkeletonSurfaceProgressMeterRating
LabelFieldFieldsetCheckboxRadioSwitchSliderSelectComboboxSearchTextareaNumberFieldDate PickerTime PickerOTP InputFile UploadCalendar
AlertBannerToastTooltip
TabsAccordionCollapsibleBreadcrumbPaginationStepperSegmentedControlButtonGroupToggleButtonToggleGroupToolbarNavigation MenuMenubarBottom NavSidebar
Split ButtonFABDropdown MenuContextMenuCommandPopoverHoverCard
ContainerStackFlexGridAspectRatioSpacerCardCarouselDividerScroll Area
Table
ChatBubblePromptInputCodeBlock
ModalAlertDialogDrawerAction SheetTop Header MobileTop Header DesktopEmptyStateForm
Contributing
ComponentsNavigation Blocks

ToggleGroup

A pill container of toggle buttons that act like a radio group (single select) or a multi-select toolbar, built on Base UI's ToggleGroup primitive.

Playground

Installation

pnpm add @tessinaui/ui

Usage

import { ToggleGroup, ToggleGroupItem } from "@tessinaui/ui";
<ToggleGroup variant="outline" size="md" defaultValue={["left"]}>
  <ToggleGroupItem value="left" leadingIcon={<AlignLeft />} label="Left" />
  <ToggleGroupItem value="center" leadingIcon={<AlignCenter />} label="Center" />
  <ToggleGroupItem value="right" leadingIcon={<AlignRight />} label="Right" />
</ToggleGroup>

Showcase

Variants, intents, sizes, orientations, single-vs-multiple, usage patterns, and RTL:

API Reference

ToggleGroup Props

PropTypeDefaultDescription
variant"outline" | "ghost""outline"Visual style applied to all items
intent"none" | "error""none"Semantic color intent applied to all items
size"xs" | "sm" | "md" | "lg" | "xl""md"Size applied to all items
rounded"full" | "lg" | "md" | "sm" | "none""full"Corner radius applied to both the container and every item
orientation"horizontal" | "vertical""horizontal"Layout direction of the group
gap"micro" | "none""micro"Gap between items — micro is 4px (horizontal) / 8px (vertical), none is 0px
multiplebooleanfalseWhen true, multiple items can be pressed at once; when false, at most one item is pressed
valuestring[]—Controlled array of pressed item values
defaultValuestring[][]Initial pressed values for uncontrolled usage
onValueChange(value: string[], event: Event) => void—Callback fired when the pressed set changes
loopFocusbooleantrueWhether arrow-key focus wraps around the group
disabledbooleanfalseDisables every item in the group at once
dir"ltr" | "rtl""ltr"Text direction — RTL reverses icon/label order inside each item

ToggleGroupItem Props

PropTypeDefaultDescription
valuestring—Required. Identifier used in the group's value array when the item is pressed
labelstring—Visible label text
leadingIconReact.ReactNode—Icon rendered before the label; replaced by a spinner when loading
trailingIconReact.ReactNode—Icon rendered after the label; hidden when loading
loadingbooleanfalseShows a spinner and disables this item
disabledbooleanfalseDisables this item individually
aria-labelstring—Accessible label (required when no visible label is provided)

Single vs Multiple

By default ToggleGroup is single-select (multiple={false}) — it behaves like a radio group, pressing a new item unpresses the previous one. The value prop is still an array so both modes share one shape:

// Single select — only one pressed value at a time
const [align, setAlign] = useState<string[]>(["left"]);

<ToggleGroup value={align} onValueChange={setAlign}>
  <ToggleGroupItem value="left"   leadingIcon={<AlignLeft />} />
  <ToggleGroupItem value="center" leadingIcon={<AlignCenter />} />
  <ToggleGroupItem value="right"  leadingIcon={<AlignRight />} />
</ToggleGroup>

Set multiple to let users press any combination:

// Multi select — each item toggles independently
const [format, setFormat] = useState<string[]>([]);

<ToggleGroup multiple value={format} onValueChange={setFormat}>
  <ToggleGroupItem value="bold"      leadingIcon={<Bold />} />
  <ToggleGroupItem value="italic"    leadingIcon={<Italic />} />
  <ToggleGroupItem value="underline" leadingIcon={<Underline />} />
</ToggleGroup>

Supported Combinations

VariantIntents
outlinenone, error
ghostnone, error

Sizes

SizeHeightUse case
xs40pxCompact toolbars
sm48pxSecondary actions
md56pxDefault, most use cases
lg64pxProminent toolbars
xl104pxHero / large controls

Accessibility

The ToggleGroup component:

  • Built on Base UI's ToggleGroup + Toggle primitives
  • Renders a role="group" container with aria-orientation reflecting the orientation prop
  • Each item renders a <button> with aria-pressed reflecting its pressed state
  • Keyboard: Tab focuses the group, Arrow keys move focus between items (with optional wrap via loopFocus), Enter / Space toggles the focused item
  • data-pressed, data-disabled, and data-focus-visible attributes expose state for CSS
  • Focus ring meets WCAG 2.1 AA on each item (2px ring + 2px offset)
  • Touch targets ≥ 44×44px for xs/sm; larger sizes exceed minimum
  • loading sets aria-busy="true" and disables the item
  • disabled (item or group) sets pointer-events-none and the native disabled attribute
  • RTL fully supported via the dir prop

ToggleButton

A button that toggles between on and off states, with the same variant, intent, size, and rounded system as Button. Shows a persistent pressed visual when active.

Toolbar

Container for grouping a set of controls — buttons, toggles, links, inputs, separators. Wraps `@base-ui/react/toolbar` for keyboard focus management. Four variants, three sizes, five rounded values, horizontal (with overflow wrap) + vertical orientation, LTR/RTL.

On this page

PlaygroundInstallationUsageShowcaseAPI ReferenceToggleGroup PropsToggleGroupItem PropsSingle vs MultipleSupported CombinationsSizesAccessibility