GitHub

Achievement List

Vertical React achievement list with icons, descriptions, and optional progress for dense achievement UI. Complements grids and cards in gamification dashboards. Open source, built on shadcn/ui + Tailwind.

Achievement List is built for dense gamification layouts where each row carries a title, supporting text, and progress—ideal for onboarding missions, quest logs, and checklist-style achievement gamification.

10 Day Streak

Open app for 10 days

60%

5,000 Calorie Burn

Burn 5K calories total

32%

Weekend Warrior

Complete challenges on weekends

Installation

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

Usage

import { AchievementList } from "@/components/ui/achievement-list"
<AchievementList
  achievements={[
    {
      id: "list-1",
      name: "10 Day Streak",
      description: "Open app for 10 days",
      trigger: "streak",
      achievedAt: "2024-01-01T00:00:00Z",
      progress: 60,
    },
    {
      id: "list-2",
      name: "5,000 Calorie Burn",
      description: "Burn 5K calories total",
      trigger: "metric",
      achievedAt: "2024-01-01T00:00:00Z",
      progress: 32,
    },
  ]}
/>

Examples

Basic Usage

10 Day Streak

Open app for 10 days

60%

5,000 Calorie Burn

Burn 5K calories total

32%

Weekend Warrior

Complete challenges on weekends

<AchievementList
  achievements={[
    {
      id: "list-1",
      name: "10 Day Streak",
      description: "Open app for 10 days",
      trigger: "streak",
      achievedAt: "2024-01-01T00:00:00Z",
      progress: 60,
    },
    {
      id: "list-2",
      name: "5,000 Calorie Burn",
      description: "Burn 5K calories total",
      trigger: "metric",
      achievedAt: "2024-01-01T00:00:00Z",
      progress: 32,
    },
  ]}
/>

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

<AchievementList achievements={response} />

API Reference

Props

PropTypeDefaultDescription
achievementsUserAchievement[]RequiredArray of achievements to render in list rows
badgeSize"sm" | "default" | "lg""default"Size of badge in each row
lockedStyle"grayscale" | "silhouette" | "hidden""grayscale"Locked achievement visual treatment
onAchievementClick(achievement) => void-Row click handler
columns2 | 3 | 4 | "auto""auto"Supported for compatibility with AchievementGrid
gap"sm" | "default" | "lg""default"Vertical spacing between rows

Types

interface Achievement {
  id: string
  name: string
  description?: string | null
  trigger: "metric" | "api" | "streak"
  badgeUrl?: string | null
  progress?: number // optional, unlocked only
  rarity?: number // accepted but not rendered in list rows
}

interface UserAchievement extends Achievement {
  achievedAt: string | null
}