Responsive React achievement grid for displaying collections of badges with progress and rarity across breakpoints. Ideal achievement UI design for galleries and showcases in consumer apps. Open source, built on shadcn/ui + Tailwind.
Achievement Grid lays out badge collections in a scannable gamification surface—balanced columns, spacing rhythm, and built-in rarity or completion metadata for trophy rooms and showcase-style achievement gamification.
Installation
npx shadcn@latest add https://ui.trophy.so/achievement-gridUsage
import { AchievementGrid } from "@/components/ui/achievement-grid"<AchievementGrid
achievements={[
{
id: "1",
name: "Early Bird",
trigger: "api",
achievedAt: "2024-01-01T00:00:00Z",
},
{
id: "2",
name: "First Steps",
trigger: "streak",
achievedAt: "2024-01-03T00:00:00Z",
},
{
id: "3",
name: "Task Master",
trigger: "metric",
achievedAt: "2024-01-02T00:00:00Z",
},
]}
/>Examples
Basic Usage
<AchievementGrid
achievements={[
{
id: "1",
name: "Early Bird",
trigger: "api",
achievedAt: "2024-01-01T00:00:00Z",
},
{
id: "2",
name: "First Steps",
trigger: "streak",
achievedAt: "2024-01-03T00:00:00Z",
},
{
id: "3",
name: "Task Master",
trigger: "metric",
achievedAt: "2024-01-02T00:00:00Z",
},
]}
/>Column Layouts
// Fixed columns
<AchievementGrid
achievements={[
{ id: "1", name: "Early Bird", trigger: "api", achievedAt: "2024-01-01T00:00:00Z" },
{ id: "2", name: "First Steps", trigger: "streak", achievedAt: "2024-01-03T00:00:00Z" },
{ id: "3", name: "Task Master", trigger: "metric", achievedAt: "2024-01-02T00:00:00Z" },
]}
columns={2}
/>
<AchievementGrid
achievements={[
{ id: "1", name: "Early Bird", trigger: "api", achievedAt: "2024-01-01T00:00:00Z" },
{ id: "2", name: "First Steps", trigger: "streak", achievedAt: "2024-01-03T00:00:00Z" },
{ id: "3", name: "Task Master", trigger: "metric", achievedAt: "2024-01-02T00:00:00Z" },
]}
columns={3}
/>
<AchievementGrid
achievements={[
{ id: "1", name: "Early Bird", trigger: "api", achievedAt: "2024-01-01T00:00:00Z" },
{ id: "2", name: "First Steps", trigger: "streak", achievedAt: "2024-01-03T00:00:00Z" },
{ id: "3", name: "Task Master", trigger: "metric", achievedAt: "2024-01-02T00:00:00Z" },
]}
columns={4}
/>
// Auto-responsive (default)
<AchievementGrid
achievements={[
{ id: "1", name: "Early Bird", trigger: "api", achievedAt: "2024-01-01T00:00:00Z" },
{ id: "2", name: "First Steps", trigger: "streak", achievedAt: "2024-01-03T00:00:00Z" },
{ id: "3", name: "Task Master", trigger: "metric", achievedAt: "2024-01-02T00:00:00Z" },
]}
columns="auto"
/>
// 2 cols mobile → 3 cols tablet → 4 cols desktop → 5 cols largeGap Sizes
<AchievementGrid
achievements={[
{ id: "1", name: "Early Bird", trigger: "api", achievedAt: "2024-01-01T00:00:00Z" },
{ id: "2", name: "First Steps", trigger: "streak", achievedAt: "2024-01-03T00:00:00Z" },
{ id: "3", name: "Task Master", trigger: "metric", achievedAt: "2024-01-02T00:00:00Z" },
]}
gap="sm"
/>
<AchievementGrid
achievements={[
{ id: "1", name: "Early Bird", trigger: "api", achievedAt: "2024-01-01T00:00:00Z" },
{ id: "2", name: "First Steps", trigger: "streak", achievedAt: "2024-01-03T00:00:00Z" },
{ id: "3", name: "Task Master", trigger: "metric", achievedAt: "2024-01-02T00:00:00Z" },
]}
gap="default"
/>
<AchievementGrid
achievements={[
{ id: "1", name: "Early Bird", trigger: "api", achievedAt: "2024-01-01T00:00:00Z" },
{ id: "2", name: "First Steps", trigger: "streak", achievedAt: "2024-01-03T00:00:00Z" },
{ id: "3", name: "Task Master", trigger: "metric", achievedAt: "2024-01-02T00:00:00Z" },
]}
gap="lg"
/>AchievementGrid composes the AchievementBadge component internally. For visual badge options such as size, progress, rarity, and click handling, see Achievement Badge. Locked badges are determined by achievedAt === null on each item.
Complete Example
<AchievementGrid
achievements={[
{
id: "complete-1",
name: "Consistency I",
trigger: "streak",
achievedAt: "2024-01-01T00:00:00Z",
progress: 28,
},
{
id: "complete-2",
name: "Daily Legend",
trigger: "streak",
achievedAt: "2024-01-01T00:00:00Z",
rarity: 3,
},
{
id: "complete-3",
name: "Power User",
trigger: "metric",
achievedAt: "2024-01-01T00:00:00Z",
rarity: 12,
},
{
id: "complete-4",
name: "Consistency II",
trigger: "streak",
achievedAt: "2024-01-01T00:00:00Z",
progress: 62,
},
]}
columns={4}
onAchievementClick={handleClick}
/>With Trophy
Use the Trophy SDK to fetch a user's achievements server-side:
import { TrophyApiClient } from '@trophyso/node';
const trophy = new TrophyApiClient({
apiKey: 'YOUR_API_KEY'
});
const response = await trophy.users.achievements("user-id");
Then pass the response into AchievementGrid props in your UI layer:
<AchievementGrid achievements={response} />API Reference
AchievementGrid
| Prop | Type | Default | Description |
|---|---|---|---|
achievements | UserAchievement[] | Required | Array of achievements to display |
columns | 2 | 3 | 4 | "auto" | "auto" | Number of grid columns |
gap | "sm" | "default" | "lg" | "default" | Gap between grid items |
badgeSize | "sm" | "default" | "lg" | "default" | Size of achievement badges |
onAchievementClick | (achievement) => void | - | Click handler for achievements |
Types
interface Achievement {
id: string
name: string
trigger: "metric" | "api" | "streak"
badgeUrl?: string | null
progress?: number // optional series progress from 0 to 100, unlocked only
rarity?: number // optional rarity from 1 to 100 shown as "X% of users"
}
interface UserAchievement extends Achievement {
achievedAt: string | null // null = locked
}