کارت متریک (MetricCard)
کامپوننت نمایش معیارها و آمار به صورت خلاصه با پشتیبانی از نمودار و درصد تغییر
معرفی
کامپوننت Metric Card برای نمایش معیارها و آمارهای مهم به صورت خلاصه استفاده میشود. این کامپوننت شامل عنوان، مقدار، درصد تغییر و نمودار کوچک (Sparkline) است.
چه زمانی استفاده کنیم:
- برای نمایش KPIهای اصلی در داشبورد (بازدید، کاربران فعال، درآمد)
- وقتی نیاز به نمایش روند تغییرات با sparkline دارید
- برای متریکهایی که درصد تغییر نسبت به دوره قبل مهم است
چه زمانی استفاده نکنیم:
- برای نمایش یک عدد ساده بدون sparkline — از
StatDisplayاستفاده کنید - برای مقایسه دو دوره زمانی — از
ComparisonCardاستفاده کنید - برای محتوای عمومی غیرعددی — از
Cardاستفاده کنید
استفاده پایه
کاربران فعال
زمین بازی
با تغییر تنظیمات زیر، کارت متریک را به صورت زنده مشاهده کنید.
بازدید کل
import {
MetricCard,
MetricCardHeader,
MetricCardLabel,
MetricCardContent,
MetricCardValue,
MetricCardDifferential,
MetricCardSparkline,
} from '@partodata/ui'
import { Users } from 'lucide-react'
export default function MyComponent() {
const data = [
{ value: 4000, timestamp: 1735689600 },
{ value: 4200, timestamp: 1735776000 },
{ value: 4100, timestamp: 1735862400 },
// ...
]
return (
<MetricCard>
<MetricCardHeader>
<MetricCardLabel icon={<Users className="h-3.5 w-3.5" />}>کاربران فعال</MetricCardLabel>
</MetricCardHeader>
<MetricCardContent>
<MetricCardValue>4,605</MetricCardValue>
<MetricCardDifferential variant="negative">-0.1%</MetricCardDifferential>
</MetricCardContent>
<MetricCardSparkline data={data} dataKey="value" />
</MetricCard>
)
}حالتهای مختلف
با آیکون و Tooltip
کاربران فعال
import { Users } from 'lucide-react'
;<MetricCard>
<MetricCardHeader>
<MetricCardLabel icon={<Users className="h-3.5 w-3.5" />} tooltip="تعداد کاربران فعال در 24 ساعت گذشته">
کاربران فعال
</MetricCardLabel>
</MetricCardHeader>
<MetricCardContent>
<MetricCardValue>4,605</MetricCardValue>
<MetricCardDifferential variant="positive">+2.5%</MetricCardDifferential>
</MetricCardContent>
<MetricCardSparkline data={data} dataKey="value" />
</MetricCard>با لینک خارجی
درآمد ماهانه
باز کردن لینک<MetricCard>
<MetricCardHeader href="https://example.com/analytics">
<MetricCardLabel>درآمد ماهانه</MetricCardLabel>
</MetricCardHeader>
<MetricCardContent>
<MetricCardValue>۲۵۰ میلیون</MetricCardValue>
<MetricCardDifferential variant="positive">+12.3%</MetricCardDifferential>
</MetricCardContent>
<MetricCardSparkline data={revenueData} dataKey="value" />
</MetricCard>بدون نمودار
کاربران جدید
<MetricCard>
<MetricCardHeader>
<MetricCardLabel>کاربران جدید</MetricCardLabel>
</MetricCardHeader>
<MetricCardContent>
<MetricCardValue>1,234</MetricCardValue>
<MetricCardDifferential variant="positive">+5.2%</MetricCardDifferential>
</MetricCardContent>
</MetricCard>حالت بارگذاری
<MetricCard isLoading={true} />حالت انگلیسی (LTR)
Active Users
<MetricCard dir="ltr">
<MetricCardHeader href="https://example.com">
<MetricCardLabel tooltip="Number of active users in the last 24 hours">Active Users</MetricCardLabel>
</MetricCardHeader>
<MetricCardContent>
<MetricCardValue>4,605</MetricCardValue>
<MetricCardDifferential variant="negative">-0.1%</MetricCardDifferential>
</MetricCardContent>
<MetricCardSparkline data={data} dataKey="value" />
</MetricCard>Props
MetricCard
MetricCardHeader
MetricCardLabel
MetricCardDifferential
MetricCardSparkline
مثالهای کاربردی
داشبورد آنالیتیکس
const metrics = [
{
label: 'کاربران فعال',
value: '4,605',
differential: '-0.1%',
variant: 'negative',
data: activeUsersData,
},
{
label: 'فروش امروز',
value: '۱۲۳ میلیون',
differential: '+5.2%',
variant: 'positive',
data: salesData,
},
{
label: 'نرخ تبدیل',
value: '3.24%',
differential: '+0.8%',
variant: 'positive',
data: conversionData,
},
]
;<div className="grid grid-cols-1 md:grid-cols-3 gap-4" dir="rtl">
{metrics.map((metric) => (
<MetricCard key={metric.label}>
<MetricCardHeader>
<MetricCardLabel>{metric.label}</MetricCardLabel>
</MetricCardHeader>
<MetricCardContent>
<MetricCardValue>{metric.value}</MetricCardValue>
<MetricCardDifferential variant={metric.variant}>{metric.differential}</MetricCardDifferential>
</MetricCardContent>
<MetricCardSparkline data={metric.data} dataKey="value" />
</MetricCard>
))}
</div>با React Query
import { useQuery } from '@tanstack/react-query'
function MetricCardWithQuery() {
const { data, isLoading } = useQuery({
queryKey: ['metrics'],
queryFn: fetchMetrics,
})
return (
<MetricCard isLoading={isLoading}>
<MetricCardHeader>
<MetricCardLabel>کاربران فعال</MetricCardLabel>
</MetricCardHeader>
<MetricCardContent>
<MetricCardValue>{data?.value.toLocaleString('en-US')}</MetricCardValue>
<MetricCardDifferential variant={data?.trend > 0 ? 'positive' : 'negative'}>
{data?.trend > 0 ? '+' : ''}
{data?.trend}%
</MetricCardDifferential>
</MetricCardContent>
<MetricCardSparkline data={data?.history || []} dataKey="value" />
</MetricCard>
)
}نکات مهم
ساختار داده Sparkline
نمودار Sparkline نیاز به آرایهای از داده دارد که هر آیتم شامل:
type SparklineData = {
value: number // مقدار عددی
timestamp: number // Unix seconds؛ مثلا 1735689600
}رنگبندی Differential
variant="positive": سبز (برند) - برای تغییرات مثبتvariant="negative": قرمز (destructive) - برای تغییرات منفی
نمایش علامت مثبت/منفی
محتوای MetricCardDifferential داخل یک span با dir="ltr" رندر میشود؛ بنابراین علامتی که در ابتدای مقدار تایپ میکنید (مثل + یا -) در همان ترتیب و سمت درستِ عدد باقی میماند، حتی داخل کارت RTL. علامت را همانجا که میخواهید در ابتدای children بگذارید:
<MetricCardDifferential variant="negative">-۰.۱٪</MetricCardDifferential>
<MetricCardDifferential variant="positive">+۱۲٪</MetricCardDifferential>اگر میخواهید علامت بهصورت جدا و بعد از مقدار افزوده شود، از prop sign استفاده کنید (کامپوننت علامت را بهطور خودکار درج یا جابهجا نمیکند؛ children دقیقاً همانگونه که پاس میدهید نمایش داده میشود):
<MetricCardDifferential variant="negative" sign="-">
۰.۱٪
</MetricCardDifferential>RTL Support
کامپوننت به طور کامل از RTL پشتیبانی میکند. برای استفاده در محیط انگلیسی، dir="ltr" را به MetricCard اضافه کنید:
<MetricCard dir="ltr">{/* ... */}</MetricCard>وزن مقدار
مقدار (MetricCardValue) با وزن معمولی (font-normal، بههمراه کلاس tabular-nums که در این فونت بیاثر است) رندر میشود، نه پررنگ — مطابق نظم وزنِ فارسیِ سیستم طراحی (Wave G). این کامپوننت همچنان KPIِ تیتر است: عدد بزرگ (text-3xl) اما با وزن سبک، همراه sparkline و differential اختیاری. برای عدد آرام و بدون قاب از InlineStat استفاده کنید.
راهنمای استفاده
بکنید
- همیشه
MetricCardLabelبا tooltip توضیحی همراه کنید تا کاربر متریک را درک کند - برای دادههای async از propisLoadingاستفاده کنید تا layout shift نداشته باشید - در grid layout از تعداد یکسان MetricCard در هر ردیف استفاده کنید
نکنید
- بیش از ۴ MetricCard در یک ردیف قرار ندهید — خوانایی کاهش مییابد - مقادیر را بدون واحد نمایش ندهید — کاربر باید
بداند عدد چه معنایی دارد - از
variant="negative"برای مقادیر مثبت استفاده نکنید — رنگ باید با معنا همخوانی داشته باشد
دسترسیپذیری
MetricCardLabelباtooltipاطلاعات بیشتری را برای صفحهخوانها فراهم میکند- حالت بارگذاری از Skeleton استفاده میکند و layout shift را کاهش میدهد
- رنگبندی differential (سبز/قرمز) جهت روند را نشان میدهد؛ چون کامپوننت آیکون جهتی رندر نمیکند، برای اینکه اطلاعات فقط وابسته به رنگ نباشد علامت
+/-را صریح در children یا با propsignقرار دهید - لینک header نام دسترسپذیر خود را از یک متن پنهان (
sr-only) با محتوای «باز کردن لینک» میگیرد
کامپوننتهای مرتبط
- Card — اگر محتوای شما عمومی است و نیاز به sparkline ندارید، از Card استفاده کنید
- StatDisplay — اگر فقط یک عدد با label نیاز دارید بدون sparkline و differential، از StatDisplay استفاده کنید
- InlineStat — اگر عدد یک واقعیت محیطی و کمرنگ در کنار محتواست (نه KPI تیتر)، از InlineStat استفاده کنید؛ بدون قاب و بدون عدد بزرگشده
- ComparisonCard — اگر نیاز به مقایسه مقادیر دو دوره زمانی دارید، از ComparisonCard استفاده کنید