GitHub

Achievement Badge

Open source React achievement badge component with locked/unlocked states, progress rings and rarity support. Use for achievement UI design and collections. Built on shadcn/ui + Tailwind.

The Achievement Badge is the atomic unit of achievement gamification UI—a compact tile users recognize from games and productivity apps, with progress and rarity built in. Compose with Achievement Card and Achievement Grid when you need achievement gamification at scale.

Consistency I

Installation

npx shadcn@latest add https://ui.trophy.so/achievement-badge

Usage

import { AchievementBadge } from "@/components/ui/achievement-badge"
<AchievementBadge
  achievement={{
    id: "1",
    name: "Consistency I",
    trigger: "streak",
    achievedAt: "2024-01-01T00:00:00Z",
    progress: 28,
  }}
/>

Examples

Basic Usage

Consistency I
<AchievementBadge
  achievement={{
    id: "1",
    name: "Consistency I",
    trigger: "streak",
    achievedAt: "2024-01-01T00:00:00Z",
    progress: 28,
  }}
/>

Badge Sizes

Early Bird
Early Bird
Early Bird
Early Bird
<AchievementBadge
  achievement={{
    id: "1",
    name: "Consistency I",
    trigger: "streak",
    achievedAt: "2024-01-01T00:00:00Z",
    progress: 28,
  }}
  badgeSize="sm"
/>
<AchievementBadge
  achievement={{
    id: "1",
    name: "Consistency I",
    trigger: "streak",
    achievedAt: "2024-01-01T00:00:00Z",
    progress: 28,
  }}
  badgeSize="default"
/>
<AchievementBadge
  achievement={{
    id: "1",
    name: "Consistency I",
    trigger: "streak",
    achievedAt: "2024-01-01T00:00:00Z",
    progress: 28,
  }}
  badgeSize="lg"
/>
<AchievementBadge
  achievement={{
    id: "1",
    name: "Consistency I",
    trigger: "streak",
    achievedAt: "2024-01-01T00:00:00Z",
    progress: 28,
  }}
  badgeSize="xl"
/>

Locked State

When achievement.achievedAt is null, the badge is shown in a locked state.

Consistency I
Perfectionist
<AchievementBadge
  achievement={{
    id: "badge-1",
    name: "Consistency I",
    trigger: "streak",
    achievedAt: "2024-01-01T00:00:00Z",
  }}
/>
<AchievementBadge
  achievement={{
    id: "badge-locked-1",
    name: "Perfectionist",
    trigger: "metric",
    achievedAt: null,
  }}
/>

Series Progress

Consistency I
Consistency II
Consistency III
Consistency IV
<AchievementBadge
  achievement={{
    id: "series-1",
    name: "Consistency I",
    trigger: "streak",
    achievedAt: "2024-01-01T00:00:00Z",
    progress: 28,
  }}
/>

Rarity

3% of usersDaily Legend
12% of usersPower User
41% of usersFinisher
78% of usersFirst Win
<AchievementBadge
  achievement={{
    id: "rare-1",
    name: "Daily Legend",
    trigger: "streak",
    achievedAt: "2024-01-01T00:00:00Z",
    rarity: 3,
  }}
/>

Clickable Achievement

Consistency I
<AchievementBadge
  achievement={{
    id: "1",
    name: "Consistency I",
    trigger: "streak",
    achievedAt: "2024-01-01T00:00:00Z",
    progress: 28,
  }}
  onAchievementClick={(achievement) => {
    openDetailModal(achievement)
  }}
/>

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 AchievementBadge props in your UI layer:

const achievement = response[0]

<AchievementBadge achievement={achievement} />

API Reference

PropTypeDefaultDescription
achievementUserAchievementRequiredAchievement data for this badge
badgeSize"sm" | "default" | "lg" | "xl""default"Badge size
onAchievementClick(achievement) => void-Click handler

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
}