Components

Awesome Stats

Data-driven metric cards with grid, flex, and animated tabs layouts.

Client Only

Installation

pnpm dlx @docyrus/cli add @docyrus/ui-awesome-stats
UI Primitives(3 components)
npx shadcn@latest add card popover sortable

Usage

import { AwesomeStats } from '@docyrus/ui/components/awesome-stats';

const items = [
  {
    id: 'revenue',
    eyebrow: 'Growth',
    title: 'Monthly revenue',
    value: 2840000,
    format: {
      style: 'currency',
      currency: 'USD',
      notation: 'compact',
      maximumFractionDigits: 1
    },
    comparison: {
      previousValue: 2470000,
      period: 'last-month'
    },
    miniChart: {
      type: 'area',
      data: [1.72, 1.98, 2.14, 2.08, 2.31, 2.54, 2.84],
      position: 'right'
    }
  },
  {
    id: 'returns',
    title: 'Return rate',
    value: 3.4,
    format: { style: 'percent', maximumFractionDigits: 1 },
    comparison: {
      previousValue: 4.2,
      period: 'last-month',
      positiveDirection: 'down'
    },
    miniChart: {
      type: 'bar',
      data: [5.1, 4.7, 4.4, 4.2, 4.1, 3.8, 3.4],
      position: 'bottom'
    }
  }
];

<AwesomeStats
  items={items}
  layout={{
    type: 'grid',
    columns: 2,
    maxCardWidth: 420,
    gap: '1rem'
  }}
/>

Layouts

LayoutConfigUse when
gridcolumns, optional maxCardWidth, optional gapYou want a responsive dashboard-style stat grid.
flexcardWidth, behavior, optional gapYou need fixed-width cards that either wrap or scroll horizontally.
tabsoptional defaultTabIdYou want multiple stats to share a single card surface with animated tab switching.

Card Features

PropPurpose
eyebrowSmall light label above the title.
iconSupports either a React node or a Docyrus icon string such as "fal chart-line".
colorTailwind-style color token or raw CSS color used for icon and chart accents.
comparisonComputes the delta against a previous period and styles it as positive or negative.
miniChartRenders sparkline, bar, or area charts at the right edge or docked to the bottom.
unitLabelAppends a small unit label next to the formatted value.
sortableEnables drag-and-drop reordering for cards and tab items.
onClickPer-item click handler. Takes precedence over the top-level onItemClick.

Awesome Card Mode

Set cardVariant="awesome" to render every stat with AwesomeCard. Use awesomeCardProps for the safe shared subset:

<AwesomeStats
  items={items}
  cardVariant="awesome"
  sortable
  awesomeCardProps={{
    pattern: true,
    patternStyle: 'dots',
    collapsible: false
  }}
  layout={{
    type: 'flex',
    behavior: 'scroll',
    cardWidth: 320
  }}
/>

Clickable Cards

Pass onItemClick to make every card actionable, or set a per-item onClick for individual handlers (per-item wins when both are present). Use clickTarget to choose what the user clicks:

clickTargetBehavior
card (default)The entire card is clickable — cursor-pointer over the whole surface, keyboard-focusable (Enter / Space activate it).
titleOnly the title is clickable and underlines on hover.
<AwesomeStats
  items={items}
  clickTarget="card"
  onItemClick={(item) => router.push(`/metrics/${item.id}`)}
  layout={{ type: 'grid', columns: 2 }}
/>

// Or per-item handlers with a title-only target:
const items = [
  {
    id: 'revenue',
    title: 'Monthly revenue',
    value: 2840000,
    onClick: (item) => openDrawer(item.id)
  }
];

<AwesomeStats items={items} clickTarget="title" layout={{ type: 'grid', columns: 2 }} />

The card menu button and drag handle stop propagation, so they never trigger the card/title click handler.

On this page