caliper uidocs

Expandable action bar

Free

A compact bar of actions that expands to reveal labels.

Installs components/ui/expandable-action-bar.tsxDepends on none beyond ReactMotion none in component source
pnpm dlx shadcn@latest add https://caliperui.site/r/expandable-action-bar.json

Hover or focus the bar.

When to use #

Use it for

  • Message and post actions that should stay quiet until needed.
  • A row of three to five actions.

Skip it when

  • There are more than six actions; use an overflow menu.

Installation #

terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/expandable-action-bar.json

Adds its 2 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.

Usage #

This is the code behind the preview above.

example.tsx
import { Heart, MessageSquare, Star } from "lucide-react"
import { useState } from "react"
import { ExpandableActionBar } from "@/components/ui/expandable-action-bar"

export function PostActions() {
  const [last, setLast] = useState("Hover or focus the bar.");
  return (
    <div className="grid justify-items-center gap-3">
      <ExpandableActionBar
        label="Post actions"
        onAction={(item) => setLast(`${item.label} chosen.`)}
        items={[
          { id: "like", label: "Like", icon: <Heart aria-hidden="true" />, badge: "12" },
          { id: "reply", label: "Reply", icon: <MessageSquare aria-hidden="true" /> },
          { id: "save", label: "Save", icon: <Star aria-hidden="true" /> },
        ]}
      />
      <p role="status" className="text-sm text-muted-foreground">{last}</p>
    </div>
  );
}

API reference #

ExpandableActionBar

component
PropTypeDefault
items *readonly BarAction[]—
label *string—
expandedboolean—
defaultExpandedbooleanfalse
onExpandedChange((expanded: boolean) => void)—
activeIdstring—
onAction((item: BarAction) => void)—
classNamestring—

Accessibility #

It exposes toolbar semantics, with aria-label and aria-pressed kept in step with state.

No custom key handling; Tab and the native activation keys do the work.

Motion #

It declares no animation in its component source. Any transition comes from its stylesheet, which uses the duration tokens that collapse to instant under prefers-reduced-motion.