Typography
The two text primitives the theme's type ladder is spelled through, plus the blocks that are more than a font.
import { Heading, Body, TypographyTone, BodySize, Blockquote, InlineCode } from "@glint/components/typography.slint";import { Tokens } from "@glint/theme/tokens.slint";
export component Demo inherits Window { width: 560px; height: 300px; background: Tokens.color-background;
VerticalLayout { alignment: center; padding: 24px;
HorizontalLayout { alignment: center;
VerticalLayout { width: 440px; spacing: 12px;
Heading { level: 2; text: "Typography in Glint"; }
Body { text: "Glint typography maps semantic font sizes to responsive rem tokens."; tone: TypographyTone.muted; }
Blockquote { text: "Design is not just what it looks like and feels like. Design is how it works."; } } } }}Usage
import { Heading, Body, TypographyTone, BodySize, Blockquote, InlineCode, BulletList } from "@glint/components/typography.slint";import { Tokens } from "@glint/theme/tokens.slint";
export component AppWindow inherits Window { width: 560px; height: 300px; background: Tokens.color-background;
VerticalLayout { alignment: center; padding: 24px; spacing: 12px;
Heading { level: 1; text: "Documentation Heading"; }
Body { text: "Standard paragraph copy set at 400 regular weight."; } }}Two primitives rather than one, and the split falls on the weight: Heading is
the semibold ladder, Body the running-text one. They are not named Text
because that name is Slint’s own — importing a component called Text shadows
the built-in for the whole file that imports it, and Glint ships a barrel, so
one such name would cost every consumer the built-in Text in any file that
imports Glint.
Every step is a rem token in Tokens — typography-display-size,
typography-headline-size, typography-h1-size, typography-h2-size,
typography-title-size for the headings, and the typography-body-* family
under them. rem is relative to the default font size, which is what makes the
whole ladder follow a reader who has set a larger one: nothing here is a pixel
count, so nothing here ignores that setting. Components never spell a size of
their own — a private scale is a second scale disagreeing with the first.
level is a step on that ladder and nothing else. It changes how big a heading
is drawn, not what a screen reader calls it: Heading inherits Slint’s Text
and declares no accessible-role, so level: 1 and level: 5 announce
identically.
Examples
Heading levels
Headings provide five structured levels (level: 1 through level: 5), all rendered in semibold weight.
import { Heading } from "@glint/components/typography.slint";import { Tokens } from "@glint/theme/tokens.slint";
export component Demo inherits Window { width: 560px; height: 280px; background: Tokens.color-background;
VerticalLayout { alignment: center; padding: 24px;
HorizontalLayout { alignment: center;
VerticalLayout { width: 440px; spacing: 8px;
Heading { level: 1; text: "Heading 1 (Display)"; } Heading { level: 2; text: "Heading 2 (Headline)"; } Heading { level: 3; text: "Heading 3 (H1)"; } Heading { level: 4; text: "Heading 4 (H2)"; } Heading { level: 5; text: "Heading 5 (Title)"; } } } }}Body sizes
Body text supports five distinct size steps: BodySize.lg, BodySize.default, BodySize.sm, BodySize.label (medium weight), and BodySize.caption.
import { Body, BodySize } from "@glint/components/typography.slint";import { Tokens } from "@glint/theme/tokens.slint";
export component Demo inherits Window { width: 560px; height: 260px; background: Tokens.color-background;
VerticalLayout { alignment: center; padding: 24px;
HorizontalLayout { alignment: center;
VerticalLayout { width: 440px; spacing: 8px;
Body { size: BodySize.lg; text: "Large body text"; } Body { size: BodySize.default; text: "Default body text"; } Body { size: BodySize.sm; text: "Small body text"; } Body { size: BodySize.label; text: "Medium-weight form label"; } Body { size: BodySize.caption; text: "Caption footnote text"; } } } }}Typography tones
Both Heading and Body accept semantic color tones via TypographyTone: default, muted, subtle, accent, and danger.
import { Body, TypographyTone } from "@glint/components/typography.slint";import { Tokens } from "@glint/theme/tokens.slint";
export component Demo inherits Window { width: 560px; height: 240px; background: Tokens.color-background;
VerticalLayout { alignment: center; padding: 24px;
HorizontalLayout { alignment: center;
VerticalLayout { width: 440px; spacing: 8px;
Body { tone: TypographyTone.default; text: "Default high-contrast foreground"; } Body { tone: TypographyTone.muted; text: "Muted secondary foreground"; } Body { tone: TypographyTone.subtle; text: "Subtle footnote foreground"; } Body { tone: TypographyTone.accent; text: "Accent primary color highlight"; } Body { tone: TypographyTone.danger; text: "Destructive danger warning"; } } } }}Rich text blocks
Use Blockquote, InlineCode, and BulletList for formatted prose structures.
import { Blockquote, InlineCode, BulletList, Body } from "@glint/components/typography.slint";import { Tokens } from "@glint/theme/tokens.slint";
export component Demo inherits Window { width: 560px; height: 280px; background: Tokens.color-background;
VerticalLayout { alignment: center; padding: 24px;
HorizontalLayout { alignment: center;
VerticalLayout { width: 440px; spacing: 12px;
Blockquote { text: "Simplicity is prerequisite for reliability."; }
HorizontalLayout { spacing: 6px; alignment: start; Body { text: "Use"; } InlineCode { text: "cargo build"; } Body { text: "to compile your project."; } }
BulletList { items: [ "Type-safe design token access", "Seamless dark and light theme switching", "Full keyboard and accessibility support" ]; } } } }}API Reference
Heading
The five heading steps, all at semibold — the ladder the theme spells out.
level picks the step, and it is a size rather than an outline level: it
changes what a heading looks like, not what a screen reader calls it.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
level | in int | 1 | Which step, 1 (largest) through 5 (smallest). Out-of-range levels take the smallest step rather than drawing nothing. |
tone | in TypographyTone | TypographyTone.default | Colour role — default, muted, subtle. |
Enums
| Enum | Values |
|---|---|
TypographyTone | default, muted, subtle, accent, danger |
Body
Running text, at the five steps of the body ladder. label and caption are
the two that are not simply smaller body: a label is set at medium weight, the
way a form label is, and a caption is the smallest step the theme publishes.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
size | in BodySize | BodySize.default | Which step — lg, default, sm, label, caption. |
tone | in TypographyTone | TypographyTone.default | Colour role — default, muted, subtle. |
Enums
| Enum | Values |
|---|---|
BodySize | lg, default, sm, label, caption |
TypographyTone | default, muted, subtle, accent, danger |
Blockquote
A quoted passage, with the rule down its leading edge.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
text | in string | no default | The quoted text. |
InlineCode
A run of code inside a sentence, on the muted surface.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
text | in string | no default | The code. |
BulletList
A list of strings, each behind a bullet. The bullet is a mark rather than a word and is silenced in the accessibility tree, so what is announced is the item.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
items | in [string] | no default | One string per item, in order. |
Accessibility
- None of these carries a role.
HeadingandBodyinherit Slint’sText;Blockquote,InlineCodeandBulletListare containers that draw text descendants. None declares anaccessible-role, so a heading is not a heading node, aBulletListis not a list node and aBlockquoteis not a quote node. Their text is announced in layout order. What structure a reader gets comes from the landmarks around the prose — a namedregion, aDialog, aGroupBox— not from these. - The bullet is silent.
BulletListdraws its mark withaccessible-role: none, so what is announced is the item and not a punctuation character in front of it. - Tone is a color, and color is not the message.
TypographyTone.dangerandmutedchange nothing a screen reader hears. Where the tone is the point — an error, a disabled hint — the words have to carry it too, or a component that announces it does (Field puts a validation message in the accessible description; ADR-0013). - Contrast is the palette’s, not this component’s. These primitives take
Tokens.color-foregroundand its muted and subtle siblings; whether a given pairing clears a contrast bar is a property of the palette in use, and a custom palette (Theming) owns that answer for itself.