Leaderboard Podium
trophy/leaderboard-podiumFreeComponent
Top-three React leaderboard podium with crowns, avatars, and ranks for competitive gamification. Leaderboard UI component for highlights and recap screens. Built on shadcn/ui + Tailwind. Open source.
Live preview
live · rendered by the registry
Rendered by trophy on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://ui.trophy.so/r/leaderboard-podium.jsonSource
1"use client"23import * as React from "react"4import { cva, type VariantProps } from "class-variance-authority"5import { Crown } from "lucide-react"67import { cn } from "@/lib/utils"89// Types (inlined)10interface LeaderboardRanking {11 userId: string12 userName: string | null13 rank: number14 value: number15 avatarUrl?: string | null16}1718// Variants19const podiumVariants = cva("flex items-end justify-center gap-4", {20 variants: {21 size: {22 sm: "gap-2",23 default: "gap-4",24 lg: "gap-6",25 },26 },27 defaultVariants: {28 size: "default",29 },30})3132// Podium styles for each position33const PODIUM_CONFIG = {34 1: {35 icon: Crown,36 color: "text-rank-1",37 bg: "bg-rank-1/60",38 ringColor: "ring-rank-1/50",39 height: "h-32",40 heightSm: "h-24",41 heightLg: "h-40",42 },43 2: {44 icon: Crown,45 color: "text-rank-2",46 bg: "bg-rank-2/30",47 ringColor: "ring-rank-2/50",48 height: "h-24",49 heightSm: "h-20",50 heightLg: "h-32",51 },52 3: {53 icon: Crown,54 color: "text-rank-3",55 bg: "bg-rank-3/50",56 ringColor: "ring-rank-3/50",57 height: "h-20",58 heightSm: "h-16",59 heightLg: "h-28",60 },61} as const6263// Props64interface LeaderboardPodiumProps65 extends66 React.HTMLAttributes<HTMLDivElement>,67 VariantProps<typeof podiumVariants> {68 /** Top 3 rankings (expects at least 1, ideally 3) */69 rankings: LeaderboardRanking[]70 /** Show value below name */71 showValue?: boolean72 /** Show avatar */73 showAvatar?: boolean74 /** Crown badge style variant */75 medalStyle?: "classic" | "modern" | "minimal"76}7778const LeaderboardPodium = React.forwardRef<79 HTMLDivElement,80 LeaderboardPodiumProps81>(82 (83 {84 className,85 size,86 rankings,87 showValue = true,88 showAvatar = true,89 medalStyle = "classic",90 ...props91 },92 ref93 ) => {94 // Get top 3, reorder for podium display: 2nd, 1st, 3rd95 const top3 = rankings.slice(0, 3)96 const podiumOrder = [97 top3.find((r) => r.rank === 2),98 top3.find((r) => r.rank === 1),99 top3.find((r) => r.rank === 3),100 ].filter(Boolean) as LeaderboardRanking[]101102 if (podiumOrder.length === 0) {103 return null104 }105106 const avatarSize = {107 sm: "h-10 w-10 text-sm",108 default: "h-14 w-14 text-lg",109 lg: "h-20 w-20 text-2xl",110 }[size ?? "default"]111112 const iconSize = {113 sm: "h-4 w-4",114 default: "h-5 w-5",115 lg: "h-6 w-6",116 }[size ?? "default"]117118 const textSize = {119 sm: "text-xs",120// … truncated
What it pulls in
npm packages
Files it writes
More from trophy
All 18 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Achievement Badgeachievement-badge | trophy | Components | Free | 1 dep | |
| Achievement Cardachievement-card | trophy | Components | Free | no deps | |
| Achievement Gridachievement-grid | trophy | Components | Free | 2 deps | |
| Achievement Listachievement-list | trophy | Components | Free | 2 deps | |
| Achievement Unlockedachievement-unlocked | trophy | Components | Free | 1 dep | |
| Leaderboard Cardleaderboard-card | trophy | Components | Free | no deps | |
| Leaderboard Rankingsleaderboard-rankings | trophy | Components | Free | 2 deps | |
| Points Awardspoints-awards | trophy | Components | Free | 2 deps |
