Toolbar Button Group
Liquid Glass capsules of toolbar buttons: actions like back and forward, or a set that works like radio buttons, like Finder's view switcher.
"use client"
import {
ChevronLeftIcon,
ChevronRightIcon,
CopyIcon,
PlusIcon,
ShareIcon,
} from "lucide-react"
import {
ToolbarButton,
ToolbarButtonGroup,
ToolbarButtonGroupSeparator,
} from "@/components/ui/toolbar-button-group"
// Safari's capsules: back and forward, and share, new tab and tabs.
export default function ToolbarButtonGroupDemo() {
return (
<div className="flex items-center gap-3">
<ToolbarButtonGroup>
<ToolbarButton aria-label="Back">
<ChevronLeftIcon className="size-5" strokeWidth={2} />
</ToolbarButton>
<ToolbarButtonGroupSeparator />
<ToolbarButton aria-label="Forward" disabled>
<ChevronRightIcon className="size-5" strokeWidth={2} />
</ToolbarButton>
</ToolbarButtonGroup>
<ToolbarButtonGroup>
<ToolbarButton aria-label="Share" className="w-[37px]">
<ShareIcon strokeWidth={1.6} />
</ToolbarButton>
<ToolbarButton aria-label="New Tab" className="w-[37px]">
<PlusIcon strokeWidth={1.6} />
</ToolbarButton>
<ToolbarButton aria-label="Show Tab Overview" className="w-[37px]">
<CopyIcon strokeWidth={1.6} />
</ToolbarButton>
</ToolbarButtonGroup>
</div>
)
}Installation
pnpm dlx shadcn@latest add @cupertinoui-pro/toolbar-button-groupPart of CupertinoUI Pro: the CLI installs it with your license key, once the @cupertinoui-pro registry is in components.json.
Usage
import {
ToolbarButton,
ToolbarButtonGroup,
ToolbarButtonGroupSeparator,
} from "@/components/ui/toolbar-button-group"
<ToolbarButtonGroup>
<ToolbarButton aria-label="Back">
<ChevronLeftIcon />
</ToolbarButton>
<ToolbarButtonGroupSeparator />
<ToolbarButton aria-label="Forward">
<ChevronRightIcon />
</ToolbarButton>
</ToolbarButtonGroup>
<ToolbarButtonGroup type="single" value={view} onValueChange={setView}>
<ToolbarButton value="icons" aria-label="as Icons">
<LayoutGridIcon />
</ToolbarButton>
<ToolbarButton value="list" aria-label="as List">
<ListIcon />
</ToolbarButton>
</ToolbarButtonGroup>Examples
Radio
With type="single" the group works like radio buttons, as in Finder's view switcher: exactly one button is selected and sits on a pill, and clicking it again keeps it selected. Dividers appear between unselected buttons.
"use client"
import * as React from "react"
import {
Columns3Icon,
GalleryThumbnailsIcon,
LayoutGridIcon,
ListIcon,
} from "lucide-react"
import {
ToolbarButton,
ToolbarButtonGroup,
} from "@/components/ui/toolbar-button-group"
const views = [
{ value: "icons", label: "Icons", icon: LayoutGridIcon },
{ value: "list", label: "List", icon: ListIcon },
{ value: "columns", label: "Columns", icon: Columns3Icon },
{ value: "gallery", label: "Gallery", icon: GalleryThumbnailsIcon },
]
// Finder's view switcher: one view is always selected.
export default function ToolbarButtonGroupRadio() {
const [view, setView] = React.useState("columns")
return (
<div className="flex flex-col items-center gap-3">
<ToolbarButtonGroup type="single" value={view} onValueChange={setView} aria-label="View">
{views.map((item) => (
<ToolbarButton key={item.value} value={item.value} aria-label={`as ${item.label}`}>
<item.icon strokeWidth={1.6} />
</ToolbarButton>
))}
</ToolbarButtonGroup>
<p className="text-mac-subheadline text-white/80">
Viewing as {views.find((item) => item.value === view)?.label}
</p>
</div>
)
}Toggles
With type="multiple" each button turns on and off by itself.
"use client"
import { BoldIcon, ItalicIcon, StrikethroughIcon, UnderlineIcon } from "lucide-react"
import {
ToolbarButton,
ToolbarButtonGroup,
} from "@/components/ui/toolbar-button-group"
// Text styles that turn on and off independently.
export default function ToolbarButtonGroupMultiple() {
return (
<ToolbarButtonGroup type="multiple" defaultValue={["bold"]} aria-label="Text Style">
<ToolbarButton value="bold" aria-label="Bold">
<BoldIcon strokeWidth={2} />
</ToolbarButton>
<ToolbarButton value="italic" aria-label="Italic">
<ItalicIcon strokeWidth={2} />
</ToolbarButton>
<ToolbarButton value="underline" aria-label="Underline">
<UnderlineIcon strokeWidth={2} />
</ToolbarButton>
<ToolbarButton value="strikethrough" aria-label="Strikethrough">
<StrikethroughIcon strokeWidth={2} />
</ToolbarButton>
</ToolbarButtonGroup>
)
}API Reference
Every part forwards the props of the underlying Base UI Toggle Group part. The props below are the ones CupertinoUI adds or changes.
ToolbarButtonGroup
Without type, a group of plain buttons. With a type, it takes the props of a Base UI Toggle Group.
| Prop | Type | Description |
|---|---|---|
type | "single" | "multiple" | "single" works like radio buttons: one button is always selected. "multiple" makes every button a toggle. |
value / defaultValue | string | string[] | The selected value, or values with type="multiple". |
onValueChange | (value) => void | Called when the selection changes. With type="single" it never receives an empty value. |
className | string | Extra classes, merged with the component's own. |
ToolbarButton
| Prop | Type | Description |
|---|---|---|
value | string | Identifies the button in a group with a type. |
render | ReactElement | Render another element, e.g. a link, with the button's styles. |
className | string | Extra classes, merged with the component's own. |
ToolbarButtonGroupSeparator
A divider between two plain buttons, e.g. back | forward. Groups with a type draw their own.
| Prop | Type | Description |
|---|---|---|
className | string | Extra classes, merged with the component's own. |