カード
Stats Card
数値・トレンド・アイコンを表示するダッシュボード向けカード。
インストール
npx shadcn add https://d-ui.daigo-suhara.com/registry/stats-card.jsonサンプル
月間売上
¥1,234,567
+12.5%先月比
使い方
import { StatsCard } from "@/components/ui/stats-card";
import { Users } from "lucide-react";
export default function Example() {
return (
<StatsCard
title="月間ユーザー数"
value="12,540"
trend={8.2}
trendLabel="先月比"
icon={<Users className="h-4 w-4" />}
/>
);
}プロパティ
title必須stringカードのラベル
value必須string | number表示する値
trend必須number前期比(%)
trendLabel必須stringトレンドの補足テキスト
icon必須ReactNodeアイコン
prefix必須string値の前に付く文字
suffix必須string値の後に付く文字
| 名前 | 型 | デフォルト | 説明 | |
|---|---|---|---|---|
| 必須 | title | string | — | カードのラベル |
| 必須 | value | string | number | — | 表示する値 |
| 必須 | trend | number | — | 前期比(%) |
| 必須 | trendLabel | string | — | トレンドの補足テキスト |
| 必須 | icon | ReactNode | — | アイコン |
| 必須 | prefix | string | — | 値の前に付く文字 |
| 必須 | suffix | string | — | 値の後に付く文字 |
ソースコード
import * as React from "react";
import { cn } from "@/lib/utils";
import { TrendingUp, TrendingDown, Minus } from "lucide-react";
interface StatsCardProps {
title: string;
value: string | number;
trend?: number;
trendLabel?: string;
icon?: React.ReactNode;
prefix?: string;
suffix?: string;
className?: string;
}
export function StatsCard({
title,
value,
trend,
trendLabel,
icon,
prefix,
suffix,
className,
}: StatsCardProps) {
const trendDirection =
trend == null ? null : trend > 0 ? "up" : trend < 0 ? "down" : "flat";
return (
<div
className={cn(
"rounded-xl border bg-card p-5 shadow-sm",
className
)}
>
<div className="flex items-start justify-between mb-3">
<p className="text-sm text-muted-foreground font-medium">{title}</p>
{icon && (
<div className="flex h-9 w-9 items-center justify-center rounded-lg bg-primary/10 text-primary">
{icon}
</div>
)}
</div>
<p className="text-3xl font-bold tracking-tight tabular-nums">
{prefix}
{value}
{suffix}
</p>
{trend != null && (
<div className="mt-2 flex items-center gap-1">
{trendDirection === "up" && (
<TrendingUp className="h-3.5 w-3.5 text-emerald-500" />
)}
{trendDirection === "down" && (
<TrendingDown className="h-3.5 w-3.5 text-red-500" />
)}
{trendDirection === "flat" && (
<Minus className="h-3.5 w-3.5 text-muted-foreground" />
)}
<span
className={cn(
"text-xs font-medium",
trendDirection === "up" && "text-emerald-500",
trendDirection === "down" && "text-red-500",
trendDirection === "flat" && "text-muted-foreground"
)}
>
{trend > 0 ? "+" : ""}
{trend}%
</span>
{trendLabel && (
<span className="text-xs text-muted-foreground">{trendLabel}</span>
)}
</div>
)}
</div>
);
}