ThemeExtension API — the platform-native way to attach custom data to a ThemeData.
The two extensions
Both are installed by
AppTheme:
Context accessors
theme_extensions.dart provides the two getters used throughout the app:
- They resolve against the nearest
Theme— inside a ThemeOverride subtree you get the overridden tokens, not the app-level ones. - They are non-null asserted (
!) — anyThemea Sundial widget lives under must carry both extensions. In practice that means themes must come fromAppTheme.*; a bareThemeData()would crash token consumers. When overriding a subtree theme, always go throughAppTheme.light/.darkorThemeOverride.
Why copyWith and lerp matter
EveryThemeExtension subclass must implement copyWith and lerp. Sundial implements both for every field (all 25 colors, all 15 text styles, and the 5 accent fields):
copyWithis howAppThemenests the resolved accent:baseColorTheme.copyWith(accent: accent).lerpis what makes theme changes animate. WhenThemeDatachanges (brightness flip, persona change,ThemeOverrideboundary), Flutter’sAnimatedThemeinterpolates between old and new extensions — every color cross-fades and every text style transitions smoothly, with zero widget-level work.
Adding a token (checklist)
Adding a field to either extension means updating four places in the token file — the field, the constructor,copyWith, and lerp — plus the .light/.dark (or .base) instances. Missing lerp won’t fail to compile for nullable fields, so review carefully; a token that doesn’t lerp will snap during animated theme changes. See Contributing.