Expanding Button Group
A compact pill of icon buttons where hover or focus reveals labels and slides neighbours aside with inline confirmations.
Installation
npx viora-ui@latest add expanding-button-grouppnpm dlx viora-ui@latest add expanding-button-groupnpx viora-ui@latest add expanding-button-groupbunx viora-ui@latest add expanding-button-groupStep 1: Install Dependencies
npm install motion lucide-reactStep 2: Copy the Source Code
Copy expanding-button-group.tsx into your @/components/arc/expanding-button-group/ directory.
Usage
import { Archive, Clock3, Forward, Reply, Trash2 } from "lucide-react";
import { ExpandingButtonGroup } from "@/components/arc/expanding-button-group/expanding-button-group";
export function MessageActions({ message }: { message: { id: string } }) {
return (
<ExpandingButtonGroup
label="Message actions"
defaultExpanded="reply"
items={[
{ id: "reply", label: "Reply", icon: <Reply size={16} />, onSelect: () => openReply(message.id) },
{ id: "forward", label: "Forward", icon: <Forward size={16} />, onSelect: () => openForward(message.id) },
{ id: "archive", label: "Archive", doneLabel: "Archived", icon: <Archive size={16} />, onSelect: () => archive(message.id) },
{ id: "snooze", label: "Snooze", doneLabel: "Snoozed", icon: <Clock3 size={16} />, onSelect: () => snooze(message.id) },
{ id: "delete", label: "Delete", doneLabel: "Deleted", tone: "danger", icon: <Trash2 size={16} />, onSelect: () => moveToTrash(message.id) },
]}
/>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
items | ExpandingButtonGroupItem[] | — | Toolbar action items. |
label | string | — | Accessible name of toolbar. |
size | "sm" | "md" | "md" | Pill size geometry. |
defaultExpanded | string | null | — | Id of the item initially expanded at rest. |
onAction | (id: string) => void | — | Callback fired when any item is triggered. |
confirmDuration | number | 1400 | Duration in ms to display checkmark confirmation. |
Built by Otis
Last updated: 10/12/2026