caliper uidocs

Popover

Free

A small panel anchored to a trigger for quick settings or details.

Installs components/ui/popover.tsxDepends on @radix-ui/react-popoverMotion none in component source
pnpm dlx shadcn@latest add https://caliperui.site/r/popover.json

No reminder yet.

When to use #

Use it for

  • Quick settings that should not leave the page.
  • Content that needs controls inside it.

Skip it when

  • The content is only a label; use a tooltip.
  • The decision blocks everything else; use a dialog.

Installation #

terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/popover.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. It is built from Popover, PopoverTrigger, PopoverClose, PopoverAnchor and PopoverContent.

example.tsx
import { Calendar } from "lucide-react"
import { useState } from "react"
import { Button } from "@/components/ui/button"
import { SegmentedControl } from "@/components/ui/segmented-control"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"

export function QuickSettings() {
  const [open, setOpen] = useState(false);
  const [remind, setRemind] = useState("3");
  const [saved, setSaved] = useState<string | null>(null);
  const dates: Record<string, string> = { "1": "13 Oct", "3": "11 Oct", "7": "7 Oct" };
  return (
    <div className="grid justify-items-center gap-3 pb-40">
      <Popover open={open} onOpenChange={setOpen}>
        <PopoverTrigger asChild>
          <Button variant="secondary" size="sm"><Calendar aria-hidden="true" />Due 14 Oct · remind {remind === "7" ? "1 week" : `${remind} day${remind === "1" ? "" : "s"}`} before</Button>
        </PopoverTrigger>
        <PopoverContent arrow aria-label="Reminder" className="grid gap-3">
          <p className="text-sm font-medium">Remind Ostra Freight</p>
          <SegmentedControl
            label="Remind before"
            value={remind}
            onValueChange={setRemind}
            options={[{ value: "1", label: "1 day" }, { value: "3", label: "3 days" }, { value: "7", label: "1 week" }]}
          />
          <p className="text-xs text-muted-foreground">Sends the invoice again with a pay link on {dates[remind]}.</p>
          <div className="flex justify-end gap-2">
            <Button variant="ghost" size="sm" onClick={() => setOpen(false)}>Cancel</Button>
            <Button size="sm" onClick={() => { setSaved(dates[remind]); setOpen(false); }}>Save reminder</Button>
          </div>
        </PopoverContent>
      </Popover>
      <p role="status" className="text-sm text-muted-foreground">{saved ? `Reminder set for ${saved}, 09:00 in Ostra Freight’s time zone.` : "No reminder yet."}</p>
    </div>
  );
}

API reference #

Popover

component

No props of its own; it accepts the native props of its root element.

PopoverTrigger

component

No props of its own; it accepts the native props of its root element.

PopoverClose

component

No props of its own; it accepts the native props of its root element.

PopoverAnchor

component

No props of its own; it accepts the native props of its root element.

PopoverContent

component

Also accepts the native props of its root element and a ref.

PropTypeDefaultDescription
arrowbooleanfalsePoints at the trigger and follows collision shifts.

Accessibility #

It is built on native elements, so roles and focus come from the browser.

Keyboard and focus handling comes from Radix popover: arrow keys move through items, Enter and Space select, and Escape closes and returns focus.

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.