Files
nick-doc/05 - Design System/Typography.md
Siavash Sameni dceaf82934 audit: 2026-05-30 full-codebase audit — report, issues, docs, runbooks
Full-codebase-audit 2026-05-30 outputs:
- Audit report: 09 - Audits/Full Codebase Audit - 2026-05-30.md
- 81 issue files ISSUE-055..135 (decisions + 1 skipped no-brainer).
- Scanner docs from scratch (was zero): architecture, data model, API ref, payment
  flow, operations runbook + repo README.
- Doc-sync updates across API reference, data models, flows, design system.
- Secret Rotation Runbook (08 - Operations) for the exposed credentials.
- Reusable workflow guide (07 - Development) + .claude/workflows/full-codebase-audit.js.

Issues remain status:open intentionally — the code fixes are uncommitted-then-committed
working-tree changes per repo and aren't "resolved" until merged/deployed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 18:48:04 +04:00

193 lines
5.6 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: Typography
tags: [design-system, typography, fonts]
created: 2026-05-23
updated: 2026-05-30
---
# Typography
> [!info] Amaneh Design System v2.7.0 (commit 56fc84e)
> The font stack changed in v2.7.0 from Public Sans + Barlow to a **three-font purposeful stack**:
> - **Source Serif 4** — headings in italic; editorial, humanist character
> - **IBM Plex Sans** — body and UI text; technical clarity, RTL-compatible
> - **IBM Plex Mono** — amounts, wallet addresses, tx hashes; monospaced, tabular-nums built-in
The system uses a three-font purposeful stack for the Amaneh design. Locale-specific Persian/Arabic faces are loaded when the active language requires them.
---
## 1. Font stack
Loaded via `@fontsource-variable`. Current active fonts (`frontend/package.json`):
```jsonc
"@fontsource-variable/source-serif-4": "...", // Headings (italic)
"@fontsource/ibm-plex-sans": "...", // UI / body
"@fontsource/ibm-plex-mono": "...", // Amounts, addresses, hashes
```
The settings drawer still lists alternative fonts (DM Sans, Inter, Nunito Sans, Public Sans) for user override.
Default font-family stack in the theme:
```css
/* Headings */
font-family: "Source Serif 4 Variable", Georgia, serif;
/* UI / body */
font-family: "IBM Plex Sans", "Helvetica", "Arial", sans-serif;
/* Monospaced (amounts / addresses) */
font-family: "IBM Plex Mono", "Courier New", monospace;
```
Use `sx={{ fontFamily: 'IBMPlexMono' }}` (theme alias) for any USDT amounts, contract addresses, or transaction hashes.
---
## 2. Type scale
| Variant | Size (px) | Line height | Weight | Use |
|---|---|---|---|---|
| `h1` | 64 | 80 | 800 | Hero titles only |
| `h2` | 48 | 64 | 800 | Page titles |
| `h3` | 32 | 48 | 700 | Section titles |
| `h4` | 24 | 36 | 700 | Card titles, dialog headers |
| `h5` | 20 | 30 | 700 | Sub-section titles |
| `h6` | 18 | 28 | 700 | Item titles, sidebar headers |
| `subtitle1` | 16 | 24 | 600 | Form section labels |
| `subtitle2` | 14 | 22 | 600 | List item subtitles |
| `body1` | 16 | 24 | 400 | Body copy default |
| `body2` | 14 | 22 | 400 | Secondary copy, table cells |
| `caption` | 12 | 18 | 400 | Helper text, timestamps |
| `overline` | 12 | 18 | 700 | Tags, all-caps category labels |
| `button` | 14 | 24 | 700 | Button text — NOT uppercase |
> [!tip]
> Use `responsiveFontSizes(theme)` once at theme creation to scale `h1`/`h2` on small screens automatically.
---
## 3. Weights
The variable Public Sans face supports 100900. Convention:
| Weight | Token | Use |
|---|---|---|
| 400 | `fontWeightRegular` | Body |
| 500 | `fontWeightMedium` | Mild emphasis |
| 600 | `fontWeightSemiBold` | Subtitles, table headers |
| 700 | `fontWeightBold` | Headings |
| 800 | (raw) | Display |
Never use `font-weight: bolder` — always pick from the table.
---
## 4. Letter-spacing
- Headings (h1h2): `-1` (tight, modern)
- Overline: `+1.1` (open, all-caps)
- Body, subtitle: `0`
---
## 5. Numeric variants
Tabular figures matter for financial UI (payments, prices). Enable per-instance:
```tsx
<Typography variant="body1" sx={{ fontVariantNumeric: 'tabular-nums' }}>
{amount}
</Typography>
```
---
## 6. Multi-script support
The system officially supports Latin, **Persian (Farsi)**, and **Arabic** rendering; French and Vietnamese use Latin glyphs already covered by Public Sans; Chinese (Simplified) falls back to the OS-default CJK font (the current fontsource set does not ship CJK).
Persian/Arabic font swap is layered at theme build:
```ts
fontFamily:
locale === 'fa' || locale === 'ar'
? '"Vazirmatn", "Public Sans Variable", "Tahoma", sans-serif'
: '"Public Sans Variable", "Helvetica", sans-serif'
```
> [!note]
> "Vazirmatn" is the **recommended** Persian face for new installations — it has full Unicode coverage and a variable axis. If not installed via `@fontsource`, ship it as a self-hosted woff2 under `public/fonts/`.
For Chinese (`cn`), consider adding `"PingFang SC", "Microsoft YaHei", "Noto Sans CJK SC"` to the family at the front.
For Vietnamese (`vi`) — Public Sans already covers all needed glyphs.
---
## 7. Line-length
Aim for **4575 characters per line** on body copy. Constrain with `maxWidth`:
```tsx
<Typography variant="body1" sx={{ maxWidth: 720 }}>{longBody}</Typography>
```
---
## 8. Text truncation
Single-line:
```tsx
<Typography noWrap>{text}</Typography>
```
Multi-line (clamp at 2 lines):
```tsx
<Typography
sx={{
display: '-webkit-box',
WebkitLineClamp: 2,
WebkitBoxOrient: 'vertical',
overflow: 'hidden',
}}
>{text}</Typography>
```
---
## 9. Bidi & RTL considerations
- Don't hard-code `text-align: left/right` — use `text-align: start/end` so it flips with direction.
- For inline mixed-script (Persian + English), prefer the auto direction inside `<bdi>` or wrap with the Unicode `` (RLE) / `` (PDF) markers.
- Numeric formatting per locale handled by `Intl.NumberFormat`; do NOT translate digits manually.
---
## 10. Loading & FOUC prevention
- All fonts loaded at the route segment that needs them (Next.js best practice).
- `font-display: swap` is the default in fontsource — visible text uses fallback first, then swaps.
- For the FIRST PAINT on auth pages, preload the primary Latin face by adding `<link rel="preload" as="font" />` to the root layout.
---
## 11. Customising
Add a font:
1. `yarn add @fontsource-variable/<name>`
2. `import '@fontsource-variable/<name>'` in `src/app/layout.tsx`.
3. Add to `fontFamily` stack in `theme/options/typography.ts`.
4. Register as a settings option if user-selectable.
---
## Related
- [[Theme Configuration]] · [[Design System Overview]] · [[Colors]]
- [[Internationalization & RTL]]
- [[Settings & Theming]]