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

ButtonGroup

A group of pill buttons inside a rounded pill container, supporting horizontal and vertical orientations with configurable gap

Playground

Installation

pnpm add @tessinaui/ui

Usage

import { ButtonGroup, ButtonGroupItem } from "@tessinaui/ui";
<ButtonGroup variant="outline" size="md">
  <ButtonGroupItem leadingIcon={<Scissors />} label="Cut" />
  <ButtonGroupItem leadingIcon={<Copy />} label="Copy" />
  <ButtonGroupItem leadingIcon={<Clipboard />} label="Paste" />
</ButtonGroup>

Showcase

All variants, intents, sizes, orientations, and states:

API Reference

ButtonGroup 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
orientation"horizontal" | "vertical""horizontal"Layout direction of the group
gap"micro" | "none""micro"Gap between items — micro is 4px, none is 0px
disabledbooleanfalseDisables all items in the group at once
dir"ltr" | "rtl""ltr"Text direction — RTL reverses icon/label order

ButtonGroupItem Props

PropTypeDefaultDescription
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)
onClickMouseEventHandler—Click handler

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 ButtonGroup component:

  • Renders with role="group" on the wrapper for semantic grouping
  • Requires aria-label on icon-only ButtonGroupItem elements
  • focus-visible:ring-2 focus ring meets WCAG 2.1 AA on each item
  • 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 disabled attribute
  • RTL fully supported via the dir prop

SegmentedControl

A radio-group style control where one segment is selected at a time, with outline, filled, and pill variants, horizontal and vertical orientations, and full keyboard navigation

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.

On this page

PlaygroundInstallationUsageShowcaseAPI ReferenceButtonGroup PropsButtonGroupItem PropsSupported CombinationsSizesAccessibility