Skip to content
PorabuildHeroGPUI component library
v0.14.0 · Apache-2.0

Typography

Typography

Semantic typography primitives for headings, body and code.

Rust
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.

Usage

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{Typography, TypographyType};

Typography::new(
    "Typography sets the size, weight and line height of a run of text.",
)

Render Props

`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.

Rust
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.",
    ))

Scale

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
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).

Colors & weights

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
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(),
    ])

Alignment & truncation

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
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(),
    ])

Primitives

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
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(),
    ])

Prose

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
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.

MONO_FONT
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

TypographyProse

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

Typography styling
MethodValuesDescription
color(TextColor)TextColor::Default | TextColor::MutedText color role.
Rust
// 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

Typography builders
BuilderValuesDefaultDescription
kind(TypographyType)TypographyType::H1 | TypographyType::H2 | TypographyType::H3 | TypographyType::H4 | TypographyType::H5 | TypographyType::H6 | TypographyType::Body | TypographyType::BodySm | TypographyType::BodyXs | TypographyType::CodeTypographyType::BodySemantic 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(TextAlign)PartialTextAlign::Start | TextAlign::Center | TextAlign::End | TextAlign::JustifyTextAlign::StartText alignment. Gpui-pre 0.3.3 has no `text-justify`; justify falls back to start alignment.
color(TextColor)TextColor::Default | TextColor::MutedTextColor::DefaultText color role.
weight(FontWeight)FontWeight::Normal | FontWeight::Medium | FontWeight::Semibold | FontWeight::Bold—Font weight override over the type's default.
truncate(bool)true | false—Truncates the text to one line with an ellipsis.
ParentElement::extendPartialAnyElement—Text content, either as the constructor's text or as composed children.
heading(u8, text)1 | 2 | 3 | 4 | 5 | 61Maps to `type="h1"` through `type="h6"`; higher levels clamp to h6.
paragraph(ParagraphSize, text)'base' | 'sm' | 'xs''base'Maps to the `body`, `body-sm` and `body-xs` types.
code(text)AnyElement—The inline code text; `Typography.Code` is the `code` type.
Not ported2 HeroUI entries not ported
Typography builders not ported
HeroUI v3Why it is not ported
Typography.renderRender 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

Typography parts
PartDescription
TypographyPartialRoot 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.
ProsePartialProse 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.