Skip to content

feat(design): typography & font customization — 15 text roles, per-role family, brand-name font#381

Open
91jaeminjo wants to merge 12 commits into
mainfrom
feat/brand-theme-api-gaps
Open

feat(design): typography & font customization — 15 text roles, per-role family, brand-name font#381
91jaeminjo wants to merge 12 commits into
mainfrom
feat/brand-theme-api-gaps

Conversation

@91jaeminjo

Copy link
Copy Markdown
Collaborator

Summary

Closes the consumer-facing typography/font gaps in the public BrandTheme façade, so a whitelabel fork can reproduce an arbitrary type scale and a distinct brand-name font through config alone.

  • All 15 Material text roles are now built, each accepting a per-role TypeScaleOverride (was 9 — displayLarge/Medium/Small, headlineLarge/Small, and labelLarge were previously left to Material defaults).
  • Per-role font-family assignment via TypeScaleOverride.familyBrandFontRole { body, display, brand }. The enum maps a role onto an already-resolved named family — no per-role family strings, no extra resolver calls.
  • brandFamily — a fourth named font, resolved onto the SoliplexTheme extension (mirroring the monospace token) and rendered as the app/brand name in the auth and lobby headers, read via context.brandFont / context.brandNameOn.
  • BrandTint / TintSource re-exported from soliplex_frontend, so a facade-only consumer can build BrandTheme(tint: …) without a direct soliplex_design dependency.
  • FontResolver.resolve contract documented: an implementation may load a font as a side effect, and a consumer should await font readiness in main() before runApp (resolution is synchronous; the theme layer cannot await it).

Label scale

The label roles are now strictly ordered at 12 / 14 / 16 (labelSmall / labelMedium / labelLarge). labelLarge (16) drives interactive component text — buttons, chips, tabs, segmented controls — which previously fell through to Material's 14 pt default. labelMedium (14) is for incidental labels (badges, counters, dividers, filter indicators); prominent labels — the connect-flow rail, room-info section headers, and the classification badge — are pinned to labelLarge so they stay at 16.

Visual impact

Typography only: interactive controls 14→16, incidental labels 16→14, plus minor line-height / letter-spacing on the newly-built roles. No color, spacing, radii, or layout changes. BrandTheme.soliplex() leaves the new families null, so brand-name rendering is unchanged by default.

Out of scope

The runtime theme-mode toggle (library-side UI work) and the module-level hardcoded-color → token migrations are intentionally not included here.

Test plan

  • flutter analyze — zero warnings.
  • Unit/widget tests pass with --exclude-tags golden: soliplexTextTheme builds all 15 roles; per-role family routing (body/display/brand); brandFamily lowering onto SoliplexTheme.brandFont and context.brandFont; brand-name header rendering; facade exports of BrandTint/TintSource/BrandFontRole.
  • Component goldens regenerated on Linux via the update-goldens workflow — 10 updated (button / chip / badge / classification / dropdown, light + dark); input and picker unchanged, confirming the diffs are genuine typography changes rather than render drift.

🤖 Generated with Claude Code

91jaeminjo and others added 12 commits June 25, 2026 08:01
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
soliplexTextTheme now emits all 15 TextTheme slots instead of 9.
The 6 new roles (displayLarge/Medium/Small, headlineLarge, headlineSmall,
labelLarge) carry Soliplex-consistent metrics; the existing 9 are unchanged.

BrandTypography gains matching TypeScaleOverride? fields for all 15 roles,
with constructor, copyWith, ==, and hashCode updated in Material order.
brand_lowering.dart threads all 15 overrides through to soliplexTextTheme.

Golden refresh needed on CI for lib/src/modules/quiz/ui/quiz_results.dart:
displayLarge height shifts from the Material default (1.12) to the Soliplex
value (1.2); font size is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- BrandTypography gains brandFamily (String?) alongside bodyFamily/displayFamily/codeFamily; threads through copyWith/==/hashCode
- SoliplexTheme gains brandFont (nullable record) with snap lerp, matching the monospace pattern
- buildSoliplexThemeData accepts brandFont and populates the extension
- _lowerBrandFont in brand_lowering.dart resolves brandFamily through FontResolver and passes it to buildSoliplexThemeData
- context.brandFont accessor and context.brandNameOn(base) helper added to TypographyX extension
- HomeShellHeader and _BrandHeader (server_sidebar) now render the app name via context.brandNameOn; default behavior unchanged (null brandFamily → style unchanged)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…Role to body/display/brand

- labelLarge 18→16, labelMedium 16→14; labelSmall stays 12
- Remove BrandFontRole.code and the monospace parameter from soliplexTextTheme
- Replace String? brandFamily param with pre-resolved brandFont tuple; resolve once in lowerBrandTheme
- Replace two internal soliplex_design imports in server_sidebar_test with the public barrel

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…in the customization table

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The connect-flow rail, room-info section headers, and the classification
badge are prominent labels; point them at labelLarge (16) rather than the
smaller labelMedium (14) used for compact metadata.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Regenerated on Linux via the update-goldens workflow. Button/chip pick up
labelLarge 16 (was Material 14); badge and the classification/dropdown gallery
labels pick up labelMedium 14 (was 16). Input and picker are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant