Implementing Flutter Theming and Adaptive Design
SkillDev toolsCustomizes the visual appearance of a Flutter app using the theming system. Use when defining global styles, colors, or typography for an application.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Implementing Flutter Theming and Adaptive Design skill
What this skill tells your AI
The instructions your AI receives, as published by shangjin-xiao/thoughtecho in .agents/skills/flutter-theming-apps/SKILL.md and read by ahel’s review.
Contents
- Core Theming Concepts
- Material 3 Guidelines
- Component Theme Normalization
- Button Styling
- Platform Idioms & Adaptive Design
- Workflows
- Examples
Core Theming Concepts
Flutter applies styling in a strict hierarchy: styles applied to the specific widget -> themes that override the immediate parent theme -> the main app theme.
- Define app-wide themes using the
themeproperty ofMaterialAppwith aThemeDatainstance. - Override themes for specific widget subtrees by wrapping them in a
Themewidget and usingTheme.of(context).copyWith(...). - Do not use deprecated
ThemeDataproperties:- Replace
accentColorwithcolorScheme.secondary. - Replace
accentTextThemewithtextTheme(usingcolorScheme.onSecondaryfor contrast). - Replace
AppBarTheme.colorwithAppBarTheme.backgroundColor.
- Replace
Material 3 Guidelines
Material 3 is the default theme as of Flutter 3.16.
- Colors: Generate color schemes using
ColorScheme.fromSeed(seedColor: Colors.blue). This ensures accessible contrast ratios. - Elevation: Material 3 uses
ColorScheme.surfaceTintto indicate elevation instead of just drop shadows. To revert to M2 shadow behavior, setsurfaceTint: Colors.transparentand define ashadowColor. - Typography: Material 3 updates font sizes, weights, and line heights. If text wrapping breaks legacy layouts, adjust
letterSpacingon the specificTextStyle. - Modern Components:
- Replace
BottomNavigationBarwithNavigationBar. - Replace
DrawerwithNavigationDrawer. - Replace
ToggleButtonswithSegmentedButton. - Use
FilledButtonfor a high-emphasis button without the elevation ofElevatedButton.
- Replace
Component Theme Normalization
Component themes in ThemeData have been normalized to use *ThemeData classes rather than *Theme widgets.
When defining ThemeData, strictly use the *ThemeData suffix for the following properties:
cardTheme: UseCardThemeData(NotCardTheme)dialogTheme: UseDialogThemeData(NotDialogTheme)tabBarTheme: UseTabBarThemeData(NotTabBarTheme)appBarTheme: UseAppBarThemeData(NotAppBarTheme)bottomAppBarTheme: UseBottomAppBarThemeData(NotBottomAppBarTheme)inputDecorationTheme: UseInputDecorationThemeData(NotInputDecorationTheme)
Button Styling
Legacy button classes (FlatButton, RaisedButton, OutlineButton) are obsolete.
- Use
TextButton,ElevatedButton, andOutlinedButton. - Configure button appearance using a
ButtonStyleobject. - For simple overrides based on the theme's color scheme, use the static utility method:
TextButton.styleFrom(foregroundColor: Colors.blue). - For state-dependent styling (hovered, focused, pressed, disabled), use
MaterialStateProperty.resolveWith.
Platform Idioms & Adaptive Design
When building adaptive apps, respect platform-specific norms to reduce cognitive load and build user trust.
- Scrollbars: Desktop users expect omnipresent scrollbars; mobile users expect them only during scrolling. Toggle
thumbVisibilityon theScrollbarwidget based on the platform. - Selectable Text: Web and desktop users expect text to be selectable. Wrap text in
SelectableTextorSelectableText.rich. - Horizontal Button Order: Windows places confirmation buttons on the left; macOS/Linux place them on the right. Use a
RowwithTextDirection.rtlfor Windows andTextDirection.ltrfor others. - Context Menus & Tooltips: Desktop users expect hover and right-click interactions. Implement
Tooltipfor hover states and use context menu packages for right-click actions.
Workflows
Workflow: Migrating Legacy Themes to Material 3
Use this workflow when updating an older Flutter codebase.
Task Progress:
- 1. Remove
useMaterial3: falsefromThemeData(it is true by default). - 2. Replace manual
ColorSchemedefinitions withColorScheme.fromSeed(). - 3. Run validator -> review errors -> fix: Search for and replace deprecated
accentColor,accentColorBrightness,accentIconTheme, andaccentTextTheme. - 4. Run validator -> review errors -> fix: Search for
AppBarTheme(color: ...)and replace withbackgroundColor. - 5. Update
ThemeDatacomponent properties to use*ThemeDataclasses (e.g.,cardTheme: CardThemeData()). - 6. Replace legacy buttons (
FlatButton->TextButton,RaisedButton->ElevatedButton,OutlineButton->OutlinedButton). - 7. Replace legacy navigation components (
BottomNavigationBar->NavigationBar,Drawer->NavigationDrawer).
Workflow: Implementing Adaptive UI Components
Use this workflow when building a widget intended for both mobile and desktop/web.
Task Progress:
- 1. If displaying a list/grid, wrap it in a
Scrollbarand setthumbVisibility: DeviceType.isDesktop. - 2. If displaying read-only data, use
SelectableTextinstead ofText. - 3. If implementing a dialog with action buttons, check the platform. If Windows, set
TextDirection.rtlon the buttonRow. - 4. If implementing interactive elements, wrap them in
Tooltipwidgets to support mouse hover states.
Examples
Example: Modern Material 3 ThemeData Setup
MaterialApp(
title: 'Adaptive App',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.deepPurple,
brightness: Brightness.light,
),
// Use *ThemeData classes for component normalization
appBarTheme: const AppBarThemeData(
backgroundColor: Colors.deepPurple, // Do not use 'color'
elevation: 0,
),
cardTheme: const CardThemeData(
elevation: 2,
),
textTheme: const TextTheme(
bodyMedium: TextStyle(letterSpacing: 0.2),
),
),
home: const MyHomePage(),
);
Example: State-Dependent ButtonStyle
TextButton(
style: ButtonStyle(
// Default color
foregroundColor: MaterialStateProperty.all<Color>(Colors.blue),
// State-dependent overlay color
overlayColor: MaterialStateProperty.resolveWith<Color?>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.hovered)) {
return Colors.blue.withOpacity(0.04);
}
if (states.contains(MaterialState.focused) || states.contains(MaterialState.pressed)) {
return Colors.blue.withOpacity(0.12);
}
return null; // Defer to the widget's default.
},
),
),
onPressed: () {},
child: const Text('Adaptive Button'),
)
Example: Adaptive Dialog Button Order
Row(
// Windows expects confirmation on the left (RTL reverses the standard LTR Row)
textDirection: Platform.isWindows ? TextDirection.rtl : TextDirection.ltr,
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text('Cancel'),
),
FilledButton(
onPressed: () => Navigator.pop(context, true),
child: const Text('Confirm'),
),
],
)
Signals
- GitHub stars
- 45
- Forks
- 6
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
flutter-theming-apps- Source
- github.com/shangjin-xiao/thoughtecho