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.
npx shadcn@latest add https://webberui.com/r/trophy-case.jsonPlayground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<TrophyCase />
Installation
npx shadcn@latest add https://webberui.com/r/trophy-case.jsonOr, 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
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | — | Put TrophyCabinet children directly inside |
columns | number | 3 | Number of columns (how many glass cabinets per row) |
stagger | number | 0.12 | Interval between each cabinet's reveal / unlock (seconds), offsetting them in order |
gap | number | 12 | Gap between glass cabinets (px) |
className | string | — | Class appended to the grid container |
TrophyCabinet
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | — | Achievement name |
requirement | string | — | Description of what it takes to earn it (shown on hover / focus) |
unlocked | boolean | false | Whether it is unlocked: true plays the rise + highlight + confetti, false is a darkened silhouette |
progress | number | 0 | Current progress value (shown as a progress bar together with target while locked) |
target | number | 0 | Target value required to complete it |
icon | React.ReactNode | <Trophy /> | Custom trophy icon |
className | string | — | Class appended to the glass cabinet |
How it works
TrophyCabinetneeds to sit inside aTrophyCase, 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 completearia-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.
Quest Map Section
A winding quest map section — as you scroll, a marker travels the path clearing stations, and each one it reaches pops its content open, raises a flag, and stamps itself complete.
Blueprint Process Section
An engineering-blueprint take on the how-it-works layout — on graph paper, each step is a numbered, annotated station, and as you scroll the dashed leader lines, dimension callouts, and section marks are drawn in order as SVG stroke animations.