Skip to main content

Engagement Components

React

Drop-in React components for gamification features with full customization support.

Streak Components

Badges, cards, calendars for streak display

Leaderboard Components

Tables, podiums, mini boards

Achievement Components

Grids, cards, progress, modals

Fully Customizable

Override styles and behavior

Overview

All engagement components are available from @sylphx/sdk/react. They automatically connect to your engagement config and handle data fetching, loading states, and error handling.

import {
  // Streak components
  StreakBadge,
  StreakCard,
  StreakCalendar,

  // Leaderboard components
  LeaderboardTable,
  LeaderboardPodium,
  LeaderboardMini,
  UserRankBadge,

  // Achievement components
  AchievementGrid,
  AchievementCard,
  AchievementBadge,
  AchievementProgress,
  AchievementModal,
  TotalPoints,

  // Hooks (for custom UI)
  useStreak,
  useLeaderboard,
  useAchievements,
  useAchievementProgress,
  useEngagementEvents,
} from '@sylphx/sdk/react'

Streak Components

StreakBadge

Compact streak indicator for headers and profiles:

<StreakBadge streakId="daily_login" />
// Renders: 🔥 7

// With customization
<StreakBadge
  streakId="daily_login"
  showIcon={true}            // Show flame icon (default: true)
  showLabel={false}          // Show "days" label (default: false)
  emptyText="Start streak"   // Text when streak is 0
  className="text-lg"        // Custom classes
/>
PropertyTypeDescription
streakIdrequiredstringID of the streak to display
showIconbooleanShow flame icon (default: true)
showLabelbooleanShow "days" label (default: false)
emptyTextstringText when streak is 0
classNamestringCustom CSS classes

StreakCard

Full-featured streak display with milestone progress:

<StreakCard streakId="daily_login" />

// With all options
<StreakCard
  streakId="daily_login"
  showMilestoneProgress    // Progress bar to next milestone
  showBestStreak           // Display all-time best
  showRecordButton         // Button to record activity
  showRecoveryOption       // Show recovery if streak broken
  onMilestone={(m) => {    // Callback when milestone hit
    celebrate(m)
  }}
  onRecord={(result) => {  // Callback after recording
    console.log('Recorded!', result)
  }}
/>
PropertyTypeDescription
streakIdrequiredstringID of the streak
showMilestoneProgressbooleanShow progress bar to next milestone
showBestStreakbooleanDisplay all-time best streak
showRecordButtonbooleanInclude button to record activity
showRecoveryOptionbooleanShow recovery UI if streak was broken
onMilestone(milestone: number) => voidCallback when milestone is reached
onRecord(result: StreakResult) => voidCallback after recording activity

StreakCalendar

Monthly calendar showing active days:

<StreakCalendar
  streakId="daily_login"
  month={new Date()}
/>

// With customization
<StreakCalendar
  streakId="daily_login"
  month={new Date()}
  highlightMilestones      // Mark milestone days
  showWeekNumbers          // Show week numbers
  startOnMonday            // Start week on Monday (default: Sunday)
  activeClassName="bg-primary"    // Class for active days
  milestoneClassName="ring-2"     // Class for milestone days
/>

Leaderboard Components

LeaderboardTable

Full leaderboard table with pagination:

<LeaderboardTable leaderboardId="weekly_points" />

// With all options
<LeaderboardTable
  leaderboardId="weekly_points"
  limit={20}                // Entries per page
  highlightUser             // Highlight current user's row
  showPercentile            // Show percentile for user
  showAvatar                // Show user avatars
  showChange                // Show rank change (↑ ↓)
  stickyHeader              // Keep header visible on scroll
  onUserClick={(userId) => {  // Click handler for rows
    router.push(`/profile/${userId}`)
  }}
/>
PropertyTypeDescription
leaderboardIdrequiredstringID of the leaderboard
limitnumberEntries per page (default: 20)
highlightUserbooleanHighlight current user
showPercentilebooleanShow percentile for current user
showAvatarbooleanShow user avatars
showChangebooleanShow rank change indicators
stickyHeaderbooleanKeep header visible on scroll
onUserClick(userId: string) => voidClick handler for rows

LeaderboardPodium

Visual podium display for top 3:

<LeaderboardPodium leaderboardId="weekly_points" />

// Customization
<LeaderboardPodium
  leaderboardId="weekly_points"
  showScore                 // Show scores under names
  showAvatar                // Show user avatars
  animated                  // Animate on load
  size="lg"                 // sm, md, lg
/>

LeaderboardMini

Compact leaderboard for sidebars:

<LeaderboardMini
  leaderboardId="weekly_points"
  entries={5}               // Number of entries to show
/>

// With current user's rank
<LeaderboardMini
  leaderboardId="weekly_points"
  entries={5}
  showUserRank              // Always show current user's rank
/>

UserRankBadge

Display current user's rank:

<UserRankBadge leaderboardId="weekly_points" />
// Renders: "#5 of 847 (Top 1%)"

<UserRankBadge
  leaderboardId="weekly_points"
  showPercentile            // Show percentile (default: true)
  showTotal                 // Show total entries (default: true)
  compact                   // Compact mode: just "#5"
/>

Achievement Components

AchievementGrid

Grid display of all achievements:

<AchievementGrid />

// With all options
<AchievementGrid
  groupByCategory           // Group by category
  groupByTier               // Group by tier (bronze, silver, etc.)
  showProgress              // Show progress bars for progress-based
  showLocked                // Show locked achievements (default: true)
  hideSecrets               // Hide secret achievements entirely
  columns={4}               // Number of columns
  onAchievementClick={(id) => {
    showAchievementDetail(id)
  }}
/>
PropertyTypeDescription
groupByCategorybooleanGroup achievements by category
groupByTierbooleanGroup achievements by tier
showProgressbooleanShow progress bars for progress-based achievements
showLockedbooleanShow locked achievements (default: true)
hideSecretsbooleanHide secret achievements entirely
columnsnumberNumber of grid columns
onAchievementClick(id: string) => voidClick handler

AchievementCard

Single achievement card:

<AchievementCard achievementId="power_user" />

// Customization
<AchievementCard
  achievementId="power_user"
  size="lg"                 // sm, md, lg
  showDescription           // Show description text
  showPoints                // Show point value
  showProgress              // Show progress if applicable
  showUnlockDate            // Show when unlocked
/>

AchievementBadge

Compact badge icon:

<AchievementBadge achievementId="power_user" />

// Array of badges (e.g., for profile)
<div className="flex gap-1">
  <AchievementBadge achievementId="first_steps" />
  <AchievementBadge achievementId="power_user" />
  <AchievementBadge achievementId="centurion" />
</div>

AchievementProgress

Progress bar for progress-based achievements:

<AchievementProgress achievementId="centurion" />

// Customization
<AchievementProgress
  achievementId="centurion"
  showLabel                 // Show "45/100" label
  showPercentage            // Show "45%" label
  height="sm"               // sm, md, lg bar height
  color="primary"           // primary, success, warning
/>

AchievementModal

Celebration modal shown on unlock:

// Add to your layout - shows automatically when achievements unlock
<AchievementModal />

// With customization
<AchievementModal
  autoShow                  // Auto-show on unlock (default: true)
  celebrationDuration={3000}  // Confetti duration in ms
  showPoints                // Show points earned
  showShare                 // Show share button
  onClose={() => {}}        // Close callback
  onShare={(achievement) => {  // Share callback
    shareToSocial(achievement)
  }}
/>

TotalPoints

Display user's total achievement points:

<TotalPoints />
// Renders: "🏅 450 points"

<TotalPoints
  showIcon={false}          // Hide medal icon
  showLabel={false}         // Just show number
  className="text-2xl font-bold"
/>

Custom UI with Hooks

Build completely custom UIs using the underlying hooks:

'use client'

import { useStreak } from '@sylphx/sdk/react'

function CustomStreakUI() {
  const {
    streak,           // StreakData | null
    recordActivity,   // () => Promise<StreakResult>
    recoverStreak,    // () => Promise<RecoveryResult>
    isLoading,        // boolean
    error,            // Error | null
  } = useStreak('daily_login')

  // streak shape:
  // {
  //   current: number,
  //   best: number,
  //   recordedToday: boolean,
  //   lastActivityAt: Date | null,
  //   canRecover: boolean,
  //   nextMilestone: number | null,
  //   progressToMilestone: number,  // 0-100
  // }

  return (
    <div>
      <p>Current: {streak?.current}</p>
      <p>Best: {streak?.best}</p>
      <p>Next milestone: {streak?.nextMilestone}</p>
      <button
        onClick={recordActivity}
        disabled={streak?.recordedToday}
      >
        Check In
      </button>
    </div>
  )
}

Styling & Theming

All components support custom styling via className props and CSS variables:

// Method 1: className prop
<StreakCard
  streakId="daily_login"
  className="bg-gradient-to-r from-orange-500 to-red-500"
/>

// Method 2: CSS variables (global theming)
:root {
  --sylphx-streak-color: #f97316;
  --sylphx-achievement-bronze: #b87333;
  --sylphx-achievement-silver: #c0c0c0;
  --sylphx-achievement-gold: #ffd700;
  --sylphx-achievement-platinum: #e5e4e2;
  --sylphx-leaderboard-highlight: hsl(var(--primary));
}

// Method 3: Component variants (if using @sylphx/ui)
<StreakCard
  variant="gradient"      // 'default' | 'gradient' | 'minimal'
  colorScheme="orange"    // 'default' | 'orange' | 'green' | 'purple'
/>

// Method 4: Fully custom with hooks
const { streak } = useStreak('daily_login')
return <MyCustomStreakComponent data={streak} />

Tailwind Integration

All components are built with Tailwind CSS and follow your app's design tokens. They automatically adapt to light/dark mode.