# Awesome Stats
URL: /docs/web/components/awesome-stats
Data-driven metric cards with grid, flex, and animated tabs layouts.
**Demo:**
```tsx
'use client';
// @custom-demo
import { useState } from 'react';
import {
AwesomeStats,
type AwesomeStatItem,
type AwesomeStatsLayout
} from '@docyrus/ui/components/awesome-stats';
import { Button } from '@docyrus/ui/primitives/ui/button';
import {
DollarSign,
Package,
Users
} from 'lucide-react';
type LayoutMode = 'grid' | 'scroll' | 'tabs';
type ClickMode = 'off' | 'card' | 'title';
const DEMO_ITEMS: AwesomeStatItem[] = [
{
id: 'revenue',
eyebrow: 'Growth',
title: 'Monthly revenue',
subtitle: 'Closed won across all active pipelines',
icon: ,
color: 'emerald-500',
value: 2840000,
format: {
style: 'currency',
currency: 'USD',
notation: 'compact',
maximumFractionDigits: 1
},
comparison: {
previousValue: 2470000,
period: 'last-month'
},
menuItems: [
{
id: 'inspect',
label: 'Inspect revenue',
onSelect: stat => console.info('Inspect stat', stat)
},
{
id: 'pin',
label: 'Pin card',
onSelect: stat => console.info('Pin stat', stat)
}
],
miniChart: {
type: 'area',
data: [
1.72,
1.98,
2.14,
2.08,
2.31,
2.54,
2.84
],
dataKey: 'value',
position: 'right'
}
},
{
id: 'accounts',
eyebrow: 'Pipeline',
title: 'Active accounts',
subtitle: 'Paying customers with usage in the last 30 days',
icon: ,
color: 'blue-500',
value: 1284,
format: {
notation: 'compact',
maximumFractionDigits: 1
},
comparison: {
previousValue: 1198,
period: 'last-week'
},
miniChart: {
type: 'sparkline',
data: [
920,
980,
1015,
1090,
1160,
1210,
1284
],
position: 'right'
}
},
{
id: 'returns',
eyebrow: 'Health',
title: 'Return rate',
subtitle: 'Lower is better for this metric',
icon: 'fal rotate-left',
color: 'rose-500',
value: 3.4,
format: {
style: 'percent',
maximumFractionDigits: 1
},
comparison: {
previousValue: 4.2,
period: 'last-month',
positiveDirection: 'down'
},
menuItems: [
{
id: 'benchmark',
label: 'Open benchmark',
onSelect: stat => console.info('Benchmark stat', stat)
},
{
id: 'archive',
label: 'Archive card',
variant: 'destructive',
onSelect: stat => console.info('Archive stat', stat)
}
],
miniChart: {
type: 'area',
data: [
5.1,
4.7,
4.4,
4.2,
4.1,
3.8,
3.4
],
position: 'bottom'
}
},
{
id: 'orders',
eyebrow: 'Ops',
title: 'Fulfilled orders',
subtitle: 'Shipped successfully this week',
icon: ,
color: 'amber-500',
value: 8492,
format: {
notation: 'compact'
},
unitLabel: 'orders',
comparison: {
previousValue: 7784,
period: 'yesterday'
},
miniChart: {
type: 'bar',
data: [
5.8,
6.1,
6.4,
6.2,
7.0,
7.6,
8.49
],
position: 'right'
}
}
];
export function AwesomeStatsDemo() {
const [layoutMode, setLayoutMode] = useState
Card shell
Click target
{lastClicked ? (
Last clicked: {lastClicked}
) : null}
setLastClicked(typeof item.title === 'string' ? item.title : item.id)}
awesomeCardProps={cardVariant === 'awesome' ? {
pattern: true,
patternStyle: 'stripes'
} : undefined} />
);
}
```
## Installation
```bash
pnpm dlx @docyrus/cli add @docyrus/ui-awesome-stats
```
## Usage
```tsx
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'
}
}
];
```
## Layouts
| Layout | Config | Use when |
|--------|--------|----------|
| `grid` | `columns`, optional `maxCardWidth`, optional `gap` | You want a responsive dashboard-style stat grid. |
| `flex` | `cardWidth`, `behavior`, optional `gap` | You need fixed-width cards that either wrap or scroll horizontally. |
| `tabs` | optional `defaultTabId` | You want multiple stats to share a single card surface with animated tab switching. |
## Card Features
| Prop | Purpose |
|------|---------|
| `eyebrow` | Small light label above the title. |
| `icon` | Supports either a React node or a Docyrus icon string such as `"fal chart-line"`. |
| `color` | Tailwind-style color token or raw CSS color used for icon and chart accents. |
| `comparison` | Computes the delta against a previous period and styles it as positive or negative. |
| `miniChart` | Renders `sparkline`, `bar`, or `area` charts at the right edge or docked to the bottom. |
| `unitLabel` | Appends a small unit label next to the formatted value. |
| `sortable` | Enables drag-and-drop reordering for cards and tab items. |
| `onClick` | Per-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:
```tsx
```
## 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:
| `clickTarget` | Behavior |
|---------------|----------|
| `card` (default) | The entire card is clickable — `cursor-pointer` over the whole surface, keyboard-focusable (Enter / Space activate it). |
| `title` | Only the title is clickable and underlines on hover. |
```tsx
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)
}
];
```
The card menu button and drag handle stop propagation, so they never trigger the card/title click handler.