Typography¶
Source: design/tokens/typography.tokens.json. Values in px; the apps scale them with the
system setting (iOS Dynamic Type, Android font size, Windows text size) through
MediaQuery.textScaler. Images: Components.
Font choice¶
| Role | Font | License | Axes |
|---|---|---|---|
| Interface, messages | Atkinson Hyperlegible Next | SIL Open Font License 1.1 | variable, weight 200 to 800, with italic |
| Code, tool names, IDs, metrics | Atkinson Hyperlegible Mono | SIL Open Font License 1.1 | variable, weight 200 to 800, with italic |
Evidence: package data of @fontsource-variable/atkinson-hyperlegible-next@5.3.0 and
@fontsource-variable/atkinson-hyperlegible-mono@5.3.0 (license OFL-1.1, axis wght 200 to
800; https://fontsource.org/fonts/atkinson-hyperlegible-next, retrieved 2026-10-10 [verified]).
Source repositories: https://github.com/googlefonts/atkinson-hyperlegible-next and
https://github.com/googlefonts/atkinson-hyperlegible-next-mono (retrieved 2026-10-10 [verified]).
The font family comes from the Braille Institute and is designed for people with low vision;
the "Next" version appeared in 2025 with seven weights and a mono variant [verified through the
Fontsource page and press reports, primary page of the Braille Institute not read].
Reasons:
- Readability as a property of the font. Confusable characters (I, l, 1; 0, O) are clearly distinct. In a chat with IDs, paths, commands and code, this is a working advantage, not decoration.
- A face of its own. The font is recognizably different from the usual grotesques (Inter, system fonts) of the generic look and different from Discord's house font.
- One family for text and code. Next and Mono share shapes and letter spacing; metrics in the live box (mono) sit calmly next to running text.
- Variable. One font file per style covers all weights; this keeps app bundles small.
- Free license. OFL allows embedding in apps and redistribution; the license text is included
(
tools/design-tokens/vendor/fonts/*.OFL.txt, likewise in the app package).
Study B recommended system fonts (SF, Segoe UI). The requirement "unmistakable" and
readability weigh more; the system fonts remain as fallback in font.family.*.
Rejected: Inter (generic look), system font alone (no face of its own, different per platform), Bricolage Grotesque (strong, but too idiosyncratic for dense lists), fonts close to Material or Discord.
Roles¶
Components use only these roles, never font.size.* directly.
| Role | Character | Use |
|---|---|---|
type.display |
very large, extra bold, set tighter | empty states, setup, metric tiles |
type.title |
large, bold | title of a view, dialog |
type.heading |
medium, semibold | channel and thread header, sections |
type.body |
base size, regular | message text on desktop |
type.body-strong |
base size, semibold | author name |
type.body-sm |
one step smaller | list rows, channel names, live box |
type.label |
small, semibold | buttons, chips, badges |
type.section |
small, bold, set wider | space titles in the sidebar |
type.caption |
small, regular | timestamps, help texts |
type.code |
mono, one step below base size | code blocks, inline code |
type.code-sm |
mono, small, medium | tool chips, costs, token counts |
Sizes, weights, line heights and letter spacing are in the generated Token reference; this page gives only names and intent.
Message text on touch devices: density.message-font-size (context touch) instead of the size
from type.body, so that the iPhone does not read smaller than the system default.
Rules¶
- No uppercase by transformation. Long German words ("Benachrichtigungen") become unreadable in capitals. Space titles differ through weight and letter spacing.
- Numbers in mono where they change. Run time, cost, tokens, context in the live box use
type.code-sm, so that the line does not jump while counting up. - Dynamic type size up to 200 percent without loss of content (WCAG 2.2 SC 1.4.4, https://www.w3.org/TR/WCAG22/, retrieved 2026-10-10 [verified]). Rows grow in height; columns collapse into the navigation stack on narrow windows (see 01-product.md).
- Markdown. Headings in messages use at most
type.heading; an agent cannot fill the history with display sizes. - Fallback. If a character is missing in Atkinson (for example CJK), the fallback list from
font.family.*applies; the apps bundle no further fonts.
Integration¶
- Flutter:
packages/design_systembundles the variable TTF files of both families (upright and italic, axiswght) from the source repositories at a recorded commit, with the OFL text of each family next to them, underpackages/design_system/fonts/;fonts/MANIFEST.jsonrecords source URL, commit, SHA-256 and license of every file, andtest/fonts_test.dartfails on a changed, missing or extra file or a file without license text (docs/DECISIONS.md D-M4-04-4). The files carry the Google Fonts download names (<Family>-VariableFont_wght.ttf), not the bracket names of the repositories.pubspec.yamldeclares the familiesAtkinson Hyperlegible NextandAtkinson Hyperlegible Mono.DsType(generated, copied intolib/src/generated/bytokens.py build) supplies theTextStyleconstants;dsTextStyleadds the package font namepackages/design_system/<family>in front of the fallback list (apps that depend on the package register the fonts under that name) and drives thewghtaxis from the weight. The theme (buildDsTheme) takes its text theme from the roles throughdsTextStyle; the fallback list offont.family.*stays behind it. - Web console and docs site: WOFF2 from the same version;
tokens.cssprovides the variables--ds-type-*. - Preview: the WOFF2 files are under
tools/design-tokens/vendor/fonts/and are embedded.