Stat Card
Compact metric card with label, value, and an up/down/flat trend chip. Compound and single-prop APIs.
Example
Installation
npx shadcn@latest add https://hirael.com/r/stat-card.jsonUsage
import {
StatCard,
StatCardLabel,
StatCardValue,
StatCardDelta,
} from "@/components/stat-card"Paths assume the default @/ alias from your components.json. The example above shows the parts composed.
API
<StatCard />
+ native element propsNo props of its own; forwards everything to the underlying element.
<StatCardLabel />
+ native element propsNo props of its own; forwards everything to the underlying element.
<StatCardValue />
+ native element propsNo props of its own; forwards everything to the underlying element.
<StatCardDelta />
+ native element props| Prop | Type | Default |
|---|---|---|
trend* | StatCardTrend | none |
children | React.ReactNode | none |
Component source
'use client';
import * as React from 'react';
import { Minus, TrendingDown, TrendingUp } from 'lucide-react';
import { cn } from '@/lib/utils';
export type StatCardTrend = 'up' | 'down' | 'flat';
type StatCardProps = React.ComponentProps<'div'>;
const StatCard = ({ className, ...props }: StatCardProps) => {
return (
<div
data-slot="stat-card"
className={cn('flex flex-col gap-2 rounded-md border border-border bg-card p-5 text-card-foreground', className)}
{...props}
/>
);
};
type StatCardLabelProps = React.ComponentProps<'p'>;
const StatCardLabel = ({ className, ...props }: StatCardLabelProps) => {
return (
<p
data-slot="stat-card-label"
className={cn('font-mono text-[10px] uppercase tracking-[0.12em] text-muted-foreground', className)}
{...props}
/>
);
};
type StatCardValueProps = React.ComponentProps<'p'>;
const StatCardValue = ({ className, ...props }: StatCardValueProps) => {
return (
<p
data-slot="stat-card-value"
className={cn('text-3xl font-semibold tracking-[-0.035em] text-foreground', className)}
{...props}
/>
);
};
interface StatCardDeltaProps extends Omit<React.ComponentProps<'span'>, 'children'> {
trend: StatCardTrend;
children?: React.ReactNode;
}
const StatCardDelta = ({ trend, className, children, ...props }: StatCardDeltaProps) => {
const Icon = trend === 'up' ? TrendingUp : trend === 'down' ? TrendingDown : Minus;
const tone = trend === 'flat' ? 'text-muted-foreground' : 'text-foreground';
return (
<span
data-slot="stat-card-delta"
data-trend={trend}
className={cn(
'inline-flex w-fit items-center gap-1 rounded-sm bg-accent px-1.5 py-0.5 font-mono text-[11px] leading-none',
tone,
className,
)}
{...props}
>
<Icon className="size-3" aria-hidden />
{children}
</span>
);
};
export { StatCard, StatCardLabel, StatCardValue, StatCardDelta };
Dependencies
npm
lucide-react