6.4 KiB
6.4 KiB
Typography System Guide
This guide documents the typography and text styling system in Bedrock.
Overview
The typography system consists of:
Typographyenum - All font definitions with explicit namingTextEmphasisenum - Semantic text colorsStyledLabel- Simple text component combining typography + emphasisIconLabel- Icon + text component.typography()modifier - View extension for applying fonts
Typography Enum
All fonts are defined in the Typography enum. Each case name explicitly describes the font:
- Base name = regular weight (e.g.,
.title2= Font.title2) *Bold= bold weight (e.g.,.title2Bold= Font.title2.bold())*Emphasis= semibold weight (e.g.,.bodyEmphasis= Font.body.weight(.semibold))
Available Styles
| Category | Style | Font |
|---|---|---|
| Hero/Titles | .hero |
largeTitle |
.heroBold |
largeTitle.bold() | |
.title |
title | |
.titleBold |
title.bold() | |
.title2 |
title2 | |
.title2Bold |
title2.bold() | |
.title3 |
title3 | |
.title3Bold |
title3.bold() | |
| Headings | .heading |
headline |
.headingEmphasis |
headline.weight(.semibold) | |
.headingBold |
headline.bold() | |
.subheading |
subheadline | |
.subheadingEmphasis |
subheadline.weight(.semibold) | |
| Body | .body |
body |
.bodyEmphasis |
body.weight(.semibold) | |
.callout |
callout | |
.calloutEmphasis |
callout.weight(.semibold) | |
| Micro | .footnote |
footnote |
.footnoteEmphasis |
footnote.weight(.semibold) | |
.caption |
caption | |
.captionEmphasis |
caption.weight(.semibold) | |
.caption2 |
caption2 | |
.caption2Emphasis |
caption2.weight(.semibold) |
Usage
// Using the .typography() modifier (preferred)
Text("Hello")
.typography(.heading)
// Using .font() directly
Text("Hello")
.font(Typography.heading.font)
TextEmphasis Enum
Semantic text colors that work with any theme:
| Emphasis | Description |
|---|---|
.primary |
Main text color |
.secondary |
Supporting text |
.tertiary |
Subtle/hint text |
.disabled |
Disabled state |
.inverse |
Contrasting backgrounds |
.custom(Color) |
Custom color override |
Usage
// With StyledLabel
StyledLabel("Title", .heading, emphasis: .primary)
StyledLabel("Subtitle", .subheading, emphasis: .secondary)
StyledLabel("Custom", .body, emphasis: .custom(.red))
// With custom theme colors
StyledLabel("Title", .heading, emphasis: .custom(AppTextColors.primary))
StyledLabel Component
A single component for all styled text. Replaces the old TitleLabel, BodyLabel, CaptionLabel.
StyledLabel(_ text: String, _ typography: Typography = .body, emphasis: TextEmphasis = .primary)
Examples
// Simple usage
StyledLabel("Morning Ritual", .heading)
StyledLabel("Day 6 of 28", .caption, emphasis: .secondary)
// With custom theme colors
StyledLabel("Title", .heading, emphasis: .custom(AppTextColors.primary))
StyledLabel("Subtitle", .subheading, emphasis: .custom(AppTextColors.secondary))
IconLabel Component
For icon + text combinations:
IconLabel(_ icon: String, _ text: String, _ typography: Typography = .body, emphasis: TextEmphasis = .primary)
Examples
IconLabel("bell.fill", "Notifications", .subheading)
IconLabel("star.fill", "Favorites", .body, emphasis: .secondary)
When to Use StyledLabel vs Text()
Use StyledLabel (Preferred)
Use StyledLabel for the vast majority of text:
// Simple text
StyledLabel("Settings", .subheadingEmphasis)
StyledLabel("Description", .subheading, emphasis: .secondary)
// With multiline alignment
StyledLabel("Centered text", .body, emphasis: .primary, alignment: .center)
// With line limit
StyledLabel("One line only", .caption, emphasis: .secondary, lineLimit: 1)
// In buttons (put frame modifiers outside)
Button(action: onContinue) {
StyledLabel("Continue", .heading, emphasis: .custom(AppTextColors.inverse))
.frame(maxWidth: .infinity)
.frame(height: 50)
.background(AppAccent.primary)
}
Use Text() with .typography() (Rare Exceptions)
Only use Text() when you genuinely need modifiers that StyledLabel doesn't support:
// Font design variants (rounded, etc.)
Text(formattedValue)
.typography(.subheadingEmphasis)
.fontDesign(.rounded)
// TextField styling
TextField("Placeholder", text: $value)
.typography(.heading)
// Inside special view builders (like Charts AxisValueLabel)
AxisValueLabel {
Text("\(value)%")
.font(Typography.caption2.font) // .typography() won't work here
.foregroundStyle(color)
}
Never Use Raw .font() with System Fonts
Instead of:
// BAD
Text("Title").font(.headline)
Use:
// GOOD
StyledLabel("Title", .heading)
Migration from Old System
Old vs New
// OLD: Design.Typography
Text("Title").font(Design.Typography.headline)
Text("Body").font(Design.Typography.body)
Text("Caption").font(Design.Typography.caption)
// NEW: Typography enum
Text("Title").typography(.heading)
Text("Body").typography(.subheading)
Text("Caption").typography(.caption)
// OLD: Multiple Label components
TitleLabel("Title", style: .headline, color: .white)
BodyLabel("Body", emphasis: .secondary)
CaptionLabel("Caption")
// NEW: Single StyledLabel
StyledLabel("Title", .heading, emphasis: .custom(.white))
StyledLabel("Body", .subheading, emphasis: .secondary)
StyledLabel("Caption", .caption, emphasis: .secondary)
Mapping Table
| Old (Design.Typography) | New (Typography) |
|---|---|
.displayLarge |
.heroBold |
.displayMedium |
.titleBold |
.displaySmall |
.title2Bold |
.headline |
.heading |
.headlineBold |
.headingBold |
.body |
.subheading |
.bodyMedium |
.subheadingEmphasis |
.bodyLarge |
.body |
.caption |
.caption |
.captionMedium |
.captionEmphasis |
.captionSmall |
.caption2 |
.settingsTitle |
.subheadingEmphasis |
.sectionHeader |
.captionEmphasis |
SymbolIcon (Unchanged)
The SymbolIcon component remains the same for consistent icon styling:
SymbolIcon("star.fill", size: .row, color: .accent)
SymbolIcon("sparkles", size: .hero, color: AppAccent.primary)
SymbolIcon.chevron()
See the existing documentation for SymbolIcon sizes and usage.