CodeBlanks Logo Icon CodeBlanks

Challenge 4

Build a multi-theme design system with tokens and ThemeExtension.

Multi-theme with tokens and ThemeExtension

Tokens gather design values in one place; ThemeExtension adds these values as custom fields in ThemeData. You define separate token sets for light and dark themes, registering each with a distinct AppColors extension. The extensions parameter attaches the extension to ThemeData.

class AppTokens {
  static const Color lightBrand = Color(0xFF1A73E8);
  static const Color darkBrand = Color(0xFF66A8FF);
}

ThemeData lightTheme = ThemeData(
  extensions: [const AppColors(brand: AppTokens.lightBrand)],
);

Practice Write tokens and AppColors

Define two Color constants lightBrand (0xFF1A73E8) and darkBrand (0xFF66A8FF) in an AppTokens class. Write a ThemeExtension subclass named AppColors with a brand field, copyWith and lerp methods. In main create an AppColors with lightBrand and print brand.

Starter code

main.dart
import 'package:flutter/material.dart';

// AppTokens: iki marka rengi sabiti
// AppColors: ThemeExtension tabanlı, brand alanı
// Kopyalama ve ara değer metodlarını uygula
// main: AppColors oluştur ve brand yazdır

void main() {
}

Sample solution

main.dart
import 'package:flutter/material.dart';

class AppTokens {
  static const Color lightBrand = Color(0xFF1A73E8);
  static const Color darkBrand = Color(0xFF66A8FF);
}

class AppColors extends ThemeExtension<AppColors> {
  final Color brand;
  const AppColors({required this.brand});

  @override
  AppColors copyWith({Color? brand}) =>
      AppColors(brand: brand ?? this.brand);

  @override
  AppColors lerp(AppColors? other, double t) =>
      AppColors(brand: Color.lerp(brand, other?.brand, t)!);
}

void main() {
  final colors = const AppColors(brand: AppTokens.lightBrand);
  print(colors.brand);
}

Expected output

Color(0xff1a73e8)

Practice Light and dark themes

Write the same AppTokens and AppColors classes. In main create two AppColors instances: one with lightBrand and one with darkBrand. Print each one's brand color on a separate line.

Starter code

main.dart
import 'package:flutter/material.dart';

// AppTokens: açık ve koyu marka renkleri
// AppColors: ThemeExtension, brand alanı
// Kopyalama ve ara değer metodlarını uygula
// main: hem açık hem koyu AppColors oluştur
// Her ikisinin brand rengini yazdır

void main() {
}

Sample solution

main.dart
import 'package:flutter/material.dart';

class AppTokens {
  static const Color lightBrand = Color(0xFF1A73E8);
  static const Color darkBrand = Color(0xFF66A8FF);
}

class AppColors extends ThemeExtension<AppColors> {
  final Color brand;
  const AppColors({required this.brand});

  @override
  AppColors copyWith({Color? brand}) =>
      AppColors(brand: brand ?? this.brand);

  @override
  AppColors lerp(AppColors? other, double t) =>
      AppColors(brand: Color.lerp(brand, other?.brand, t)!);
}

void main() {
  final light = const AppColors(brand: AppTokens.lightBrand);
  final dark = const AppColors(brand: AppTokens.darkBrand);
  print(light.brand);
  print(dark.brand);
}

Expected output

Color(0xff1a73e8)
Color(0xff66a8ff)

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 How is a ThemeExtension added to a ThemeData?

  • Embedded into colorScheme
  • Via the extensions parameter Correct answer
  • With setExtension in main
  • Via the theme parameter

Explanation: ThemeData's extensions parameter takes a list; ThemeExtension instances are listed there.

2 extensions parameter

Question
ThemeData(
  ____: [const AppColors(brand: AppTokens.lightBrand)],
);
Answer
ThemeData(
  extensions: [const AppColors(brand: AppTokens.lightBrand)],
);

Explanation: The extensions parameter registers ThemeExtension instances in ThemeData; descendants access them via Theme.of(context).

3 Multi-theme system parts

Term Meaning
AppTokens Design value constants
ThemeExtension Custom theme field
extensions Extension registration in ThemeData
lerp Interpolation between themes

All lessons in Expert