Skip to Content

Stat Card

A card for displaying metrics with label, value, and optional trend indicator. Built using Box, Column, Row, Icon, and Text components.

Total Users
12,345
+12%vs last month
Revenue
$54,321
-3.2%vs last month

Source

'use client'; import { ArrowDown, ArrowUp, Minus } from 'lucide-react'; import { Box, Column, Icon, Row, Text } from '@umami/react-zen'; export function StatCard({ label, value, change, icon, trend, ...props }) { const trendColor = trend === 'up' ? 'green' : trend === 'down' ? 'red' : 'muted'; const TrendIcon = trend === 'up' ? ArrowUp : trend === 'down' ? ArrowDown : Minus; return ( <Box padding="4" backgroundColor="surface-raised" borderRadius="lg" border borderColor="muted" {...props} > <Column gap="3"> <Row alignItems="center" justifyContent="space-between"> <Text color="muted">{label}</Text> {icon && <Icon size="sm" color="muted">{icon}</Icon>} </Row> <Text size="2xl" weight="semibold">{value}</Text> {change && ( <Row alignItems="center" gap="1"> <Icon size="sm" color={trendColor}><TrendIcon /></Icon> <Text color={trendColor}> {change.value > 0 ? '+' : ''}{change.value}% </Text> {change.label && <Text color="muted">{change.label}</Text>} </Row> )} </Column> </Box> ); } export function StatCardGroup({ children, ...props }) { return ( <Row gap="4" flexWrap="wrap" {...props}> {children} </Row> ); } export function StatCardCompact({ label, value, subValue }) { return ( <Column gap="1"> <Text color="muted" transform="uppercase">{label}</Text> <Row alignItems="baseline" gap="1"> <Text size="xl" weight="semibold">{value}</Text> {subValue && <Text color="muted">{subValue}</Text>} </Row> </Column> ); }

Variations

Compact inline stats

Users
12.3k+12%
Revenue
$54k-3%
Orders
1,234

Without icon

Page Views
45,678
+8.5%
Bounce Rate
32.1%
-2.3%

In a group

Total Sales
$123,456
+15%
Orders
1,234
+8%
Customers
567