پرتوپرتو

اشتباهات رایج

الگوهایی که باید از آن‌ها پرهیز کنید — بر اساس مشکلات واقعی در محصولات پرتو

اشتباهات رایج

این صفحه اشتباهات پرتکرار را که در محصولات پرتو دیده شده‌اند مستند می‌کند. هر آیتم یک نام، توضیح، مشکل، و راه‌حل دارد.


رنگ‌های Hardcode

مشکل: استفاده از رنگ‌های مستقیم Tailwind به جای توکن‌های سیستم.

// ❌ غلط
<span className="text-gray-500">توضیحات</span>
<div className="bg-gray-900 text-white">محتوا</div>
<div style={{ color: '#22c55e' }}>موفقیت</div>

// ✅ درست
<span className="text-muted-foreground">توضیحات</span>
<div className="bg-foreground text-background">محتوا</div>
<span className="text-brand">موفقیت</span>

چرا اشتباه است: رنگ‌های hardcode در تم dark کار نمی‌کنند و WCAG contrast را نقض می‌کنند.


CSS Properties فیزیکی در RTL

مشکل: استفاده از ml، mr، pl، pr، left، right به جای Logical Properties.

// ❌ غلط — در RTL چیدمان معکوس می‌شود
<div className="ml-4 pl-6 border-l-2 text-left">محتوا</div>

// ✅ درست — با RTL و LTR هر دو کار می‌کند
<div className="ms-4 ps-6 border-s-2 text-start">محتوا</div>

چرا اشتباه است: در محیط RTL (فارسی)، ml به چپ اضافه می‌شود اما انتظار داریم به راست اضافه شود.

فیزیکی ❌Logical ✅
ml-*ms-*
mr-*me-*
pl-*ps-*
pr-*pe-*
text-lefttext-start
text-righttext-end

چند دکمه Primary در یک صفحه

مشکل: بیش از یک variant="primary" در یک view.

// ❌ غلط — کاربر نمی‌داند کجا کلیک کند
<div className="flex gap-2">
  <Button variant="primary">ذخیره</Button>
  <Button variant="primary">انتشار</Button>
  <Button variant="primary">پیش‌نویس</Button>
</div>

// ✅ درست — سلسله‌مراتب واضح
<div className="flex gap-2">
  <Button variant="primary">انتشار</Button>
  <Button variant="default">ذخیره</Button>
  <Button variant="outline">پیش‌نویس</Button>
</div>

چرا اشتباه است: primary باید یک عمل اصلی در هر view داشته باشد. وقتی همه چیز مهم است، هیچ چیز مهم نیست.


Dialog به جای Drawer در موبایل

مشکل: استفاده از Dialog در صفحه‌های موبایل که فضای کافی ندارند.

// ❌ غلط — Dialog در موبایل فضای کمی دارد
<Dialog>
  <DialogContent>
    <FilterForm />
  </DialogContent>
</Dialog>

// ✅ درست — Drawer از پایین صفحه باز می‌شود
<Drawer>
  <DrawerContent>
    <FilterForm />
  </DrawerContent>
</Drawer>

راه‌حل بهتر: از responsive pattern استفاده کنید — Dialog در desktop، Drawer در موبایل.


ساختن کامپوننت Domain از صفر

مشکل: ساختن EngagementRate، SentimentBadge، یا SocialPlatformBadge از صفر.

// ❌ غلط — چرخ را دوباره اختراع نکنید
function MyEngagementRate({ rate }: { rate: number }) {
  const color = rate > 5 ? 'green' : rate > 3 ? 'yellow' : 'red'
  return <div style={{ color }}>{rate}%</div>
}

// ✅ درست — استانداردهای دامنه داخل کامپوننت کد شده
import { EngagementRate } from '@parto-system-design/ui'
;<EngagementRate currentRate={0.042} followers={15000} />

کامپوننت‌های domain-specific موجود:

  • EngagementRate — ۵ دسته اینفلوئنسر × ۶ سطح تعامل
  • EngagementRateBar — نوار ساده‌تر
  • SentimentBadge / SentimentDistribution — سه نوع احساس
  • SocialPlatformBadge — ۷ پلتفرم با رنگ برند
  • ProfileCard / ProfileInfo — پروفایل اینفلوئنسر

Compound Component ناقص

مشکل: استفاده از MetricCard، Card، یا Table بدون sub-component های لازم.

// ❌ غلط — MetricCard بدون MetricCardContent
<MetricCard>
  <MetricCardHeader>
    <MetricCardLabel>کاربران</MetricCardLabel>
  </MetricCardHeader>
  <p>۱,۲۳۴</p>
</MetricCard>

// ✅ درست
<MetricCard>
  <MetricCardHeader>
    <MetricCardLabel>کاربران</MetricCardLabel>
  </MetricCardHeader>
  <MetricCardContent>
    <MetricCardValue>۱,۲۳۴</MetricCardValue>
    <MetricCardDifferential variant="positive">+۵٪</MetricCardDifferential>
  </MetricCardContent>
</MetricCard>

Input بدون FormField در react-hook-form

مشکل: استفاده مستقیم از Input در form های react-hook-form بدون FormField.

// ❌ غلط — validation و error message کار نمی‌کند
<form onSubmit={handleSubmit(onSubmit)}>
  <Input {...register('email')} />
</form>

// ✅ درست
<Form {...form}>
  <form onSubmit={form.handleSubmit(onSubmit)}>
    <FormField
      control={form.control}
      name="email"
      render={({ field }) => (
        <FormItem>
          <FormLabel>ایمیل</FormLabel>
          <FormControl><Input {...field} /></FormControl>
          <FormMessage />
        </FormItem>
      )}
    />
  </form>
</Form>

Skeleton با ابعاد اشتباه

مشکل: Skeleton هایی که شکل محتوای واقعی را منعکس نمی‌کنند.

// ❌ غلط — Skeleton با ابعاد random
<Skeleton className="h-4 w-24" />
<Skeleton className="h-4 w-48" />

// ✅ درست — Skeleton شکل محتوای واقعی را تقلید می‌کند
<div className="bg-surface-100 p-4 rounded-lg border space-y-2">
  <div className="flex items-center gap-3">
    <Skeleton className="h-10 w-10 rounded-full" />
    <div className="space-y-2">
      <Skeleton className="h-4 w-32" />
      <Skeleton className="h-3 w-20" />
    </div>
  </div>
  <Skeleton className="h-4 w-full" />
  <Skeleton className="h-4 w-3/4" />
</div>

صفحات مرتبط