Metric Cards
12 blocksMetric Card 01
Preview
npx nateui@latest add MetricCardTrendDark
import Card from '@/components/ui/Card'
import { AreaChart } from '@/components/composites/Chart'
import { PiClock } from 'react-icons/pi'
const sessionTrend = [
{ day: 'Mon', value: 24 },
{ day: 'Tue', value: 18 },
{ day: 'Wed', value: 30 },
{ day: 'Thu', value: 26 },
{ day: 'Fri', value: 40 },
{ day: 'Sat', value: 34 },
{ day: 'Sun', value: 29 },
]
const MetricCardTrend = () => {
return (
<Card className="mx-auto w-full max-w-sm overflow-hidden">
<div className="flex items-end gap-4">
<div className="min-w-0 flex-1">
<div className="flex items-center gap-2">
<PiClock className="text-lg" />
<span>Average Session / Day</span>
</div>
<h4 className="mt-4 text-xl font-semibold">3.6 hrs</h4>
</div>
<div className="w-32 shrink-0 sm:w-36 ">
<AreaChart
data={sessionTrend}
height={60}
chartHorizontalSpace={0}
chartVerticalSpace={0}
xAxisConfig={{ dataKey: 'day', hide: true }}
yAxisConfig={{ domain: [0, 'dataMax + 15'] }}
cartesianGridConfig={{ horizontal: false, vertical: false }}
areaConfig={[
{
dataKey: 'value',
name: 'Session',
stroke: 'var(--color-chart-1)',
fill: 'url(#metricCardTrendFill)',
strokeWidth: 2,
},
]}
>
<defs>
<linearGradient id="metricCardTrendFill" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="var(--color-chart-1)" stopOpacity={0.35} />
<stop offset="95%" stopColor="var(--color-chart-1)" stopOpacity={0} />
</linearGradient>
</defs>
</AreaChart>
</div>
</div>
</Card>
)
}
export default MetricCardTrend
Metric Card 02
Preview
npx nateui@latest add MetricCardProgressDark
import Card from '@/components/ui/Card'
import Button from '@/components/ui/Button'
import Tooltip from '@/components/ui/Tooltip'
import SegmentProgressBar from '@/components/composites/SegmentProgressBar'
import GrowShrinkTag from '@/components/composites/GrowShrinkTag'
import { PiInfo } from 'react-icons/pi'
const MetricCardProgress = () => {
return (
<Card className="mx-auto w-full max-w-sm">
<div className="flex items-start justify-between gap-4">
<h6 className="text-base font-medium">Active Listings</h6>
<Tooltip title="Count of products currently active in your catalog.">
<Button
variant="ghost"
shape="circle"
size="sm"
icon={<PiInfo className="text-lg" />}
aria-label="About active listings"
/>
</Tooltip>
</div>
<div className="mt-4 flex items-baseline justify-between gap-4">
<div className="flex items-baseline gap-2">
<h4 className="text-xl font-semibold">150</h4>
<GrowShrinkTag
value={4.5}
suffix="%"
className="border bg-transparent"
/>
</div>
<p className="shrink-0 text-right leading-none">
<span className="font-semibold">80%</span>{' '}
<span className="text-muted-foreground">of goal</span>
</p>
</div>
<SegmentProgressBar
className="mt-2"
segments={36}
percent={80}
height={28}
filledClass="bg-success"
gap={2}
/>
</Card>
)
}
export default MetricCardProgress
Metric Card 03
Preview
npx nateui@latest add MetricCardIconMenuDark
import Card from '@/components/ui/Card'
import Button from '@/components/ui/Button'
import Dropdown from '@/components/ui/Dropdown'
import IconFrame from '@/components/composites/IconFrame'
import GrowShrinkTag from '@/components/composites/GrowShrinkTag'
import { PiChartLineUp, PiDotsThreeOutlineVerticalFill } from 'react-icons/pi'
const MetricCardIconMenu = () => {
return (
<Card className="mx-auto w-full max-w-sm">
<div className="flex items-start justify-between">
<IconFrame variant="layered">
<PiChartLineUp className="text-xl" />
</IconFrame>
<Dropdown
placement="bottom-end"
renderTitle={
<Button
variant="ghost"
size="sm"
icon={<PiDotsThreeOutlineVerticalFill />}
aria-label="Metric options"
/>
}
>
<Dropdown.Item>View details</Dropdown.Item>
<Dropdown.Item>Export CSV</Dropdown.Item>
</Dropdown>
</div>
<p className="mt-4">Signups ยท 24h</p>
<div className="mt-1 flex items-baseline justify-between gap-4">
<h4 className="text-xl font-semibold">3,200</h4>
<div className="flex items-center gap-1">
<GrowShrinkTag
value={32}
suffix="%"
className="gap-1 border-0 bg-transparent p-0 text-sm font-semibold"
/>
<span className="text-sm text-muted-foreground">vs prior month</span>
</div>
</div>
</Card>
)
}
export default MetricCardIconMenu
Metric Card 04
Preview
npx nateui@latest add MetricCardTrendWideDark
import Card from '@/components/ui/Card'
import GrowShrinkTag from '@/components/composites/GrowShrinkTag'
import { AreaChart } from '@/components/composites/Chart'
const revenueTrend = [
{ day: 1, value: 38 },
{ day: 2, value: 44 },
{ day: 3, value: 36 },
{ day: 4, value: 50 },
{ day: 5, value: 45 },
{ day: 6, value: 54 },
{ day: 7, value: 48 },
{ day: 8, value: 60 },
{ day: 9, value: 55 },
{ day: 10, value: 64 },
]
const MetricCardTrendWide = () => {
return (
<Card className="mx-auto w-full max-w-sm overflow-hidden" bodyClass="p-0">
<div className="p-4">
<p>Net Sales</p>
<h4 className="mt-4 text-xl font-semibold">$84,200</h4>
<div className="mt-1 flex items-center gap-1">
<GrowShrinkTag
value={12.4}
suffix="%"
prefix="+"
className="gap-1 border-0 bg-transparent p-0 text-sm font-semibold"
/>
<span className="text-sm text-muted-foreground">month over month</span>
</div>
</div>
<AreaChart
data={revenueTrend}
height={80}
chartHorizontalSpace={0}
chartVerticalSpace={0}
xAxisConfig={{ dataKey: 'day', hide: true }}
yAxisConfig={{ domain: ['dataMin - 10', 'dataMax + 5'] }}
cartesianGridConfig={{ horizontal: false, vertical: false }}
areaConfig={[
{
dataKey: 'value',
name: 'Sales',
stroke: 'var(--color-success)',
fill: 'url(#metricCardTrendWideFill)',
strokeWidth: 2,
},
]}
>
<defs>
<linearGradient id="metricCardTrendWideFill" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="var(--color-success)" stopOpacity={0.35} />
<stop offset="95%" stopColor="var(--color-success)" stopOpacity={0} />
</linearGradient>
</defs>
</AreaChart>
</Card>
)
}
export default MetricCardTrendWide
Metric Card 05
Preview
npx nateui@latest add MetricCardStatsSummaryDark
import StatisticCard from '@/components/composites/StatisticCard'
import Button from '@/components/ui/Button'
import Tooltip from '@/components/ui/Tooltip'
import GrowShrinkTag from '@/components/composites/GrowShrinkTag'
import { PiFileText, PiInfo, PiLink } from 'react-icons/pi'
const MetricCardStatsSummary = () => {
return (
<StatisticCard
inset
className="mx-auto w-full max-w-md"
footer={
<div className="grid grid-cols-1 gap-2 p-2 sm:grid-cols-2">
<div className="flex items-center gap-2">
<PiFileText className="text-base" />
<span>Tracked Keywords: 812</span>
</div>
<div className="flex items-center gap-2">
<PiLink className="text-base" />
<span>Indexed Pages: 96</span>
</div>
</div>
}
>
<div className="flex items-center gap-1.5">
<h6 className="text-base font-medium">Search Visibility</h6>
<Tooltip title="Summary of your organic search visibility for the selected period.">
<Button
variant="ghost"
shape="circle"
size="sm"
icon={<PiInfo />}
aria-label="About search visibility"
/>
</Tooltip>
</div>
<div className="mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2">
<div>
<p>Impression Share</p>
<div className="mt-1 flex items-baseline gap-2">
<h4 className="text-xl font-semibold">5.2K</h4>
<GrowShrinkTag
value={5.4}
suffix="%"
className="bg-card border"
/>
</div>
<p className="mt-1 text-xs text-muted-foreground font-medium">Rank #14 of 300</p>
</div>
<div>
<p>Avg. Position</p>
<div className="mt-1 flex items-baseline gap-2">
<h4 className="text-xl font-semibold">2.4</h4>
<GrowShrinkTag
value={2.6}
suffix="%"
className="bg-card border"
/>
</div>
<p className="mt-1 text-xs text-muted-foreground font-medium">Rank #8 of 300</p>
</div>
</div>
</StatisticCard>
)
}
export default MetricCardStatsSummary
Metric Card 06
Preview
npx nateui@latest add MetricCardIconValueDark
import Card from '@/components/ui/Card'
import IconFrame from '@/components/composites/IconFrame'
import { PiWallet } from 'react-icons/pi'
const MetricCardIconValue = () => {
return (
<Card className="mx-auto w-full max-w-sm">
<div className="flex items-start justify-between gap-4">
<span>Payout Balance</span>
<IconFrame className="border-0 bg-palette-purple-soft text-palette-purple-soft-foreground">
<PiWallet className="text-xl" />
</IconFrame>
</div>
<h4 className="mt-4 text-xl font-semibold">
$3,982.00
</h4>
<p className="text-sm text-muted-foreground">Previous month: $3,410.00</p>
</Card>
)
}
export default MetricCardIconValue
Metric Card 07
Preview
npx nateui@latest add MetricCardTargetSummaryDark
import Card from '@/components/ui/Card'
import Progress from '@/components/ui/Progress'
import IconFrame from '@/components/composites/IconFrame'
import Divider from '@/components/composites/Divider'
import GrowShrinkTag from '@/components/composites/GrowShrinkTag'
import { PiCurrencyCircleDollar } from 'react-icons/pi'
const summaryRows = [
{ label: 'Profit margin', value: '39.6%' },
{ label: 'Subscription revenue', value: '$1.94M' },
{ label: 'Median deal size', value: '$28.6K' },
]
const MetricCardTargetSummary = () => {
return (
<Card className="mx-auto w-full max-w-sm" bodyClass="p-0">
<div className="p-4">
<div className="flex items-center gap-2">
<IconFrame size={48}>
<PiCurrencyCircleDollar className="text-2xl" />
</IconFrame>
<div>
<h6 className="text-base font-semibold">Net Revenue</h6>
<p className="text-muted-foreground">Q2 2026</p>
</div>
</div>
<div className="mt-8 flex items-center gap-2">
<h4 className="text-xl font-semibold">$3.18M</h4>
<GrowShrinkTag value={9.8} suffix="%" />
</div>
<div className="mt-2 flex items-center justify-between gap-4 text-sm">
<span>Quarterly goal: $3.6M</span>
<span className="font-semibold">88%</span>
</div>
<Progress
className="mt-2"
percent={88}
showInfo={false}
/>
</div>
<Divider className="my-0" />
<div className="space-y-2 p-4">
{summaryRows.map((row) => (
<div key={row.label} className="flex items-center justify-between gap-4">
<span>{row.label}</span>
<span className="font-semibold">{row.value}</span>
</div>
))}
</div>
</Card>
)
}
export default MetricCardTargetSummary
Metric Card 08
Preview
npx nateui@latest add MetricCardChannelBreakdownDark
import StatisticCard from '@/components/composites/StatisticCard'
import IconFrame from '@/components/composites/IconFrame'
import { PiCursorClickFill } from 'react-icons/pi'
const channelRows = [
{ label: 'Newsletter', value: '6%' },
{ label: 'Push notifications', value: '22%' },
{ label: 'SMS alerts', value: '9%' },
]
const MetricCardChannelBreakdown = () => {
return (
<StatisticCard
inset
className="mx-auto w-full max-w-sm"
header={
<div className="flex items-center gap-2 -ml-2 py-0.5">
<IconFrame
size={28}
className="border-0 bg-palette-orange text-white"
>
<PiCursorClickFill />
</IconFrame>
<span className="font-medium">Engagements</span>
</div>
}
>
<div className="flex items-baseline justify-between gap-4">
<h4 className="text-xl font-semibold">18%</h4>
<span className="text-sm font-semibold text-destructive">-2.85%</span>
</div>
<div className="mt-4 space-y-2">
{channelRows.map((row) => (
<div key={row.label} className="flex items-center justify-between gap-4 text-sm">
<span className="text-muted-foreground">{row.label}</span>
<span className="font-medium">{row.value}</span>
</div>
))}
</div>
</StatisticCard>
)
}
export default MetricCardChannelBreakdown
Metric Card 09
Preview
npx nateui@latest add MetricCardInsightDark
import { useState } from 'react'
import Card from '@/components/ui/Card'
import Button from '@/components/ui/Button'
import Dropdown from '@/components/ui/Dropdown'
import { PiArrowUpRight, PiCaretDown, PiSparkle } from 'react-icons/pi'
const periodOptions = ['This week', 'This month', 'This quarter']
const MetricCardInsight = () => {
const [period, setPeriod] = useState<string>(periodOptions[0])
return (
<Card className="relative mx-auto w-full max-w-sm overflow-hidden">
<div className="relative">
<div className="flex items-center justify-between gap-4">
<div className="flex items-center gap-2">
<PiSparkle className="text-lg" />
<span className="font-medium">Insight</span>
</div>
<Dropdown
placement="bottom-end"
activeKey={period}
onSelect={(eventKey) => setPeriod(eventKey)}
menuClass="min-w-40"
renderTitle={
<Button
variant="default"
size="sm"
icon={<PiCaretDown />}
iconAlignment="end"
>
{period}
</Button>
}
>
{periodOptions.map((option) => (
<Dropdown.Item key={option} eventKey={option}>
{option}
</Dropdown.Item>
))}
</Dropdown>
</div>
<div className="mt-4 flex items-start gap-2">
<h4 className="text-xl font-semibold">92%</h4>
<PiArrowUpRight className="text-xl text-success" />
</div>
<p className="mt-4">
Your engagement is <span className="font-semibold">trending upward</span>{' '}
this week.
</p>
<p className="mt-2 text-sm text-muted-foreground">
Active users are following a similar pattern to last week, with steady
day-over-day growth across most channels.
</p>
</div>
</Card>
)
}
export default MetricCardInsight
Metric Card 10
Preview
npx nateui@latest add MetricCardStatusBreakdownDark
import Card from '@/components/ui/Card'
import GrowShrinkTag from '@/components/composites/GrowShrinkTag'
const breakdown = [
{ label: 'To Do', value: 40, colorClass: 'bg-palette-cyan' },
{ label: 'In Progress', value: 30, colorClass: 'bg-palette-blue' },
{ label: 'In Review', value: 20, colorClass: 'bg-palette-purple' },
{ label: 'Completed', value: 10, colorClass: 'bg-palette-rose' },
]
const MetricCardStatusBreakdown = () => {
return (
<Card className="mx-auto w-full max-w-md">
<p className="text-sm text-muted-foreground">Tickets</p>
<div className="mt-1 flex items-center gap-2">
<h4 className="text-xl font-semibold">18,240</h4>
<GrowShrinkTag value={21.6} suffix="%" />
</div>
<div className="mt-6 flex h-2 gap-0.5">
{breakdown.map((segment) => (
<div
key={segment.label}
className={`h-full rounded-full ${segment.colorClass}`}
style={{ width: `${segment.value}%` }}
/>
))}
</div>
<div className="mt-4 grid grid-cols-2 gap-4 sm:grid-cols-4">
{breakdown.map((segment) => (
<div key={segment.label}>
<p className="text-sm text-muted-foreground">{segment.label}</p>
<div className="mt-1 flex items-center gap-1.5">
<span
className={`size-2 shrink-0 rounded-full ${segment.colorClass}`}
/>
<span className="font-semibold">{segment.value}%</span>
</div>
</div>
))}
</div>
</Card>
)
}
export default MetricCardStatusBreakdown
Metric Card 11
Preview
npx nateui@latest add MetricCardKpiStripDark
import Card from '@/components/ui/Card'
import Tooltip from '@/components/ui/Tooltip'
import { AreaChart } from '@/components/composites/Chart'
import {
PiArrowDown,
PiArrowUp,
PiCurrencyCircleDollar,
PiHexagon,
PiInfo,
PiSparkle,
PiUsers,
} from 'react-icons/pi'
import type { ComponentType, SVGProps } from 'react'
type Panel = {
label: string
chartName: string
tooltip: string
icon: ComponentType<SVGProps<SVGSVGElement>>
value: string
trend: 'up' | 'down'
data: Array<{ x: number; value: number }>
}
const panels: Panel[] = [
{
label: 'Active Customers',
chartName: 'Customers',
tooltip: 'Total number of active customer accounts.',
icon: PiUsers,
value: '1,204',
trend: 'up',
data: [40, 45, 42, 50, 55, 52, 60].map((value, x) => ({ x, value })),
},
{
label: 'New Signups',
chartName: 'Signups',
tooltip: 'New customer signups this period.',
icon: PiSparkle,
value: '98',
trend: 'down',
data: [50, 45, 52, 48, 53, 47, 50].map((value, x) => ({ x, value })),
},
{
label: 'Sales Revenue',
chartName: 'Revenue',
tooltip: 'Total revenue generated from orders.',
icon: PiCurrencyCircleDollar,
value: '$22,150',
trend: 'up',
data: [30, 35, 40, 42, 48, 52, 58].map((value, x) => ({ x, value })),
},
{
label: 'Affiliate Leads',
chartName: 'Leads',
tooltip: 'Leads generated through affiliate referrals.',
icon: PiHexagon,
value: '47',
trend: 'up',
data: [45, 50, 42, 48, 44, 50, 46].map((value, x) => ({ x, value })),
},
]
const MetricCardKpiStrip = () => {
return (
<Card className="w-full" bodyClass="p-0">
<div className="grid grid-cols-1 divide-y md:grid-cols-4 md:divide-x md:divide-y-0">
{panels.map((panel) => {
const Icon = panel.icon
const TrendIcon = panel.trend === 'up' ? PiArrowUp : PiArrowDown
const gradientId = `metricCardKpiStripFill-${panel.label.replace(/\s+/g, '')}`
return (
<div key={panel.label} className="p-4">
<div className="flex items-center gap-1.5">
<Icon className="text-base" />
<span className="font-medium">{panel.label}</span>
<Tooltip
title={panel.tooltip}
tabIndex={0}
aria-label={`About ${panel.label}`}
>
<PiInfo className="text-muted-foreground" />
</Tooltip>
</div>
<div className="mt-3 flex items-center justify-between gap-2">
<div className="flex items-center gap-1">
<span className="text-lg font-semibold">{panel.value}</span>
<TrendIcon
className={
panel.trend === 'up'
? 'text-success'
: 'text-destructive'
}
/>
</div>
<div className="h-10 w-16 shrink-0">
<AreaChart
data={panel.data}
height={40}
chartHorizontalSpace={0}
chartVerticalSpace={2}
xAxisConfig={{ dataKey: 'x', hide: true }}
yAxisConfig={{ domain: ['dataMin - 5', 'dataMax + 5'] }}
cartesianGridConfig={{ horizontal: false, vertical: false }}
areaConfig={[
{
dataKey: 'value',
name: panel.chartName,
stroke: 'var(--color-chart-1)',
fill: `url(#${gradientId})`,
strokeWidth: 1.5,
},
]}
>
<defs>
<linearGradient
id={gradientId}
x1="0"
y1="0"
x2="0"
y2="1"
>
<stop
offset="5%"
stopColor="var(--color-chart-1)"
stopOpacity={0.3}
/>
<stop
offset="95%"
stopColor="var(--color-chart-1)"
stopOpacity={0}
/>
</linearGradient>
</defs>
</AreaChart>
</div>
</div>
</div>
)
})}
</div>
</Card>
)
}
export default MetricCardKpiStrip
Metric Card 12
Preview
npx nateui@latest add MetricCardKpiGridDark
import Card from '@/components/ui/Card'
import IconFrame from '@/components/composites/IconFrame'
import GrowShrinkTag from '@/components/composites/GrowShrinkTag'
import {
PiChartBar,
PiCurrencyDollar,
PiPackage,
PiShoppingCartSimple,
} from 'react-icons/pi'
import type { ComponentType, SVGProps } from 'react'
type Metric = {
label: string
icon: ComponentType<SVGProps<SVGSVGElement>>
iconClass: string
value: string
delta: { prefix: string; value: number; suffix: string }
}
const metrics: Metric[] = [
{
label: 'Gross Revenue',
icon: PiCurrencyDollar,
iconClass: 'bg-palette-orange',
value: '$312.8K',
delta: { prefix: '+$', value: 18.4, suffix: 'K' },
},
{
label: 'Units Shipped',
icon: PiPackage,
iconClass: 'bg-palette-blue',
value: '9,540',
delta: { prefix: '+', value: 820, suffix: '' },
},
{
label: 'Orders Placed',
icon: PiShoppingCartSimple,
iconClass: 'bg-palette-emerald',
value: '6,180',
delta: { prefix: '+', value: 512, suffix: '' },
},
{
label: 'Signup Rate',
icon: PiChartBar,
iconClass: 'bg-palette-purple',
value: '3.92%',
delta: { prefix: '+', value: 0.18, suffix: '%' },
},
]
const MetricCardKpiGrid = () => {
return (
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4">
{metrics.map((metric) => {
const Icon = metric.icon
return (
<Card key={metric.label}>
<div className="flex items-center gap-2">
<IconFrame size={32} className={`border-0 text-white ${metric.iconClass}`}>
<Icon className="text-lg" />
</IconFrame>
<span className="font-medium">{metric.label}</span>
</div>
<h4 className="mt-4 text-xl font-semibold">{metric.value}</h4>
<div className="mt-2 flex items-center gap-1 text-sm">
<GrowShrinkTag
prefix={metric.delta.prefix}
value={metric.delta.value}
suffix={metric.delta.suffix}
className="gap-1 border-0 bg-transparent p-0 font-semibold"
/>
<span className="text-muted-foreground">vs previous month</span>
</div>
</Card>
)
})}
</div>
)
}
export default MetricCardKpiGrid