Fifty Theme

pub package License: MIT

Generates Material ThemeData from your fifty_tokens configuration -- configure your brand once, theme everywhere.

A complete Flutter theming layer that reads from fifty_tokens and produces fully wired ThemeData with 25+ component themes, a custom ThemeExtension for semantic colors, shadows, and motion, and zero-config dark/light mode support. Part of Fifty Flutter Kit.


The Pipeline

FiftyTokens.configure(colors: yourBrand)
         |
         v
FiftyTheme.light() / .dark()       <-- reads from FiftyTokens.active
         |
         v
Complete Material ThemeData         <-- colorScheme, textTheme, 25+ component themes
         |
         v
Your entire app themed

Set your brand in fifty_tokens, call FiftyTheme.light() or FiftyTheme.dark(), and every Material widget in your app inherits your design decisions.


Quick Start

Installation

dependencies:
  fifty_theme: ^3.0.0

For contributors using the monorepo:

dependencies:
  fifty_theme:
    path: ../fifty_theme

Dependency: fifty_tokens

Use

import 'package:fifty_theme/fifty_theme.dart';

GetMaterialApp(
  theme: FiftyTheme.light(),
  darkTheme: FiftyTheme.dark(),
);

That is it. Zero config gives you the FDL v2 "Sophisticated Warm" palette in both modes.


Brand Configuration

The power of this package is that you never touch FiftyTheme directly to change your brand. You configure fifty_tokens and the theme follows.

import 'package:fifty_tokens/fifty_tokens.dart';
import 'package:fifty_theme/fifty_theme.dart';

// 1. Configure your brand
FiftyTokens.configure(
  colors: FiftyPreset.fdlV2.colors.copyWith(
    primary: Color(0xFF586994),     // your brand color
    onPrimary: Color(0xFFFFFFFF),
  ),
);

// 2. Theme auto-generates from your tokens
// FiftyTheme.light() reads FiftyColors.primary -> colorScheme.primary
// FiftyTheme.dark()  reads FiftyColors.backgroundDark -> scaffold background
GetMaterialApp(
  theme: FiftyTheme.light(),
  darkTheme: FiftyTheme.dark(),
);

Change the tokens, the theme changes. No manual color wiring needed.


Preset Switching

Swap the entire visual identity of your app at runtime with a single call:

// Switch to Baltic Blue preset
FiftyTokens.load(FiftyPreset.balticBlue);
Get.forceAppUpdate();  // entire app re-themes instantly

// Back to default
FiftyTokens.reset();
Get.forceAppUpdate();

Or load from JSON:

final preset = FiftyPreset.fromMap(jsonDecode(jsonString));
FiftyTokens.load(preset);
Get.forceAppUpdate();

What Gets Generated

FiftyTheme.dark() and FiftyTheme.light() produce a complete ThemeData with every slot wired to your tokens.

ColorScheme Mapping

Material Role Token Source Purpose
primary FiftyColors.primary Brand, buttons, CTAs, focus
secondary FiftyColors.secondary Secondary actions
tertiary FiftyColors.success Success states
surface backgroundDark / background Scaffold, app bar
surfaceContainerHighest surfaceDark / surface Cards, dialogs, panels
error FiftyColors.error Destructive actions
outline borderDark / borderLight Borders and dividers

TextTheme

Built from FiftyTypography tokens via FiftyFontResolver. Defaults to Manrope via google_fonts. Override with:

FiftyTheme.dark(fontFamily: 'Inter', fontSource: FontSource.asset);

Component Themes (25+)

All derived from the ColorScheme -- no hardcoded colors anywhere:

  • Buttons: elevated, outlined, text, FAB
  • Surfaces: card, dialog, bottom sheet, drawer
  • Inputs: text field, checkbox, radio, switch, slider, chip
  • Navigation: app bar, bottom nav, navigation rail, tab bar
  • Feedback: snack bar, tooltip, progress indicator
  • Menus: popup, dropdown
  • Other: divider, list tile, icon, scrollbar

FiftyThemeExtension

Exposes tokens that have no Material equivalent:

final fifty = Theme.of(context).extension<FiftyThemeExtension>()!;

// Semantic colors
fifty.accent;      // mode-aware accent (dark: FiftyColors.accent, light: primary)
fifty.success;     // FiftyColors.success
fifty.warning;     // FiftyColors.warning
fifty.info;        // FiftyColors.secondary

// Shadows
fifty.shadowSm;    // subtle elevation
fifty.shadowMd;    // cards
fifty.shadowLg;    // modals
fifty.shadowPrimary; // primary buttons
fifty.shadowGlow;  // dark mode accent glow (none in light)

// Motion
fifty.fast;        // 150ms -- hover, micro-interactions
fifty.compiling;   // 300ms -- panel reveals
fifty.systemLoad;  // 800ms -- staggered entry
fifty.standardCurve;
fifty.enterCurve;
fifty.exitCurve;

Customization Levels

Level 1: Zero Config

FDL v2 defaults:

GetMaterialApp(theme: FiftyTheme.dark());

Level 2: Token-Level

Override tokens globally -- theme follows automatically:

FiftyTokens.configure(
  colors: FiftyPreset.fdlV2.colors.copyWith(primary: Color(0xFF1A73E8)),
);
GetMaterialApp(theme: FiftyTheme.dark());

Level 3: Theme-Level

Pass overrides directly to FiftyTheme:

FiftyTheme.dark(
  primaryColor: Color(0xFF1A73E8),
  secondaryColor: Color(0xFF34A853),
  fontFamily: 'Inter',
  fontSource: FontSource.asset,
);

Or a full ColorScheme:

FiftyTheme.dark(
  colorScheme: ColorScheme.dark(
    primary: Color(0xFF1A73E8),
    secondary: Color(0xFF34A853),
  ),
);

Level 4: Widget-Level

Override individual component themes after generation:

final theme = FiftyTheme.dark().copyWith(
  elevatedButtonTheme: ElevatedButtonThemeData(
    style: ElevatedButton.styleFrom(backgroundColor: Colors.blue),
  ),
);

FiftyThemeExtension Override

FiftyTheme.dark(
  extension: FiftyThemeExtension.dark(
    accent: Color(0xFFFF6B6B),
    success: Color(0xFF00C853),
  ),
);

Core Components

Component Description
FiftyTheme Main entry point. dark() and light() assemble complete ThemeData.
FiftyColorScheme Maps FiftyColors tokens to Material ColorScheme for both modes.
FiftyTextTheme Builds TextTheme from FiftyTypography tokens via FiftyFontResolver.
FiftyComponentThemes 25+ static methods returning configured component theme objects.
FiftyThemeExtension Custom ThemeExtension with semantic colors, shadows, and motion tokens.

Platform Support

Platform Support Notes
Android Yes OLED optimization benefits AMOLED screens
iOS Yes
macOS Yes
Linux Yes
Windows Yes
Web Yes Manrope loaded via Google Fonts CDN

Ecosystem

fifty_tokens  (design tokens -- foundation)
    |
    v
fifty_theme   (this package -- Flutter ThemeData)
    |
    v
fifty_ui      (component library)

fifty_theme sits between the raw tokens and the widget layer. It reads whatever fifty_tokens has configured and translates it into Material's theming system. Consuming packages and widgets never need to reference token values directly for standard Material properties.


Version

Current: 3.0.0


License

MIT License - see LICENSE for details.

Part of Fifty Flutter Kit.

Libraries

fifty_theme
Flutter theming layer for the fifty.dev ecosystem.