Flutter · One codebase, native feel

How do you build a maintainable theme system?

Easythemingmaterial 3colorschemedark modeUpdated Oct 2026
Quiz this track

Short answer

Define ThemeData from a ColorScheme seed, centralise typography and component styles, and use ThemeMode plus ThemeExtension for custom tokens instead of hardcoded values.

Material 3 derives much of its palette from a seed colour. A single ColorScheme supplies semantic roles such as primary, surface and error. Widgets should read those roles rather than hardcoded colours, so dark mode and brand changes propagate without editing every screen.

dart
final lightScheme = ColorScheme.fromSeed(
  seedColor: const Color(0xFF0F766E),
  brightness: Brightness.light,
);

final appTheme = ThemeData(
  useMaterial3: true,
  colorScheme: lightScheme,
  filledButtonTheme: FilledButtonThemeData(
    style: FilledButton.styleFrom(
      minimumSize: const Size(48, 48),
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(12),
      ),
    ),
  ),
);
  • Use ColorScheme roles instead of raw hex values in widgets
  • Provide light and dark ThemeData and let ThemeMode follow the system when appropriate
  • Centralise text styles and component themes rather than repeating styleFrom
  • Use ThemeExtension for tokens Material does not model, such as custom spacing or brand colours
  • Check contrast ratios and do not encode meaning in colour alone

Why hardcoded styles rot

A screen that writes Colors.grey directly will look wrong in dark mode and will not follow a rebrand. A screen that reads colorScheme.outline adapts. Component themes keep interaction states consistent across the app and reduce the chance that one button forgets its disabled style.

Theming is not only colour. Text scale, touch target size, focus indication and motion settings are part of the same system and must be tested together.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1What does ColorScheme.fromSeed generate?
  2. 2When would you use a ThemeExtension?
  3. 3How do you support system dark mode?
  4. 4What accessibility checks apply to a theme?

Say it in the interview

I base the theme on a ColorScheme seed so semantic roles are consistent, and I provide light and dark variants through ThemeMode. Widgets read roles like surface and onSurface rather than raw hex values. Custom tokens go in a ThemeExtension, and component themes centralise states. Then I check contrast and large text scale because theming is broader than colour.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Flutter mock interview and get scored feedback on depth, clarity and confidence.