giantToadMaterialTheme function
Builds a Material host theme from Giant Toad's canonical UI tokens.
Editor applications can use standard Flutter layout and accessibility widgets without maintaining a second, visually divergent token system.
Implementation
ThemeData giantToadMaterialTheme(GiantToadUiTheme theme, {Color? errorColor}) {
final scheme =
ColorScheme.fromSeed(
seedColor: theme.primaryColor,
brightness: Brightness.dark,
surface: theme.surfaceColor,
error: errorColor ?? const Color(0xffef6f6c),
).copyWith(
primary: theme.primaryColor,
onPrimary: theme.onPrimaryColor,
secondary: theme.secondaryColor,
surface: theme.surfaceColor,
onSurface: theme.onSurfaceColor,
outline: theme.outlineColor,
);
final border = OutlineInputBorder(
borderRadius: BorderRadius.zero,
borderSide: BorderSide(color: theme.outlineColor, width: theme.borderWidth),
);
final controlShape = RoundedRectangleBorder(
borderRadius: BorderRadius.zero,
side: BorderSide(color: theme.outlineColor, width: theme.borderWidth),
);
final controlPadding = EdgeInsets.symmetric(
horizontal: theme.padding,
vertical: theme.padding / 2,
);
return ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
colorScheme: scheme,
scaffoldBackgroundColor: theme.backgroundColor,
canvasColor: theme.surfaceColor,
cardColor: theme.surfaceColor,
dividerColor: theme.outlineColor,
focusColor: theme.primaryColor,
hoverColor: theme.primaryColor.withValues(alpha: 0.12),
fontFamily: theme.fontFamily,
iconTheme: IconThemeData(color: theme.onSurfaceColor),
inputDecorationTheme: InputDecorationTheme(
filled: true,
fillColor: theme.secondaryColor,
hintStyle: TextStyle(
color: theme.disabledColor,
fontFamily: theme.fontFamily,
fontSize: theme.fontSize * theme.displayScale,
),
labelStyle: TextStyle(
color: theme.onSurfaceColor,
fontFamily: theme.fontFamily,
fontSize: theme.fontSize * theme.displayScale,
),
floatingLabelStyle: TextStyle(
color: theme.primaryColor,
fontFamily: theme.fontFamily,
fontSize: theme.fontSize * theme.displayScale * .85,
),
isDense: true,
contentPadding: EdgeInsets.all(theme.padding),
border: border,
enabledBorder: border,
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.zero,
borderSide: BorderSide(
color: theme.primaryColor,
width: theme.borderWidth,
),
),
),
outlinedButtonTheme: OutlinedButtonThemeData(
style: OutlinedButton.styleFrom(
foregroundColor: theme.primaryColor,
side: BorderSide(color: theme.outlineColor, width: theme.borderWidth),
shape: controlShape,
padding: controlPadding,
textStyle: TextStyle(
fontFamily: theme.fontFamily,
fontSize: theme.fontSize * theme.displayScale,
),
),
),
filledButtonTheme: FilledButtonThemeData(
style: FilledButton.styleFrom(
foregroundColor: theme.onPrimaryColor,
backgroundColor: theme.primaryColor,
shape: controlShape,
padding: controlPadding,
textStyle: TextStyle(
fontFamily: theme.fontFamily,
fontSize: theme.fontSize * theme.displayScale,
),
),
),
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(
foregroundColor: theme.primaryColor,
shape: controlShape,
padding: controlPadding,
textStyle: TextStyle(
fontFamily: theme.fontFamily,
fontSize: theme.fontSize * theme.displayScale,
),
),
),
listTileTheme: ListTileThemeData(
titleTextStyle: TextStyle(
color: theme.onSurfaceColor,
fontFamily: theme.fontFamily,
fontSize: theme.fontSize * theme.displayScale,
),
subtitleTextStyle: TextStyle(
color: theme.disabledColor,
fontFamily: theme.fontFamily,
fontSize: theme.fontSize * theme.displayScale * .85,
),
contentPadding: EdgeInsets.symmetric(horizontal: theme.padding),
),
cardTheme: CardThemeData(
color: theme.surfaceColor,
margin: EdgeInsets.all(theme.displayScale * 2),
shape: RoundedRectangleBorder(
side: BorderSide(color: theme.outlineColor, width: theme.borderWidth),
borderRadius: BorderRadius.zero,
),
),
visualDensity: VisualDensity.compact,
);
}