GitHub

StatCard

An interactive statistic card for filtering and selection. Designed for dashboard filter controls where clicking cards filters associated data.

StatCard vs StatsBlock

StatCard and StatsBlock serve different purposes:

  • StatCard: Interactive filter control with click handling, active states, and status colors. Use for dashboards where clicking stats filters data.
  • StatsBlock: Display-only statistics grid with optional count-up animations. Use for showcasing metrics without interaction.

Choose StatCard when users need to interact with statistics; choose StatsBlock for read-only displays.

When to Use

Use StatCard when:

  • Statistics act as filter controls for data tables
  • Users need to toggle between different data views
  • Dashboard cards should indicate selected/active state
  • You need semantic status colors (success, warning, destructive)

CMS Demo

Basic Usage

Usage

import { StatCard } from "@corew500/ui"
const [active, setActive] = useState(false)

<StatCard
  label="Active Users"
  value={1234}
  active={active}
  onClick={() => setActive(!active)}
/>

Status Variants

Five status variants for semantic meaning. Click each card to see the active state.

<StatCard label="Total" value={500} status="default" />
<StatCard label="Active" value={342} status="primary" />
<StatCard label="Completed" value={128} status="success" />
<StatCard label="Pending" value={25} status="warning" />
<StatCard label="Failed" value={5} status="destructive" />

DataTable Integration

The primary use case for StatCard is filtering DataTable content. Click stat cards to filter the table below.

Integration Pattern

import { useState, useMemo } from 'react'
import { StatCard, DataTable } from '@corew500/ui'

function Dashboard() {
  const [statusFilter, setStatusFilter] = useState<string | null>(null)

  // Compute counts from data
  const counts = useMemo(() => ({
    completed: data.filter(d => d.status === 'completed').length,
    pending: data.filter(d => d.status === 'pending').length,
  }), [data])

  // Filter data based on selected stat card
  const filteredData = useMemo(() => {
    if (!statusFilter) return data
    return data.filter(d => d.status === statusFilter)
  }, [data, statusFilter])

  const toggleFilter = (status: string) => {
    setStatusFilter(statusFilter === status ? null : status)
  }

  return (
    <>
      <StatCard
        label="Completed"
        value={counts.completed}
        status="success"
        active={statusFilter === 'completed'}
        onClick={() => toggleFilter('completed')}
      />
      <StatCard
        label="Pending"
        value={counts.pending}
        status="warning"
        active={statusFilter === 'pending'}
        onClick={() => toggleFilter('pending')}
      />
      <DataTable columns={columns} data={filteredData} />
    </>
  )
}

Sizes

Three size options for different contexts.

<StatCard label="Small" value={42} size="sm" />
<StatCard label="Default" value={42} size="default" />
<StatCard label="Large" value={42} size="lg" />

With Prefix and Suffix

Display currency, percentages, or units.

<StatCard label="Revenue" value={50} prefix="$" suffix="K" />
<StatCard label="Growth" value={12} suffix="%" />
<StatCard label="Users" value={1.2} suffix="M" />

With Icons

Add icons for visual context.

import { Users, CheckCircle, Clock } from 'lucide-react'

<StatCard
  label="Active Users"
  value={1234}
  status="primary"
  icon={<Users />}
/>
<StatCard
  label="Completed"
  value={89}
  status="success"
  icon={<CheckCircle />}
/>
<StatCard
  label="Pending"
  value={15}
  status="warning"
  icon={<Clock />}
/>

Props

PropTypeDefaultDescription
label*string—The statistic label (e.g., "Active Users")
value*enum—The numeric value to display
prefixstring—Optional prefix (e.g., "$", "+")
suffixstring—Optional suffix (e.g., "%", "K")
activeenumfalseWhether this card is currently active/selected
iconenum—Optional icon to display
statusenumdefault—
sizeenumdefault—

Accessibility

  • Renders as a native <button> element
  • Uses aria-pressed to communicate active state to screen readers
  • Supports keyboard navigation (Tab, Enter, Space)
  • Focus ring visible on keyboard focus
  • Disabled state properly communicated