Files
aragrp/docs/design-system/typography.md
T
ar.badieiandCursor c2376b3b9e
Build & Push Docker Image / build (push) Has been cancelled
feat: redesign landing page with brand system and section blocks
Refresh the homepage around new hero/services/roadmap sections, shared design tokens, and updated brand assets.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 17:00:55 +03:30

5.4 KiB
Raw Blame History

Typography

Persian-first typography system using IRANSansX (FaNum — Persian digits baked into the font). Canonical scale: lib/typography.ts. Prefer type.* classes or <Typography variant="…"> over ad-hoc text-* stacks.

Font family

Role Stack
Sans (UI) IRANSansX, system-ui, sans-serif
Mono ui-monospace, SF Mono, Menlo, Consolas, monospace

Loaded via @font-face in app/globals.css. Body applies font-family: "IRANSansX" with text-align: start (right in RTL).

Global base

Element Line height Letter spacing Alignment
body 1.75 normal start
h1–h6 1.45 normal start
p 1.8 normal start

Tracking is almost always tracking-normal (Persian). Avoid tracking-tight except decorative mono display (display-mono).

Prefer text-start (right in RTL). Section captions (section-intro) use text-justify with text-align-last: start so multi-line captions justify while the last line stays right-aligned. Avoid justify on body paragraphs and titles.

Scale

Use via:

import { type, typeSpacing, typeMeasure } from "@/lib/typography";
import { Typography, SectionTitle } from "@/components/ui/typography";
import { toPersianDigits } from "@/lib/persian-digits";

<h2 className={type.h2}>عنوان بخش</h2>
<Typography variant="section-intro" className={typeMeasure.prose}>
  توضیح کوتاه
</Typography>
<span>{toPersianDigits(24)}</span>
Requested level Variant Size / weight Default element Use
Heading 1 h1 / display 3xl→5xl, extrabold / bold h1 Page / hero titles
Heading 2 h2 / cta-title 2xl→4xl, bold h2 Major sections
Heading 3 h3 lg→xl, bold h3 Subsections / features
Body Large body-lg lg, leading 1.8 p Prominent intros (same size as captions)
Body body base, leading 1.8 p Standard copy
Small Text body-sm sm, leading 1.75 p Dense / secondary
Caption caption xs, muted span Meta, footnotes
Micro micro 11px (0.6875rem) span Dense chrome / mockups / step badges
Button Text button / button-lg sm / base, medium, leading-none span Wired into Button sizes
Navigation nav / nav-mobile sm / base, medium span Header / mobile menu
— eyebrow sm medium, muted p Section labels
— label sm medium span Form labels
— card-title / card-desc base bold / sm h3 / p Cards
— section-intro lg muted, justify p Section captions under headings
— stat 4xl→5xl bold primary span KPI numbers

Reading measure

Token Class Use
typeMeasure.narrow max-w-md Short support under a heading
typeMeasure.prose max-w-2xl Standard paragraph / intro
typeMeasure.wide max-w-3xl Longer multi-paragraph blocks

Alignment

  • Titles: right-aligned (text-start in RTL).
  • Section captions (section-intro): justify with last line start (right in RTL) when 2+ lines.
  • Body paragraphs: right-aligned; do not justify.
  • Hero marketing headlines may use text-center when the composition requires it — override with className="text-center".
  • Do not inherit text-center onto multi-line section captions.

Numbers

  • Prefer explicit Persian digits in copy (۲۴) or toPersianDigits() / formatPersianNumber().
  • IRANSansXFaNum also shapes Latin digits visually; still prefer explicit Persian for dates, counters, stats, and steps.
  • Keep Latin only for technical IDs, versions, emails, and code.

Button text

Button sizes pull from type.button (sm/default) and type["button-lg"] (lg). Horizontal padding tokens in globals.css are slightly wider for Persian glyphs. Do not wrap button labels in <Typography> unless building a non-Button control.

Hierarchy rules

  1. One h1 per page (or display acting as the page title).
  2. Section titles use h2 / cta-title; subsections use h3/h4.
  3. Pair titles with at most one short supporting sentence (section-intro or body + text-muted-foreground).
  4. Use text-balance on large headings (already in scale) for better wrap in Persian.
  5. Blog article prose uses .blog-content rules in globals.css—do not override casually.

Stacking

<div className={typeSpacing.sectionStack}>
  <p className={type.eyebrow}>خدمات</p>
  <h2 className={cn(type.h2, typeSpacing.eyebrowToHeading)}>…</h2>
  <p className={cn(type["section-intro"], typeSpacing.headingToBody, typeMeasure.prose)}>…</p>
</div>

Forbidden

  • Inter / Roboto / Arial as primary UI fonts.
  • Random text-[15px] / text-[1.05rem] (use type.micro for dense chrome).
  • tracking-widest on Persian body copy.
  • text-justify on body paragraphs / titles (section captions are the exception).
  • Using font-bold everywhere—follow the scale weights.
  • Physical text-left / mr- / ml- / pr- / pl- when logical text-start / ms- / me- / ps- / pe- work.
  • Overriding scale sizes with sm:text-5xl / lg:text-6xl on type.display / type.h*.
  • Using type.h2 on an h3 (or vice versa) — keep element level and scale token aligned.