پرتوپرتو

فضابندی

سیستم فضابندی پرتو — مقیاس ۴px پیش‌فرض Tailwind، spacing tokens، و اصول فاصله‌گذاری

اصول فضابندی

پرتو از مقیاس فضابندی پیش‌فرض Tailwind استفاده می‌کند — واحد پایه ۴px است (space-1) و هر پله مضربی از همان ۴px است، نه صرفاً مضرب ۸. این با کاربرد واقعی خودِ Supabase Studio هم‌خوان است: شمارش مستقیم کلاس‌های gap-*/p-* در apps/studio/components/{ui,layouts} نشان می‌دهد gap-2/p-2 (۸px) پرکاربردترین مقدار است، اما gap-1/p-1 (۴px) و gap-3/p-3 (۱۲px) هم به‌همان اندازه در ردیف اول کاربرد قرار دارند — نه یک استثنای نادر. در عمل، پرتو بین این پله‌ها انتخاب می‌کند:

4px  → space-1
8px  → space-2
12px → space-3
16px → space-4
24px → space-6
32px → space-8
40px → space-10
48px → space-12
64px → space-16

قوانین اجباری

قوانین زیر چکیدهٔ لازم‌الاجرای این صفحه هستند؛ جزئیات و استدلال کامل هر قانون در بخش‌های بعدی همین صفحه آمده است.

فقط پله‌های مقیاس — هرگز مقدار دلخواه

// ✅ درست — پلهٔ استاندارد مقیاس ۴px
<div className="p-4">بازخورد بسته‌بندی</div>

// ❌ غلط — مقدار دلخواه خارج از مقیاس
<div className="p-[13px]">بازخورد بسته‌بندی</div>

مقادیر خارج از مقیاس یکنواختی بصری را می‌شکنند و در چگالی‌های مختلف صفحه‌نمایش (1x/2x/3x DPI) روی پیکسل کامل نمی‌نشینند.

فضابندی جهت‌دار فقط با CSS Logical Properties

// ✅ درست — RTL-safe؛ در هر دو جهت صفحه درست رندر می‌شود
<div className="ps-4 pe-6">رونمایی محصول جدید</div>

// ❌ غلط — physical؛ در RTL جای start و end برعکس می‌شود
<div className="pl-4 pr-6">رونمایی محصول جدید</div>

پرتو RTL-first است؛ کلاس‌های فیزیکی (pl/pr/ml/mr) در چیدمان راست‌به‌چپ وارونه عمل می‌کنند و قانون ESLint parto/no-physical-css-properties آن‌ها را در زمان build خطا می‌دهد.

gap متناسب با سطح سلسله‌مراتب

// ✅ درست — inline با gap-2، فیلدهای فرم با gap-4، سکشن‌ها با gap-8
<div className="flex gap-2">{/* badge ها */}</div>
<div className="flex flex-col gap-4">{/* فیلدهای فرم */}</div>
<div className="flex flex-col gap-8">{/* سکشن‌های صفحه */}</div>

// ❌ غلط — سلسله‌مراتب وارونه؛ badge ها پراکنده و سکشن‌ها چسبیده
<div className="flex gap-8">{/* badge ها */}</div>
<div className="flex flex-col gap-2">{/* سکشن‌های صفحه */}</div>

فاصلهٔ بزرگ‌تر یعنی ارتباط کمتر؛ وقتی پله‌های gap با سطح سلسله‌مراتب هم‌خوان نباشند، چشم گروه‌بندی محتوا را اشتباه می‌خواند.

padding کامپوننت‌ها در محدودهٔ استاندارد

// ✅ درست — padding کارت در محدودهٔ استاندارد p-4 تا p-6
<Card className="p-6">تحلیل گفت‌وگوهای کمپین</Card>

// ❌ غلط — خارج از محدودهٔ استاندارد؛ چگالی صفحه را ناهماهنگ می‌کند
<Card className="p-12">تحلیل گفت‌وگوهای کمپین</Card>

اندازه‌های استاندارد (جدول «اندازه‌های استاندارد کامپوننت» در ادامهٔ همین صفحه) چگالی یکنواختی در کل محصول تضمین می‌کنند؛ کارتی با padding دوبرابر، هم‌ردیف‌های خود را نامتوازن نشان می‌دهد.

فاصلهٔ عمودی متن با یک مقدار واحد روی والد

// ✅ درست — یک space-y-4 روی والد، ریتم یکنواخت بین پاراگراف‌ها
<div className="space-y-4">
  <p>خلاصهٔ بازخورد مشتریان دربارهٔ کمپین تخفیف فصلی</p>
  <p>جمع‌بندی نظرات دربارهٔ بسته‌بندی جدید</p>
</div>

// ❌ غلط — margin دستی و متفاوت روی هر پاراگراف
<div>
  <p className="mb-5">خلاصهٔ بازخورد مشتریان دربارهٔ کمپین تخفیف فصلی</p>
  <p className="mb-2">جمع‌بندی نظرات دربارهٔ بسته‌بندی جدید</p>
</div>

یک مقدار واحد روی والد، ریتم متن را در یک نقطه کنترل می‌کند؛ margin های پراکنده با هر ویرایش از هم فاصله می‌گیرند و یکنواختی را می‌شکنند.


نمونه بصری — مقیاس فضابندی

space-1 / 4px
فاصله خیلی کوچک — بین آیکون و متن
space-2 / 8px
فاصله پایه — gap بین badge ها
space-3 / 12px
فاصله کوچک — gap بین دکمه‌ها
space-4 / 16px
فاصله متوسط — gap بین form field ها
space-6 / 24px
فاصله بزرگ — بین بخش‌های card
space-8 / 32px
فاصله خیلی بزرگ — بین section ها
space-10 / 40px
فاصله page — padding card
space-12 / 48px
فاصله page padding

چرا این مقیاس؟

  • سازگار با اندازه‌های پیکسلی اکثر صفحه‌نمایش‌ها (1x، 2x، 3x DPI)
  • تصمیم‌گیری فضابندی را ساده می‌کند — همیشه از مقیاس استفاده کنید، نه مقدار دلخواه (p-[13px])
  • یکنواختی بصری در سراسر محصول — و همان مقیاسی که Supabase Studio در عمل استفاده می‌کند

padding و margin

padding داخلی کامپوننت‌ها

// padding کوچک — برای badge، tag
<span className="px-2 py-1">...</span>

// padding متوسط — برای button، input
<button className="px-4 py-2">...</button>

// padding بزرگ — برای card، section
<div className="p-6">...</div>

// padding خیلی بزرگ — برای page container
<main className="p-8 md:p-12">...</main>

فاصله بین اجزا (gap)

// gap کوچک — بین badge ها و chip ها
<div className="flex gap-2">...</div>

// gap متوسط — بین button ها
<div className="flex gap-3">...</div>

// gap استاندارد — بین form field ها
<div className="flex flex-col gap-4">...</div>

// gap بزرگ — بین section ها
<div className="flex flex-col gap-8">...</div>

CSS Logical Properties در فضابندی

چون پرتو RTL-first است، از CSS Logical Properties برای فضابندی جهت‌دار استفاده کنید:

// فضابندی جهت‌دار — RTL-safe
<div className="ps-4 pe-6">     {/* padding-inline-start / end */}
<div className="ms-2 me-4">     {/* margin-inline-start / end */}
<div className="border-s-2">    {/* border-inline-start */}

// نه این
<div className="pl-4 pr-6">    {/* physical — در RTL برعکس می‌شود */}

فضابندی در Layout

ساختار صفحه داشبورد

<div className="flex flex-col gap-6 p-6">
  {/* Header */}
  <header className="flex items-center justify-between">
    <h1 className="text-foreground text-2xl font-bold">داشبورد</h1>
    <Button>اقدام</Button>
  </header>

  {/* Metrics Row */}
  <div className="grid grid-cols-4 gap-4">
    <MetricCard />
    <MetricCard />
    <MetricCard />
    <MetricCard />
  </div>

  {/* Main Content */}
  <div className="grid grid-cols-3 gap-6">
    <div className="col-span-2">
      <Card className="p-6">محتوا</Card>
    </div>
    <div>
      <Card className="p-4">جانبی</Card>
    </div>
  </div>
</div>

اندازه‌های استاندارد کامپوننت

padding کنترل‌ها از مقیاس اندازه می‌آید، نه از یک جدول توصیه. جدول قبلیِ این بخش برای دکمهٔ sm مقدار px-3 py-1.5 می‌گفت درحالی‌که مقدار واقعی px-3 py-2 است، و «Button default» را px-4 py-2 می‌نامید که در عمل پلهٔ md است نه پیش‌فرض پروژه. مقیاس کامل و به‌روز در اندازه و چگالی.

آنچه به مقیاسِ کنترل مربوط نیست و اینجا می‌ماند — فاصلهٔ داخلی ظرف‌ها:

ظرفpadding
Cardp-4 تا p-6
Modalp-6
Page sectionpy-8

فضابندی متن

برای خوانایی بهتر متن فارسی:

// line-height مناسب برای فارسی
<p className="leading-relaxed">متن با فاصله خط مناسب</p>

// فاصله بین پاراگراف‌ها
<div className="space-y-4">
  <p>پاراگراف اول</p>
  <p>پاراگراف دوم</p>
</div>

// heading با فاصله مناسب از محتوا
<div>
  <h2 className="text-xl font-semibold mb-3">عنوان</h2>
  <p className="text-light">محتوا</p>
</div>

خلاصه قوانین

قانونمقدار
واحد پایه (اتمی)4px (space-1)
پرکاربردترین پله‌های عملی8px (space-2) و 12px (space-3)
gap بین inline elementsgap-2 یا gap-3
gap بین block elementsgap-4
gap بین section هاgap-6 تا gap-8
padding کارتp-4 تا p-6
padding pagep-6 تا p-8