caliper uidocs

Rank list

Free

A 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.

Installs components/ui/rank-list.tsxDepends on none beyond ReactMotion none in component source
pnpm dlx shadcn@latest add https://caliperui.site/r/rank-list.json
Closed-won this quarter
  1. Rank 1: Maya OkaforEMEA– no change$182,400
  2. Rank 2: Jon RuizNA West– no change$176,900
  3. Rank 3: Inès LaurentEMEA– no change$151,200
  4. Rank 4: Kai TanakaAPAC– no change$149,800
  5. 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 #

terminal
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 #

This is the code behind the preview above. It is built from rankItems and RankList.

example.tsx
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
PropTypeDefaultDescription
items *readonly RankItem[]—
label *string—
formatNumberFormatOptions—
unitstring""
limitnumber—Show only the top n.
classNamestring—

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.