From flutter-skills
Customizes the visual appearance of a Flutter app using the theming system. Use when defining global styles, colors, or typography for an application.
npx claudepluginhub gsmlg-dev/code-agent --plugin flutter-skillsThis skill uses the workspace's default tool permissions.
- [Core Theming Concepts](#core-theming-concepts)
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Guides MCP server integration in Claude Code plugins via .mcp.json or plugin.json configs for stdio, SSE, HTTP types, enabling external services as tools.
Flutter applies styling in a strict hierarchy: styles applied to the specific widget -> themes that override the immediate parent theme -> the main app theme.
theme property of MaterialApp with a ThemeData instance.Theme widget and using Theme.of(context).copyWith(...).ThemeData properties:
accentColor with colorScheme.secondary.accentTextTheme with textTheme (using colorScheme.onSecondary for contrast).AppBarTheme.color with AppBarTheme.backgroundColor.Material 3 is the default theme as of Flutter 3.16.
ColorScheme.fromSeed(seedColor: Colors.blue). This ensures accessible contrast ratios.ColorScheme.surfaceTint to indicate elevation instead of just drop shadows. To revert to M2 shadow behavior, set surfaceTint: Colors.transparent and define a shadowColor.letterSpacing on the specific TextStyle.BottomNavigationBar with NavigationBar.Drawer with NavigationDrawer.ToggleButtons with SegmentedButton.FilledButton for a high-emphasis button without the elevation of ElevatedButton.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: Use CardThemeData (Not CardTheme)dialogTheme: Use DialogThemeData (Not DialogTheme)tabBarTheme: Use TabBarThemeData (Not TabBarTheme)appBarTheme: Use AppBarThemeData (Not AppBarTheme)bottomAppBarTheme: Use BottomAppBarThemeData (Not BottomAppBarTheme)inputDecorationTheme: Use InputDecorationThemeData (Not InputDecorationTheme)Legacy button classes (FlatButton, RaisedButton, OutlineButton) are obsolete.
TextButton, ElevatedButton, and OutlinedButton.ButtonStyle object.TextButton.styleFrom(foregroundColor: Colors.blue).MaterialStateProperty.resolveWith.When building adaptive apps, respect platform-specific norms to reduce cognitive load and build user trust.
thumbVisibility on the Scrollbar widget based on the platform.SelectableText or SelectableText.rich.Row with TextDirection.rtl for Windows and TextDirection.ltr for others.Tooltip for hover states and use context menu packages for right-click actions.Use this workflow when updating an older Flutter codebase.
Task Progress:
useMaterial3: false from ThemeData (it is true by default).ColorScheme definitions with ColorScheme.fromSeed().accentColor, accentColorBrightness, accentIconTheme, and accentTextTheme.AppBarTheme(color: ...) and replace with backgroundColor.ThemeData component properties to use *ThemeData classes (e.g., cardTheme: CardThemeData()).FlatButton -> TextButton, RaisedButton -> ElevatedButton, OutlineButton -> OutlinedButton).BottomNavigationBar -> NavigationBar, Drawer -> NavigationDrawer).Use this workflow when building a widget intended for both mobile and desktop/web.
Task Progress:
Scrollbar and set thumbVisibility: DeviceType.isDesktop.SelectableText instead of Text.TextDirection.rtl on the button Row.Tooltip widgets to support mouse hover states.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(),
);
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'),
)
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'),
),
],
)