Ranking
A leaderboard card for the tops of a dashboard: products, customers or countries. Read it as stacked rows or a vertical bar chart, each row carrying a position chip, a value and a relative-share bar.
Installation#
Usage#
Ranking is composed from named parts, like Card and Stat. The Ranking root owns the surface and variant; RankingList is a semantic <ol> so assistive tech announces the positions, and each RankingItem lays out a rank, content, and value.
import {
Ranking,
RankingHeader,
RankingTitle,
RankingList,
RankingItem,
RankingRank,
RankingContent,
RankingLabel,
RankingValue,
} from "@/components/ui/ranking"
export function TopCategories({ rows }: { rows: { name: string; revenue: string }[] }) {
return (
<Ranking>
<RankingHeader>
<RankingTitle>Top categories</RankingTitle>
</RankingHeader>
<RankingList>
{rows.map((r, i) => (
<RankingItem key={r.name}>
<RankingRank highlight={i === 0}>{i + 1}</RankingRank>
<RankingContent>
<RankingLabel>{r.name}</RankingLabel>
</RankingContent>
<RankingValue>{r.revenue}</RankingValue>
</RankingItem>
))}
</RankingList>
</Ranking>
)
}Media and meta#
Give a row a face. RankingMedia is a tinted icon tile for things (products, countries); for people, drop an Avatar in the same slot. RankingMeta adds a muted second line under the label (a category, an order count) and RankingValue holds the figure in tabular-nums so the column stays aligned.
Relative bars#
RankingBar draws each row’s share of the leader from a value of 0–100, so the list reads as a chart at a glance. The fill width is a runtime value, so it rides a CSS variable (never a generated class) and animates when the data changes.
Vertical bars#
Set layout="bars" to read the same list as a vertical bar chart: RankingList turns into a row of full-height columns and each RankingBar grows from the bottom to its share. The columns are narrow, so lean on the Tooltip and wrap each RankingItem and surface the full detail on hover instead of squeezing it under the bar.
Inline bars#
Set layout="inline" for a horizontal bar chart: the name holds a fixed column and a thick bar runs beside it. The bars rest neutral and the brand is the hover: the bar under the pointer lights up, and so does a bar that takes keyboard focus as a tooltip trigger. Nothing is lit at rest. highlight on a RankingBar pins the brand on one bar, for a row that really is selected; it works in the other layouts too.
Bar tones#
tone sets a bar’s fill: blue, brand, neutral, success, warning, destructive or info, the same names and inks as the Chart’s series, so a Ranking beside a chart can carry its key. Put the leader in the brand and the rest in neutral when the list is about one row, or let a status tone report each row’s health. Set tone on the Ranking to paint every bar at once; a bar’s own tone wins over it, and highlight wins over both. In the inline layout the hovered bar still lights up in the brand.
Headline figure#
When the list breaks down a total, lead with the total. Ranking has no figure part of its own on purpose: the figure is the Stat’s StatValue, which renders outside a Stat, with a StatTrend beside it. Set them between the header and the list, so every card in a dashboard leads with the same figure and the same chip, and the description is free to say what the number counts.
Interactive rows#
Pass interactive to a RankingItem for a clickable row: pointer, a hover wash that bleeds to the card edge, and a focus ring. The wash sits close to the rank chip, media tile, and bar track, so those nested surfaces step down to the card surface on hover to keep their definition instead of dissolving into the wash, while the highlighted leader chip holds its primary fill. Wire it with onClick and add a trailing chevron to signal the affordance.
Variants#
default sits on a hairline border with a soft shadow; outline drops the shadow for flat, gridded dashboards; elevated trades the border for a lifted shadow.
API reference#
Ranking forwards all div props and adds variant (default | outline | elevated), layout (list | bars | inline), tone (every bar’s default hue) and asChild. RankingList renders an <ol>; RankingItem renders an <li> and adds interactive. RankingRank adds highlight for the leader; RankingBar takes a value (0–100), tone (blue | brand | neutral | success | warning | destructive | info) and highlight (a brand fill that wins over the tone). The rest: RankingHeader, RankingTitle, RankingDescription, RankingAction, RankingMedia, RankingContent, RankingLabel, RankingMeta, RankingValue, forward their element props. Every part accepts className, merged last.