Skip to main content
The Progress component displays a circular progress indicator showing completion percentage. It’s used in the Menu component to visualize how many countries in each region have been visited.

Overview

The Progress component:
  • Renders an SVG-based circular progress ring
  • Displays completion as a percentage (0-100%)
  • Supports dark mode theming
  • Includes accessibility attributes
  • Uses memo for performance optimization

Props

interface Props {
  complete: number;
}
complete
number
required
Completion percentage as a decimal between 0 and 1 (e.g., 0.5 = 50%)

Component Signature

export const Progress: FC<Props> = memo(({ complete }) => (
  // Component JSX
));

Usage Example

import { Progress } from './components/progress';

function RegionHeader() {
  return (
    <div>
      <h2>Europe</h2>
      <Progress complete={0.67} /> {/* 67% complete */}
    </div>
  );
}

Visual Representation

The component renders a 20x20px circular progress indicator:
<div className="relative size-5">
  <svg className="-rotate-90 size-full" viewBox="0 0 36 36">
    {/* Background circle */}
    <circle
      cx="18" cy="18" r="16"
      fill="none"
      className="stroke-current text-gray-500"
      strokeWidth="4"
    />
    
    {/* Progress circle */}
    <circle
      cx="18" cy="18" r="16"
      fill="none"
      className="stroke-current text-primary"
      strokeWidth="4"
      strokeDasharray="100"
      strokeDashoffset={(1 - complete) * 100}
      strokeLinecap="round"
    />
  </svg>
</div>

How It Works

SVG Structure

The progress ring consists of two overlapping circles:
  1. Background Circle: Gray circle showing the full ring
  2. Progress Circle: Orange circle that fills based on completion

Progress Calculation

The progress is displayed using SVG stroke properties:
strokeDasharray="100"  // Total circle circumference (normalized to 100)
strokeDashoffset={(1 - complete) * 100}  // Visible portion
Examples:
  • complete = 0strokeDashoffset = 100 → 0% visible
  • complete = 0.5strokeDashoffset = 50 → 50% visible
  • complete = 1strokeDashoffset = 0 → 100% visible

Rotation

The SVG is rotated -90 degrees to start the progress from the top:
<svg className="-rotate-90 size-full">
Without rotation, the progress would start from the right (3 o’clock position).

Styling

The component uses Tailwind CSS for theming:
/* Background circle */
text-gray-500 dark:text-neutral-500

/* Progress circle */
text-primary dark:text-primary
The primary color (#fd7e14 orange) is consistent with the country highlighting on the globe.

Accessibility

The component includes an accessible title that announces the completion percentage:
<svg>
  <title>{Math.round(complete * 1000) / 10}% complete.</title>
  {/* circles */}
</svg>
This ensures screen readers announce the progress value (e.g., “67.5% complete”).

Performance

The component is wrapped with memo() to prevent unnecessary re-renders:
export const Progress: FC<Props> = memo(({ complete }) => (
  // Only re-renders when complete prop changes
));

Examples

Different Completion States

// No progress
<Progress complete={0} />

// Quarter complete
<Progress complete={0.25} />

// Half complete
<Progress complete={0.5} />

// Three quarters complete
<Progress complete={0.75} />

// Fully complete
<Progress complete={1} />

In Region Headers

The Progress component is typically used in region headers within the Menu:
<div className="sticky top-0 bg-zinc-200 dark:bg-zinc-800">
  <h2>{region.name}</h2>
  <Progress complete={region.complete ?? 0} />
</div>

Visual Design

  • Size: 20x20 pixels (size-5 in Tailwind)
  • Stroke Width: 4px
  • Radius: 16 units (in 36x36 viewBox)
  • Gap: Small gap between start and end due to strokeLinecap="round"

Color Scheme

The progress color matches the primary brand color used throughout the application for visual consistency.
ElementLight ModeDark Mode
Backgroundtext-gray-500text-neutral-500
Progresstext-primary (#fd7e14)text-primary (#fd7e14)

Dependencies

  • react - Core React functionality
  • No external libraries required (pure SVG implementation)

Source Code

Location: src/components/progress.tsx

Build docs developers (and LLMs) love