WebberUI

Trophy Case

An achievement trophy wall — a grid of glass cabinets displays your achievements; unlocking one raises the trophy, sweeps a highlight across it, and bursts a little confetti, while hovering lets you examine it in 3D and see its requirement and progress.

Loading preview…
npx shadcn@latest add https://webberui.com/r/trophy-case.json

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

3
12
0.12
<TrophyCase />

Installation

npx shadcn@latest add https://webberui.com/r/trophy-case.json

Or, once registries are configured in components.json, install it as @webberui/trophy-case.

Usage

import { TrophyCase, TrophyCabinet } from "@/components/ui/trophy-case";

<TrophyCase columns={3}>
  <TrophyCabinet title="First blood" requirement="Finish your first match" unlocked />
  <TrophyCabinet
    title="Ten in a row"
    requirement="Win 10 matches in a row"
    progress={7}
    target={10}
  />
  <TrophyCabinet title="Veteran" requirement="Play 100 matches in total" unlocked />
</TrophyCase>

An unlocked cabinet plays the "trophy rises → highlight sweeps → confetti bursts" reveal sequence; a locked one shows a darkened silhouette and can display progress toward the goal through progress / target. Flipping unlocked from false to true (controlled) replays that cabinet's unlock celebration.

Props

TrophyCase

PropTypeDefaultDescription
childrenReact.ReactNodePut TrophyCabinet children directly inside
columnsnumber3Number of columns (how many glass cabinets per row)
staggernumber0.12Interval between each cabinet's reveal / unlock (seconds), offsetting them in order
gapnumber12Gap between glass cabinets (px)
classNamestringClass appended to the grid container

TrophyCabinet

PropTypeDefaultDescription
titlestringAchievement name
requirementstringDescription of what it takes to earn it (shown on hover / focus)
unlockedbooleanfalseWhether it is unlocked: true plays the rise + highlight + confetti, false is a darkened silhouette
progressnumber0Current progress value (shown as a progress bar together with target while locked)
targetnumber0Target value required to complete it
iconReact.ReactNode<Trophy />Custom trophy icon
classNamestringClass appended to the glass cabinet

How it works

  • TrophyCabinet needs to sit inside a TrophyCase, which injects the index automatically so the per-cabinet stagger delay can be computed; it still works standalone, but without the stagger effect.
  • Unlocked trophies are rendered in a warm amber tone with a warm glow; locked ones are neutral silhouettes at reduced opacity, with a lock / check badge in the top-right corner marking the state.
  • The progress bar animates from 0 up to its percentage when it enters the viewport; unlocked cabinets always show 100%.

Accessibility

  • When the user has "reduce motion" enabled at the system level, everything renders in its final state (trophy in place, no rise / highlight / confetti), and the tilt and the info panel slide-in are also unanimated.
  • Each cabinet is a focusable role="group" with a complete aria-label (name, unlock state, progress, and requirement), and the info panel is revealed both on hover and on keyboard focus.
  • Purely decorative elements such as the highlight, confetti, glow, and plinth are all marked aria-hidden, so they do not interfere with assistive technology.

On this page