Typography
Semantic typography primitives for headings, body and code.
use herogpui::components::typography::{Typography, TypographyType};Typography on docs.rsSource at v0.14.0
Usage
Showing Usage, live: HeroGPUI compiled to WebAssembly. The canvas has no accessibility tree; each example's description and code below carry the same information.
An element expression with window: &mut Window and cx: &mut App in scope.
use herogpui::prelude::{Typography, TypographyType};
Typography::new(
"Typography sets the size, weight and line height of a run of text.",
)`Prose` provides only the `text-foreground` color. GPUI has no per-tag CSS selectors, so the per-tag descendant styles of a typographic stylesheet — `h1`–`h6`, `p`, `code`, `a`, lists — cannot be inherited; children must already be semantic elements. An element expression with window: &mut Window and cx: &mut App in scope.
use herogpui::prelude::{ParagraphSize, Prose, Typography, TypographyType};
use herogpui::gpui::prelude::*;
Prose::new()
.child(Typography::paragraph(
ParagraphSize::Base,
"A paragraph inside `Prose` carries its own body metrics.",
))An element expression with window: &mut Window and cx: &mut App in scope.
use herogpui::prelude::{ActiveTheme, Typography, TypographyType};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;
let scale = [
(TypographyType::H1, "h1", "36 / 600"),
(TypographyType::H2, "h2", "30 / 600"),
(TypographyType::H3, "h3", "24 / 600"),
(TypographyType::H4, "h4", "20 / 600"),
(TypographyType::H5, "h5", "18 / 600"),
(TypographyType::H6, "h6", "16 / 600"),
(TypographyType::Body, "body", "16 / 400"),
(TypographyType::BodySm, "body-sm", "14 / 400"),
(TypographyType::BodyXs, "body-xs", "12 / 400"),
(TypographyType::Code, "code", "14 / mono"),
];
let muted = cx.colors().muted;
gpui::div()
.flex()
.flex_col()
.items_start()
.justify_center()
.gap(px(12.))
.children(scale
.iter()
.map(|(kind, name, meta)| {
gpui::div()
.flex()
.items_center()
.gap(px(24.))
.child(
gpui::div()
.w(px(110.))
.flex()
.flex_col()
.child(
gpui::div()
.text_size(px(13.))
.font_weight(gpui::FontWeight::SEMIBOLD)
.child(name.to_string()),
)
.child(
gpui::div()
.text_size(px(11.))
.text_color(muted)
.child(meta.to_string()),
),
)
.child(
Typography::new("Build better interfaces")
.kind(*kind)
.font_family(MONO_FONT),
)
}))Also calls MONO_FONT (included when you copy).
An element expression with window: &mut Window and cx: &mut App in scope.
use herogpui::prelude::{FontWeight, TextColor, Typography, TypographyType};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;
gpui::div()
.flex()
.flex_col()
.items_start()
.justify_center()
.gap(px(12.))
.children(vec![
Typography::new("Default foreground").into_any_element(),
Typography::new("Muted foreground")
.color(TextColor::Muted)
.into_any_element(),
Typography::new("Medium body")
.weight(FontWeight::Medium)
.into_any_element(),
Typography::new("Semibold body")
.weight(FontWeight::Semibold)
.into_any_element(),
Typography::new("Bold body")
.weight(FontWeight::Bold)
.into_any_element(),
])An element expression with window: &mut Window and cx: &mut App in scope.
use herogpui::prelude::{TextAlign, Typography, TypographyType};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;
gpui::div()
.flex()
.flex_col()
.items_start()
.justify_center()
.gap(px(12.))
.children(vec![
Typography::new("Centered against the measure")
.align(TextAlign::Center)
.into_any_element(),
Typography::new("Aligned to the end")
.align(TextAlign::End)
.into_any_element(),
Typography::new(
"Justify falls back to start alignment: gpui has no text-justify.",
)
.align(TextAlign::Justify)
.into_any_element(),
gpui::div()
.w(px(220.))
.child(
Typography::new(
"A long line that truncates to a single ellipsis at the \
edge of its 220px box instead of wrapping.",
)
.truncate(true),
)
.into_any_element(),
])An element expression with window: &mut Window and cx: &mut App in scope.
use herogpui::prelude::{ParagraphSize, Typography, TypographyType};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;
gpui::div()
.flex()
.flex_col()
.items_start()
.justify_center()
.gap(px(12.))
.children(vec![
Typography::heading(3, "Dashboard").into_any_element(),
Typography::paragraph(
ParagraphSize::Base,
"Paragraph supports base, sm and xs sizes.",
)
.into_any_element(),
// `radius(px)` rounds the `Code` chip alone; the other
// kinds paint no box.
Typography::code("cargo add herogpui")
.radius(px(2.))
.into_any_element(),
])An element expression with window: &mut Window and cx: &mut App in scope.
use herogpui::prelude::{ParagraphSize, Prose, Typography, TypographyType};
use herogpui::gpui::prelude::*;
Prose::new()
.child(Typography::heading(4, "Body heading"))
.child(Typography::paragraph(
ParagraphSize::Base,
"Prose applies the shared typographic rhythm to already-semantic children.",
))Helpers used by these examples
Plain functions over the public API, defined once here and copied with each example that calls them.
const MONO_FONT: &str = if cfg!(target_arch = "wasm32") {
// The web shell bundles JetBrains Mono; the literal family "monospace"
// resolves to nothing there and panics text resolution.
"JetBrains Mono"
} else if cfg!(target_os = "macos") {
"Menlo"
} else {
"Consolas"
};Anatomy
Rust types
Typography is assembled from these builders. The API reference lists each one.
Customization
Shared appearance belongs on ThemeBuilder::components and .recipe("name"). Typed builders change how Typography looks at one call site. Every builder also carries sx for placement, width and flex: it takes GPUI's own styling methods and refines them over the component's root after the theme, so an instance override wins. Behaviour builders live in the API reference below.
Styling
| Method | Values | Description |
|---|---|---|
color(TextColor) | TextColor::Default | TextColor::Muted | Text color role. |
// The one slot for caller-owned low-level styling: GPUI's
// styling methods, refined over the root element last.
.sx(|el| {
el.bg(gpui::rgba(0xffa500ff)) // background
.text_color(gpui::rgba(0x000000ff)) // text
.w(gpui::px(13.)) // size
.h(gpui::px(12.))
})API reference
Against HeroUI v3.2.6: 7 entries ported, 5 partial, 2 not ported. Partial rows are marked in the tables; entries not ported are listed under each table with the reason.
Builders
| Builder | Values | Default | Description |
|---|---|---|---|
kind( | TypographyType:: | TypographyType:: | Semantic typography style, carrying the tagged scale's size/line-height pair, the heading weight and the code family. Named `kind` because `type` is a Rust keyword. |
align(Partial | TextAlign:: | TextAlign:: | Text alignment. Gpui-pre 0.3.3 has no `text-justify`; justify falls back to start alignment. |
color( | TextColor:: | TextColor:: | Text color role. |
weight( | FontWeight:: | — | Font weight override over the type's default. |
truncate( | true | | — | Truncates the text to one line with an ellipsis. |
ParentElement::Partial | AnyElement | — | Text content, either as the constructor's text or as composed children. |
heading( | 1 | | 1 | Maps to `type="h1"` through `type="h6"`; higher levels clamp to h6. |
paragraph( | 'base' | | 'base' | Maps to the `body`, `body-sm` and `body-xs` types. |
code( | AnyElement | — | The inline code text; `Typography.Code` is the `code` type. |
Not ported2 HeroUI entries not ported
| HeroUI v3 | Why it is not ported |
|---|---|
Typography.render | Render prop that re-targets the rendered element. Has no element polymorphism to re-target — every type draws a plain div — so there is nothing for a render function to override. |
Typography.Prose.className |
Parts
| Part | Description |
|---|---|
TypographyPartial | Root primitive: maps each type to its semantic element (`h1`–`h6`, `p`, `code`) through Text, and headings tighten their tracking. Gpui-pre 0.3.3 has no semantics and no letter-spacing, so the same metrics, weight and color render on a plain div. |
ProsePartial | Prose container: `text-foreground` with the children rendered in order. The per-tag descendant styles in `.typography-prose h1`, `p`, `code`, `a`, lists and friends need CSS selectors GPUI does not have, so nothing is inherited automatically. |