caliper uidocs

Swipe tabs

Free

Tabs for touch: swipe the content and the next panel follows the finger while the indicator slides in step.

Installs components/ui/swipe-tabs.tsxDepends on none beyond ReactMotion honours reduced motion
pnpm dlx shadcn@latest add https://caliperui.site/r/swipe-tabs.json
  • Ostra: security review
  • Kestrel: DPA signed
  • Tide Physio: demo booked
  • Priya mentioned you in Halberd renewal
  • Tomás mentioned you in Q4 forecast
  • Price the second Palisade property
  • Send Lumen the annual quote
  • Ostra order form sent

When to use #

Use it for

  • Phone screens with a few sibling views.
  • Feeds and filters people flick between.

Skip it when

  • Desktop settings with many tabs; use tabs.

Installation #

terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/swipe-tabs.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 { SwipeTabs } from "@/components/ui/swipe-tabs"

export function SwipeTabsDemo() {
  const card = (rows: string[]) => (
    <ul className="grid gap-2 p-1">
      {rows.map((row) => <li key={row} className="rounded-[10px] px-3 py-3 text-sm shadow-[inset_0_0_0_1px_var(--border)]">{row}</li>)}
    </ul>
  );
  return (
    <SwipeTabs
      className="w-full max-w-sm"
      label="Inbox views"
      tabs={[
        { id: "all", label: "All", content: card(["Ostra: security review", "Kestrel: DPA signed", "Tide Physio: demo booked"]) },
        { id: "mentions", label: "Mentions", content: card(["Priya mentioned you in Halberd renewal", "Tomás mentioned you in Q4 forecast"]) },
        { id: "assigned", label: "Assigned", content: card(["Price the second Palisade property", "Send Lumen the annual quote"]) },
        { id: "done", label: "Done", content: card(["Ostra order form sent"]) },
      ]}
    />
  );
}

API reference #

SwipeTabs

component
PropTypeDefault
tabs *readonly SwipeTab[]—
label *string—
defaultValuestring—
onValueChange((id: string) => void)—
classNamestring—

Accessibility #

It exposes tab, tablist and tabpanel semantics, with aria-label, aria-selected, aria-controls, aria-hidden and aria-labelledby kept in step with state.

KeyBehaviour
→Moves to the next item or value.
←Moves to the previous item or value.
HomeJumps to the first item or the minimum.
EndJumps to the last item or the maximum.

Motion #

It checks prefers-reduced-motion itself and settles immediately instead of travelling. Every state is still reachable.