Rank list
FreeA leaderboard that re-ranks as values change: rows travel to their new place, values count to their new figure, and a mark says how many places each row moved.
pnpm dlx shadcn@latest add https://caliperui.site/r/rank-list.json- Rank 1: Maya OkaforEMEA– no change$182,400
- Rank 2: Jon RuizNA West– no change$176,900
- Rank 3: Inès LaurentEMEA– no change$151,200
- Rank 4: Kai TanakaAPAC– no change$149,800
- Rank 5: Sam PatelNA East– no change$132,050
When to use #
Use it for
- Top accounts, sales leaderboards, fastest-growing pages.
- Rankings that refresh while the page is open.
Skip it when
- Sortable tables people re-order themselves; use the sortable table.
- Rankings that refresh many times a second.
Installation #
pnpm dlx shadcn@latest add https://caliperui.site/r/rank-list.json
Adds its 7 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 #
import { useState } from "react" import { Button } from "@/components/ui/button" import { RankList, type RankItem } from "@/components/ui/rank-list" const reps: RankItem[] = [ { id: "maya", label: "Maya Okafor", meta: "EMEA", value: 182400 }, { id: "jon", label: "Jon Ruiz", meta: "NA West", value: 176900 }, { id: "ines", label: "Inès Laurent", meta: "EMEA", value: 151200 }, { id: "kai", label: "Kai Tanaka", meta: "APAC", value: 149800 }, { id: "sam", label: "Sam Patel", meta: "NA East", value: 132050 }, ]; export function RankListDemo() { const [items, setItems] = useState(reps); const [round, setRound] = useState(1); const update = () => { setRound((r) => r + 1); setItems((list) => list.map((item, i) => ({ ...item, value: item.value + Math.round(((round * 7 + i * 13) % 9) * 5200 * (i === round % 5 ? 3 : 1)) }))); }; return ( <div className="grid w-full max-w-md gap-3"> <div className="flex items-center justify-between"> <span className="text-sm font-medium">Closed-won this quarter</span> <Button size="sm" variant="secondary" onClick={update}>Next update</Button> </div> <RankList label="Sales leaderboard" items={items} format={{ style: "currency", currency: "USD", maximumFractionDigits: 0 }} /> </div> ); }
API reference #
rankItems
component
No props of its own; it accepts the native props of its root element.
RankList
component
Accessibility #
It is built on native elements and keeps aria-label and aria-hidden 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.