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>
193 lines
5.6 KiB
Markdown
193 lines
5.6 KiB
Markdown
---
|
||
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 100–900. 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 (h1–h2): `-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 **45–75 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]]
|