caliper uidocs

Dynamic island

Free

A compact pill that grows to show one live activity, then collapses.

Installs components/ui/dynamic-island.tsxDepends on none beyond ReactMotion none in component source
pnpm dlx shadcn@latest add https://caliperui.site/r/dynamic-island.json
Workspace ready

When to use #

Use it for

  • Ongoing work like exports and playback.
  • One activity at a time.

Skip it when

  • Several simultaneous activities; use a list.

Installation #

terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/dynamic-island.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 { Upload } from "lucide-react"
import { useState } from "react"
import { Button } from "@/components/ui/button"
import { DynamicIsland } from "@/components/ui/dynamic-island"

export function ExportIsland() {
  const [view, setView] = useState<string | null>(null);
  return (
    <div className="grid justify-items-center gap-4">
      <div className="flex min-h-28 items-start justify-center">
        <DynamicIsland
          label="Export activity"
          view={view}
          compact={<div className="flex items-center gap-2 text-xs"><span className="size-1.5 rounded-full bg-current" />Workspace ready</div>}
        >
          <div className="flex w-64 max-w-full items-center gap-3">
            <Upload size={18} aria-hidden="true" />
            <div>
              <p className="text-sm font-medium">Exporting review notes</p>
              <p className="mt-1 text-xs opacity-70">24% · local preview</p>
            </div>
          </div>
        </DynamicIsland>
      </div>
      <div className="flex gap-2">
        <Button size="sm" variant="secondary" onClick={() => setView("export")}>Show export</Button>
        <Button size="sm" variant="ghost" onClick={() => setView(null)}>Collapse</Button>
      </div>
    </div>
  );
}

API reference #

DynamicIsland

component
PropTypeDefault
label *string—
view *string | null—
compact *ReactNode—
children *ReactNode—
classNamestring—

Accessibility #

It is built on native elements and keeps aria-label 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.