Evgeny Shilov

Stacked Activity Bars

Component 23

About

Want this built into your product? AI agents write the code, an engineer directs them: https://vibecoding.tech/services?utm_source=21st&utm_medium=component Book a call and say promo code 21ST to get a free 3-day development trial. Interactive stacked daily columns with a live legend that doubles as the tooltip; the last, incomplete day is hatched. Answers: "What makes up each day's volume, and how does it breathe day to day?"

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Stacked Activity Bars to your project and fits it to your theme.

Code

How Stacked Activity Bars is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

'use client'

// --- vizcn palette (lib/palette.ts inlined for 21st.dev; canonical registry: https://vibecoding.tech/vizcn) ---
const CATEGORICAL = [
  '#4E79A7', // blue
  '#F28E2B', // orange
  '#59A14F', // green
  '#B07AA1', // purple
  '#76B7B2', // teal
  '#E15759', // red
  '#EDC948', // yellow
  '#FF9DA7', // pink
  '#9C755F', // brown
  '#BAB0AC', // grey
] as const
function seriesColor(i: number): string {
  return CATEGORICAL[((i % CATEGORICAL.length) + CATEGORICAL.length) % CATEGORICAL.length]
}
// --- end palette ---
import { StackedActivityBars, type StackSegment } from '@/components/ui/stacked-activity'

/**
 * Demo: 28 days of token traffic for the fictional model "Atlas" —
 * deterministic waves (no randomness), stacked as prompt / completion /
 * reasoning tokens. The last day is partial and hatched.
 */

const N = 28

function isoDays(startIso: string, count: number): string[] {
  const d = new Date(`${startIso}T00:00:00Z`)
  const out: string[] = []
  for (let i = 0; i < count; i++) {
    out.push(d.toISOString().slice(0, 10))
    d.setUTCDate(d.getUTCDate() + 1)
  }
  return out
}

const days = isoDays('2025-06-01', N)

const wave = (i: number, base: number, a1: number, a2: number) =>
  Math.round((base + a1 * Math.sin(i / 3.1) + a2 * Math.sin(i / 1.4 + 1.7) + i * 0.06) * 100) / 100

const prompt = days.map((_, i) => wave(i, 5.8, 1.6, 0.7))
const completion = days.map((_, i) => wave(i, 2.4, 0.8, 0.4))
const reasoning = days.map((_, i) => wave(i, 1.1, 0.5, 0.25))

// last day is in progress — scale it down to look partial
const partial = (vs: number[]) => vs.map((v, i) => (i === N - 1 ? Math.round(v * 42) / 100 : v))

const segments: StackSegment[] = [
  { key: 'prompt', label: 'Prompt', color: seriesColor(0), values: partial(prompt) },
  { key: 'completion', label: 'Completion', color: seriesColor(1), values: partial(completion) },
  { key: 'reasoning', label: 'Reasoning', color: seriesColor(2), values: partial(reasoning) },
]

export default function StackedActivityDemo() {
  return (
    <StackedActivityBars
      days={days}
      segments={segments}
      unit="B"
      note="Daily token volume for Atlas by request part. Hover a day to pin it in the legend."
      partialLast
      partialNote="partial day"
    />
  )
}

More by Evgeny Shilov

View all
  • Agentic Factory — Interactive 3D Machine

    Agentic Factory — Interactive 3D Machine

    1.2K
  • Leaderboard Table

    Leaderboard Table

    31
  • Frontier Board

    Frontier Board

    25
  • Paired Bars

    Paired Bars

    21
  • Dune Flow

    Dune Flow

    18
  • Treemap

    Treemap

    15
  • Bench Matrix

    Bench Matrix

    13
  • V8 Engine — Interactive 3D

    V8 Engine — Interactive 3D

    12

Explore more

Part of vizcn · by vibecoding.tech — browse the full library on 21st.dev.