Created
January 23, 2026 16:54
-
-
Save fredgrott/e642387708e6957d1d8400beb4787275 to your computer and use it in GitHub Desktop.
M3ECustomTypography
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /// Material 3 Expressive typography tokens. | |
| /// - `base` starts from **M3 (Typography.material2021)**. | |
| /// - Optionally remaps fonts: brand (UI) for display/headline/title/label | |
| /// and plain (reading) for body. | |
| /// - Adds an emphasized set (weight/tracking tweaks) for expressive hierarchy. | |
| @immutable | |
| class M3ECustomTypography { | |
| final TextTheme base; | |
| final M3ECustomEmphasized emphasized; | |
| const M3ECustomTypography({required this.base, required this.emphasized}); | |
| /// Build default M3E typography from M3. | |
| /// | |
| /// [brandFontFamily] is typically your UI/brand face (e.g., Roboto Flex). | |
| /// [plainFontFamily] is typically your reading face (e.g., Roboto Serif). | |
| /// If you pass neither, you’ll get pure M3 defaults (no family swap), | |
| /// but still keep the M3E emphasized set for optional use. | |
| factory M3ECustomTypography.defaultFor( | |
| Brightness brightness, { | |
| String? brandFontFamily, | |
| String? plainFontFamily, | |
| TextTheme? baseOverride, | |
| }) { | |
| // 1) Start from Material 3 baseline type. | |
| final m3 = Typography.material2021(); | |
| final TextTheme m3Base = baseOverride ?? (brightness == Brightness.dark ? m3.white : m3.black); | |
| // 2) Optionally map brand/plain families to role groups (M3E guidance). | |
| final TextTheme baseWithFamilies = _applyFamilies(m3Base, brand: brandFontFamily, plain: plainFontFamily); | |
| // 3) Provide emphasized deltas (weights/tracking). | |
| return M3ECustomTypography(base: baseWithFamilies, emphasized: M3ECustomEmphasized.forBrightness(brightness)); | |
| } | |
| /// Lerp the full token set. | |
| static M3ECustomTypography lerp(M3ECustomTypography a, M3ECustomTypography b, double t) => M3ECustomTypography( | |
| base: TextTheme.lerp(a.base, b.base, t), | |
| emphasized: M3ECustomEmphasized.lerp(a.emphasized, b.emphasized, t), | |
| ); | |
| /// Apply brand/plain families: brand → display/headline/title/label, | |
| /// plain → body. If a family is null, keep the original. | |
| static TextTheme _applyFamilies(TextTheme t, {String? brand, String? plain}) { | |
| TextStyle? _withFam(TextStyle? s, String? fam) => fam == null ? s : s?.copyWith(fontFamily: fam); | |
| return t.copyWith( | |
| // Brand / UI voice | |
| displayLarge: _withFam(t.displayLarge, brand), | |
| displayMedium: _withFam(t.displayMedium, brand), | |
| displaySmall: _withFam(t.displaySmall, brand), | |
| headlineLarge: _withFam(t.headlineLarge, brand), | |
| headlineMedium: _withFam(t.headlineMedium, brand), | |
| headlineSmall: _withFam(t.headlineSmall, brand), | |
| titleLarge: _withFam(t.titleLarge, brand), | |
| titleMedium: _withFam(t.titleMedium, brand), | |
| titleSmall: _withFam(t.titleSmall, brand), | |
| labelLarge: _withFam(t.labelLarge, brand), | |
| labelMedium: _withFam(t.labelMedium, brand), | |
| labelSmall: _withFam(t.labelSmall, brand), | |
| // Reading voice | |
| bodyLarge: _withFam(t.bodyLarge, plain), | |
| bodyMedium: _withFam(t.bodyMedium, plain), | |
| bodySmall: _withFam(t.bodySmall, plain), | |
| ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment