Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Cristiang1021/ErgoKawsay/llms.txt
Use this file to discover all available pages before exploring further.
ErgoKawsay’s theming system is built on Flutter Material 3. Rather than relying solely on ColorScheme, the app introduces a custom AppPalette theme extension that provides a complete, named color palette for both light and dark modes. Widgets access palette tokens directly from the BuildContext extension rather than through generic Theme.of(context).colorScheme lookups.
Color Palette
AppPalette extends ThemeExtension<AppPalette> and is an @immutable value class. It carries every color token the UI needs. Two static constants — AppPalette.light and AppPalette.dark — are the only values ever instantiated at runtime.
Core tokens
| Token | Light mode | Dark mode | Usage |
|---|
canvas | #FFFFFF | #0D0D0D | Scaffold background |
surface1 | #FFFFFF | #0D0D0D | Card surface |
surface2 | #F4F7EC | #1A1C14 | Chip, secondary surface |
ink | #0D0D0D | #F0EDE6 | Primary text |
inkMuted | #5C5C52 | #8A8A82 | Secondary / caption text |
hairline | #D6DBC8 | #282A20 | Dividers, border lines |
hairlineSoft | #ECF0E4 | #1A1C14 | Subtle dividers |
accent | #97BF06 | #97BF06 | Brand green — active states, progress |
primaryBtnBg | #030A8C | #4D5FC0 | Primary CTA background |
primaryBtnFg | #FFFFFF | #FFFFFF | Primary CTA text |
success | #4A6800 | #97BF06 | Success states |
error | #C0230A | #FF4835 | Error states |
Accessing the palette
A BuildContext extension makes palette access ergonomic throughout the codebase:
import 'package:ergokawsay/core/theme/app_palette.dart';
// In any widget build method:
final palette = context.palette;
Container(color: palette.accent) // brand green
Text('Hello', style: TextStyle(color: palette.ink))
ElevatedButton(
style: ElevatedButton.styleFrom(backgroundColor: palette.primaryBtnBg),
// ...
)
If the extension is somehow absent from the theme (should not happen in production), context.palette falls back to AppPalette.light.
AppTheme
AppTheme is a private-constructor utility class exposing two ThemeData getters:
MaterialApp(
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
themeMode: themeController.themeMode,
)
Both are built by the private AppTheme._build(AppPalette p) factory, which configures:
| Component | What is configured |
|---|
colorScheme | primary = primaryBtnBg, secondary = accent, surface = surface1, error = error |
appBarTheme | Transparent elevation, canvas background, system overlay style matches brightness |
cardTheme | Zero elevation, surface1 color, radiusLg (24 dp) corners |
sliderTheme | Active track = accent, thumb = primaryBtnBg, inactive track = surface2 |
switchTheme | Selected track = primaryBtnBg, selected thumb = white, unselected = hairline/inkMuted |
chipTheme | Background = surface2, selected = blockLime, label style = AppTypography.caption, pill shape |
snackBarTheme | Background = ink, text = canvas, floating behavior, radiusMd corners |
progressIndicatorTheme | Color = accent (brand green) |
AppTheme._build also sets useMaterial3: true, fontFamily: 'Inter', scaffoldBackgroundColor: p.canvas, and registers the palette as a ThemeExtension.
A custom AppScrollBehavior (extends MaterialScrollBehavior) removes the Android overscroll stretch/glow effect and applies ClampingScrollPhysics globally.
Typography
AppTypography provides static factory methods for every text style used in the app. All styles use Inter via google_fonts, with runtime fetching disabled to ensure the app works fully offline:
GoogleFonts.config.allowRuntimeFetching = false;
| Method | Size | Weight | Usage |
|---|
displayXl(p) | 48 sp | 400 | Hero numbers |
displayLg(p) | 40 sp | 400 | Large displays |
displayMd(p) | 28 sp | 600 | Section headers |
headline(p) | 28 sp | 600 | Screen titles |
subhead(p) | 24 sp | 400 | Sub-titles |
cardTitle(p) | 22 sp | 700 | Card headings |
bodyLg(p) | 19 sp | 400 | Lead body text |
body(p) | 17 sp | 400 | Standard body text |
bodySm(p) | 15 sp | 400 | Secondary body text |
button(p) | 17 sp | 600 | CTA labels |
caption(p) | 13 sp | 500 | Chips, labels |
eyebrow(p) | 12 sp | 400 | JetBrains Mono — section eyebrows |
micro(p) | 12 sp | 400 | Timestamps, micro labels |
timerDisplay(p) | 56 sp | 700 | Active break timer |
All style factory methods accept an optional color: override parameter. AppTypography.textTheme(AppPalette) maps these styles to the standard TextTheme slots used by AppTheme._build.
Spacing
AppSpacing provides a base-8pt spacing scale and named border-radius constants used throughout the codebase:
| Constant | Value | Usage |
|---|
radiusXs | 2 dp | Tight radius |
radiusSm | 6 dp | Small cards |
radiusMd | 8 dp | Snack bar, modal sheets |
radiusLg | 24 dp | Cards, main containers |
radiusXl | 32 dp | Large containers |
radiusPill | 50 dp | Chips, pill buttons |
radiusFull | 9999 dp | Fully circular |
Color Blocks
AppPalette includes 7 semantic color blocks used by SpotlightCard variants. Each block has a paired text color verified for WCAG AA compliance (≥ 4.5:1 contrast ratio):
| Block token | Light bg | Text token | Contrast |
|---|
blockLime | #E8F5A8 | blockLimeText #182E00 | 13:1 |
blockMint | #C8E488 | blockMintText #082400 | 11:1 |
blockLilac | #DCE4FF | blockLilacText #030A8C | 14:1 |
blockPink | #BFC8FF | blockPinkText #030A8C | 11:1 |
blockCream | #EDE8C8 | blockCreamText #2A2004 | 12:1 |
blockCoral | #EDE0A0 | blockCoralText #26190A | 12:1 |
blockNavy | #030A8C | blockNavyText #E8EEFF | 15:1 |
Dark-mode block values use much deeper shades of the same hue families (e.g., blockLime becomes #243600) with correspondingly lighter text tokens to maintain WCAG AA ratios on dark backgrounds.
The SpotlightVariant enum (teal, violet, magenta, orange, coral, warm) maps to block/text token pairs via AppPalette.blockForVariant() and AppPalette.blockTextForVariant().
Colorblind Filter
When AccessibilitySettings.colorBlind == true, the root of the app wraps the entire widget tree in a ColorFiltered widget using a deuteranopia simulation matrix:
ColorFiltered(
colorFilter: ColorFilter.matrix([
0.625, 0.375, 0, 0, 0,
0.700, 0.300, 0, 0, 0,
0, 0.300, 0.7, 0, 0,
0, 0, 0, 1, 0,
]),
child: child,
)
This matrix simulates deuteranopia (green-deficiency) and is toggled via the Modo daltónico / Ñawi tullpu rikuy switch in Settings.
ThemeController
ThemeController(StorageService) is a ChangeNotifier that manages themeMode. It is provided at the root widget tree via Provider.
// Read current theme mode
final mode = context.watch<ThemeController>().themeMode;
// Persist and apply a new theme mode
context.read<ThemeController>().setThemeMode(ThemeMode.dark);
setThemeMode() writes the new value to StorageService and calls notifyListeners(), which causes MaterialApp’s themeMode parameter to rebuild with the new value.