پرتوپرتو

کارت متریک (Metric Card)

کامپوننت نمایش معیارها و آمار به صورت خلاصه با پشتیبانی از نمودار و درصد تغییر

معرفی

کامپوننت Metric Card برای نمایش معیارها و آمارهای مهم به صورت خلاصه استفاده می‌شود. این کامپوننت شامل عنوان، مقدار، درصد تغییر و نمودار کوچک (Sparkline) است.

چه زمانی استفاده کنیم:

  • برای نمایش KPIهای اصلی در داشبورد (بازدید، کاربران فعال، درآمد)
  • وقتی نیاز به نمایش روند تغییرات با sparkline دارید
  • برای متریک‌هایی که درصد تغییر نسبت به دوره قبل مهم است

چه زمانی استفاده نکنیم:

  • برای نمایش یک عدد ساده بدون sparkline — از StatDisplay استفاده کنید
  • برای مقایسه دو دوره زمانی — از ComparisonCard استفاده کنید
  • برای محتوای عمومی غیرعددی — از Card استفاده کنید

استفاده پایه

کاربران فعال

۴,۶۰۵
-۰.۱٪

زمین بازی

با تغییر تنظیمات زیر، کارت متریک را به صورت زنده مشاهده کنید.

زمین بازی

بازدید کل

۱۲,۴۵۶
+۱۲.۵٪
تنظیمات
import { MetricCard } from '@parto-system-design/ui'

<MetricCard />
import {
  MetricCard,
  MetricCardHeader,
  MetricCardLabel,
  MetricCardContent,
  MetricCardValue,
  MetricCardDifferential,
  MetricCardSparkline,
} from '@parto-system-design/ui'
import { Users } from 'lucide-react'

export default function MyComponent() {
  const data = [
    { value: 4000, timestamp: '2024-01-01' },
    { value: 4200, timestamp: '2024-01-02' },
    { value: 4100, timestamp: '2024-01-03' },
    // ...
  ]

  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>

با لینک خارجی

درآمد ماهانه

باز کردن لینک
۲۵۰M
+۱۲.۳٪
<MetricCard>
  <MetricCardHeader href="https://example.com/analytics">
    <MetricCardLabel>درآمد ماهانه</MetricCardLabel>
  </MetricCardHeader>
  <MetricCardContent>
    <MetricCardValue>۲۵۰M</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)

4,870
+36.0%
<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

Prop

Type

MetricCardHeader

Prop

Type

MetricCardLabel

Prop

Type

MetricCardDifferential

Prop

Type

MetricCardSparkline

Prop

Type

مثال‌های کاربردی

داشبورد آنالیتیکس

const metrics = [
  {
    label: 'کاربران فعال',
    value: '4,605',
    differential: '-0.1%',
    variant: 'negative',
    data: activeUsersData,
  },
  {
    label: 'فروش امروز',
    value: '۱۲۳M',
    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('fa-IR')}</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: string // زمان (برای reference، در نمودار نمایش داده نمی‌شود)
}

رنگ‌بندی Differential

  • variant="positive": سبز (برند) - برای تغییرات مثبت
  • variant="negative": قرمز (destructive) - برای تغییرات منفی

نمایش علامت مثبت/منفی

علامت مثبت (+) یا منفی (-) به صورت خودکار در سمت چپ عدد نمایش داده می‌شود، حتی در حالت RTL. می‌توانید مقدار را با یا بدون علامت پاس دهید:

// هر دو حالت درست کار می‌کنند:
<MetricCardDifferential variant="negative">-۰.۱٪</MetricCardDifferential>
<MetricCardDifferential variant="negative">۰.۱٪-</MetricCardDifferential>
// هر دو به صورت "-۰.۱٪" نمایش داده می‌شوند

RTL Support

کامپوننت به طور کامل از RTL پشتیبانی می‌کند. برای استفاده در محیط انگلیسی، dir="ltr" را به MetricCard اضافه کنید:

<MetricCard dir="ltr">{/* ... */}</MetricCard>

راهنمای استفاده

بکنید

  • همیشه MetricCardLabel با tooltip توضیحی همراه کنید تا کاربر متریک را درک کند - برای داده‌های async از prop isLoading استفاده کنید تا layout shift نداشته باشید - در grid layout از تعداد یکسان MetricCard در هر ردیف استفاده کنید

نکنید

  • بیش از ۴ MetricCard در یک ردیف قرار ندهید — خوانایی کاهش می‌یابد - مقادیر را بدون واحد نمایش ندهید — کاربر باید بداند عدد چه معنایی دارد - از variant="negative" برای مقادیر مثبت استفاده نکنید — رنگ باید با معنا هم‌خوانی داشته باشد

دسترسی‌پذیری

  • MetricCardLabel با tooltip اطلاعات بیشتری را برای صفحه‌خوان‌ها فراهم می‌کند
  • حالت بارگذاری از Skeleton استفاده می‌کند و layout shift را کاهش می‌دهد
  • رنگ‌بندی differential (سبز/قرمز) با آیکون جهتی ترکیب شده تا وابستگی به رنگ نباشد
  • لینک header از aria-label توصیفی استفاده می‌کند

کامپوننت‌های مرتبط

  • Card — اگر محتوای شما عمومی است و نیاز به sparkline ندارید، از Card استفاده کنید
  • StatDisplay — اگر فقط یک عدد با label نیاز دارید بدون sparkline و differential، از StatDisplay استفاده کنید
  • ComparisonCard — اگر نیاز به مقایسه مقادیر دو دوره زمانی دارید، از ComparisonCard استفاده کنید