mydomain
No ADS
No ADS

Flutter Artist Theme - Create a custom theme

  1. Create a custom Theme
  2. FaColorTokens
  3. FaTypographyTokens
  4. FaLayoutTokens
  5. What to do after having a custom theme?
Changing your app’s appearance is not just about colors; it’s about shaping the entire user experience. With FlutterArtist Theme, you get a flexible system that allows you to define your own design language in a structured and scalable way.

1. Create a custom Theme

Let’s start by creating a custom theme by extending FaTheme. This is the foundation where you gain full control over your Design Tokens.
LeantekTheme
class LeantekTheme extends FaTheme {
  @override
  String get name => FaThemeHub.defaultThemeName;

  @override
  IconData get icon => Icons.business_center_outlined;

  @override
  Color get seedColor => const Color(0xFF056AB4);

  @override
  Brightness get brightness => Brightness.light;

  @override
  String? get fontFamily => null;

  @override
  FaThemeTokens createThemeTokens() {
    final colors = const FaColorTokens( 
      primary: Color(0xFF056AB4),
      onPrimary: Colors.white,

      secondary: Color(0xFFFF9900),
      onSecondary: Colors.black,

      tertiary: Color(0xFF22C55E),
      onTertiary: Colors.white,

      error: Color(0xFFDC2626),
      onError: Colors.white,

      background: Color(0xFFE7F0FC),
      surface: Colors.white,

      onSurface: Color(0xFF10324A),
      onSurfaceVariant: Color(0xFF5F6B7A),

      surfaceContainerLowest: Color(0xFFFFFFFF),
      surfaceContainerLow: Color(0xFFF1F7FE),
      surfaceContainer: Color(0xFFE1EDF9),
      surfaceContainerHigh: Color(0xFFD6E4F2),
      surfaceContainerHighest: Color(0xFFCCD9E7),

      textPrimary: Color(0xFF10324A),
      textSecondary: Color(0xFF5F6B7A),

      border: Color(0xFFCCD9E7),
      outline: Color(0xFFB8C6D8),
      outlineVariant: Color(0xFFCCD9E7),

      shadow: Colors.black,
      scrim: Colors.black54,

      inverseSurface: Color(0xFF1B2A38),
      onInverseSurface: Colors.white,
      inversePrimary: Color(0xFF9CCBFF),

      divider: Color(0xFFCCD9E7),
    );

    return FaThemeTokens(
      colors: colors,
      spacing: const FaSpacingTokens(xs: 4, sm: 8, md: 12, lg: 16, xl: 24),
      elevation: const FaElevationTokens(level1: 2, level2: 4, level3: 6),
      radius: const FaRadiusTokens(sm: 4, md: 8, lg: 12, xl: 16),

      typography: FaTypographyTokens(),
      components: const FaComponentTokens(),
      layout: const FaLayoutTokens(
        metrics: FaLayoutMetricsTokens(),
        colors: FaLayoutColorTokens(
          sidebarSurface: Color(0xFF10324A),
          onSidebarSurface: Colors.white,
          topbarSurface: Colors.white,
          onTopbarSurface: Color(0xFF056AB4),
        ),
      ),
      motion: const FaMotionTokens(),
    );
  }
}
To better understand how tokens work together, consider reading:

2. FaColorTokens

FaColorTokens allows you to override colors generated automatically from the seedColor. By default, the system generates a complete color palette (primary, secondary, surface, etc.). However, you can override any part when needed.
Simple Override
Only override what you actually care about.
FaColorTokens(
  primary: Color(0xFF056AB4),
  onPrimary: Colors.white,
);
No ADS
Advanced Override
When working with pixel-perfect UI/UX designs, you can fully control the color system.
FaColorTokens(
  primary: Color(0xFF056AB4),
  onPrimary: Colors.white,
  secondary: Color(0xFFFF9900),
  onSecondary: Colors.black,
  // Override more tokens as needed
  surfaceContainerLow: Color(0xFFF1F7FE),
  border: Color(0xFFCCD9E7),
);
FlutterArtist is designed so you can get started quickly…while still giving you full control when you need it.

3. FaTypographyTokens

Typography is more than just choosing a font — it determines how users “read” and “understand” your interface. In FlutterArtist, FaTypographyTokens allows you to control your entire type system consistently and scientifically.
The Flutter Typography System
Flutter provides 15 standard text styles based on Material Design, covering every possible display scenario.
  • Display: Large, Medium, Small
  • Headline: Large, Medium, Small
  • Title: Large, Medium, Small
  • Body: Large, Medium, Small
  • Label: Large, Medium, Small
But in Reality...
You won’t use all 15 styles in most applications. In most cases, only a few styles are used consistently across the app.
  • titleMedium: Used for Card titles, Dialogs or lists. Not as large as a headline, but still prominent enough for information hierarchy.
  • bodyMedium: The core content style. Used for descriptions and articles, optimized for long-term readability.
  • labelLarge: Action labels. Used for buttons and short labels, often with a higher font-weight to draw focus to actions.
No ADS
Customization Example
You can override only these critical styles instead of reconfiguring the entire system.
FaTypographyTokens(
  titleMedium: const TextStyle(
    fontSize: 16,
    fontWeight: FontWeight.w600,
    letterSpacing: 0.2,
  ),
  bodyMedium: const TextStyle(
    fontSize: 14,
    height: 1.5,
    fontWeight: FontWeight.w400,
  ),
  labelLarge: const TextStyle(
    fontSize: 14,
    fontWeight: FontWeight.w700,
    letterSpacing: 0.5,
  ),
);

4. FaLayoutTokens

Layout is more than just dimensions — it determines how users navigate and perceive your app's structure. In FlutterArtist, FaLayoutTokens empowers you to control key layout components like the Sidebar and Topbar with consistency and flexibility.
The Structure of FaLayoutTokens
The layout system is divided into two distinct parts, allowing you to separate spatial logic from aesthetic design:
  • metrics: Manages dimensions and geometric structure
  • colors: Manages specific colors for layout components.
FaLayoutTokens Example
FaLayoutTokens(
  metrics: FaLayoutMetricsTokens(
    sidebarWidth: 260,
    contentMaxWidth: null, 
  ),
  colors: FaLayoutColorTokens(
    sidebarSurface: Color(0xFF10324A),
    onSidebarSurface: Colors.white,
    topbarSurface: Colors.white,
    onTopbarSurface: Color(0xFF056AB4),
  ),
);

5. What to do after having a custom theme?

After successfully creating a custom FaTheme and registering it, there’s one important thing to keep in mind:
  • Not every value you define will automatically reflect in your UI.
Some of the properties you define will be overridden by ColorScheme and TextTheme, and Flutter will immediately apply them to standard elements such as Scaffold, AppBar, Button or Text, etc.
However, many other parts of your system — especially Theme Extensions like FaRadiusTokens, FaSpacingTokens, or layout tokens — will remain unused unless you explicitly apply them in your UI.
In other words: You’ve built a powerful design system—but you still need to activate it.
A Practical Example
Imagine you're building an Access Control Panel with a message and two action buttons.
Container(
  padding: const EdgeInsets.all(16),
  child: Row(
    children: [
      Text("Are you sure you want to grant permission?"),
      ElevatedButton(onPressed: () {}, child: Text("Cancel")),
      ElevatedButton(onPressed: () {}, child: Text("Confirm")),
    ],
  ),
)
Why is this not good enough?
At first glance, it may seem “good enough,” but in a real interface, something will feel slightly off. This layout lacks visual cohesion. The Container has no background to separate it from surrounding elements, making the whole block feel like it is “floating” in space.
Both “Cancel” and “Confirm” buttons are using the same default styling (colorScheme.primary for the background and colorScheme.onPrimary for the text). Even if you have customized colors in MyCustomTheme, having both buttons look so similar makes it hard for users to identify the primary action.
From a UX perspective, the “Confirm” button should stand out more—through color, weight, or contrast—to guide the user’s attention and support quicker, more confident decisions.
No ADS
The Professional Way with FaColorUtils
To make the interface look professional, we need to:
  • Apply a slightly different background color to the Container than the main background.
  • Use a more eye-catching color for the "Confirm" button.
  • Use a softer color for the "Cancel" button.
Container(
  padding: const EdgeInsets.all(16),
  decoration: BoxDecoration(
    color: FaColorUtils.surfaceContainerLow(context),
    borderRadius: BorderRadius.circular(context.faTokens.radius.md),
  ),
  child: Row(
    children: [
      Expanded(
        child: Text(
          "Are you sure you want to grant access?",
          style: TextStyle(
            color: FaColorUtils.primaryContent(context),
          ),
        ),
      ),
      ElevatedButton(
        onPressed: () {},
        child: Text(
          "Cancel",
          style: TextStyle(
            color: FaColorUtils.infoText(context),
          ),
        ),
      ),
      const SizedBox(width: 8),
      ElevatedButton(
        style: ElevatedButton.styleFrom(
          backgroundColor: FaColorUtils.primaryHighlight(context),
          foregroundColor: FaColorUtils.onHighlightText(context),
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(
              context.faTokens.radius.sm,
            ),
          ),
        ),
        onPressed: () {},
        child: const Text("Confirm"),
      ),
    ],
  ),
)
Creating a custom FaTheme is like building a comprehensive resource warehouse. But to turn those resources into actual products, you must still "work" by using FaColorUtils and accessing Tokens (like FaRadiusTokens) to apply them to specific Widgets.
Don't let your sophisticated settings stay hidden in the code. Master how to bring them into the real world in our next post:
No ADS

FlutterArtist

Show More
No ADS