تایپوگرافی

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

مقیاس

دو تفاوت با Tailwind: پلهٔ text-2xs تازه است، و text-sm از ۱۴px به ۱۳px آمده چون بدنهٔ واقعیِ رابط‌های فارسی همین است. بقیهٔ پله‌ها دست‌نخورده‌اند.

text-2xs۱۱pxدیگ، دیزاین سیستم فارسیریزنویسیِ جدول، شمارهٔ ردیف، متادیتای فرعی
text-xs۱۲pxدیگ، دیزاین سیستم فارسیلیبل، زیرنویس، بج
text-sm۱۳pxدیگ، دیزاین سیستم فارسیبدنهٔ رابط کاربری، پیش‌فرض فرم و جدول
text-base۱۶pxدیگ، دیزاین سیستم فارسیمتن خواندنی و پاراگرافِ مستندات
text-lg۱۸pxدیگ، دیزاین سیستم فارسیتیتر کارت و بخش
text-xl۲۰pxدیگ، دیزاین سیستم فارسیتیتر صفحه
text-2xl۲۴pxدیگ، دیزاین سیستم فارسیتیتر بزرگ
text-3xl۳۰pxدیگ، دیزاین سیستم فارسیتیتر صفحهٔ فرود

تیترها با tracking-heading جمع‌تر می‌شوند (-0.01em)؛ در فارسی تیترِ درشت با فاصلهٔ حروفِ پیش‌فرض شل به نظر می‌رسد.

نقش‌ها

پله‌های بالا خام‌اند. در کد این‌ها را بنویسید، نه پله را: نقش می‌گوید «این متن چه کاره است»، و اگر فردا مقیاس عوض شود همه‌جا با هم عوض می‌شود. هر نقش با clamp بین موبایل و دسکتاپ سیّال است. لیبل و ریزنویسی عمداً سیّال نیستند، چون در جدول فشرده بزرگ‌شدنشان با عرض صفحه چیدمان را به‌هم می‌ریزد.

text-captionریزنویسیشمارهٔ ردیف، متادیتای فرعی، برچسب کلید
text-labelلیبللیبل فرم، سرستون جدول، بج
text-descriptionتوضیحزیرنویسِ عنوان، راهنمای زیر فیلد
text-bodyبدنهمتن اصلی فرم و جدول و کارت
text-subheadingزیرعنوانعنوان گروه در فرم
text-headingعنوانتیتر کارت و بخش
text-titleتیتر صفحهتنها h1 هر صفحه
text-displayدرشتصفحهٔ فرود و حالت خالیِ بزرگ

فاصلهٔ دید در موبایل، دسکتاپ و تلویزیون

موبایل و دسکتاپ هر دو از فاصلهٔ بازو خوانده می‌شوند و تفاوتشان را خودِ clamp می‌گیرد. تلویزیون فرق دارد: از سه متری دیده می‌شود و همان ۱۳px ناخواناست، پس کل مقیاس باید بزرگ شود نه فقط تیترها.

این با عرض صفحه فعال نمی‌شود. وسوسه‌کننده است که بگوییم «۱۹۲۰ یعنی تلویزیون»، ولی ۱۹۲۰ رایج‌ترین مانیتور دسکتاپ است و عرض چیزی دربارهٔ فاصلهٔ دید نمی‌گوید. پس یک پیچ صریح است که اپلیکیشن خودش می‌چرخاند، همان نقطهٔ اتصالِ آمادهٔ حالت «متن بزرگ» برای کاربر کم‌بینا.

app/globals.css
:root { --font-scale: 1.35 }   /* تلویزیون، فاصلهٔ سه متری */

لنگر فونت: گذاشتنِ فونتِ پروژه

فونت هم مثل رنگ سه لایه دارد: پروژه فقط لنگر را عوض می‌کند، نه توکن معنایی را و نه زنجیرهٔ جایگزین را. یعنی ایران‌سنس، وزیرمتن، ایران‌یکان یا هر فونت دیگری، همه با یک خط.

app/layout.tsx
import localFont from "next/font/local"

const iranSans = localFont({
  variable: "--font-iransans",
  display: "swap",
  src: [
    { path: "./fonts/IRANSansXFaNum-Regular.ttf", weight: "400", style: "normal" },
    { path: "./fonts/IRANSansXFaNum-Medium.ttf", weight: "500", style: "normal" },
    { path: "./fonts/IRANSansXFaNum-DemiBold.ttf", weight: "600", style: "normal" },
    { path: "./fonts/IRANSansXFaNum-Bold.ttf", weight: "700", style: "normal" },
  ],
})

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="fa" dir="rtl" className={iranSans.variable}>
      <body className="font-sans">{children}</body>
    </html>
  )
}
app/globals.css
/* تنها خطی که برای تعویض فونت عوض می‌شود */
:root {
  --font-anchor: var(--font-iransans), "IRANSansX";
}

فونت گوگلی هم همین‌طور است، کافی است متغیرِ next/font/google را به لنگر بدهید. توکن‌های --font-sans و --font-mono و همهٔ کامپوننت‌ها خودشان دنبال لنگر می‌آیند.

ارقام

هرجا عدد در ستون یا کنار هم می‌نشیند (جدول، مبلغ، ساعت) از tabular-nums استفاده کنید تا ارقام هم‌عرض بمانند و ستون نلرزد. برای تبدیل رقم لاتین به فارسی، ابزارهای persian در دیگ آماده‌اند.