Guides
Customizing Themes
Generate and customize themes and widget styles using the CLI.
This guide uses FAccordionStyle
as an example, but the same principles apply to all Forui widgets. It relies on the CLI.
Generate main.dart
Navigate to your project directory.
Generate a main.dart:
dart run forui initThis generates a main.dart file where you will add your generated theme:
12import 'package:flutter/material.dart';34import 'package:forui/forui.dart';56import 'theme.dart';78void main() {9 runApp(const Application());10}1112class Application extends StatelessWidget {13 const Application({super.key});1415 @override16 Widget build(BuildContext context) {17 // Assign the generated theme to `theme`.18 final theme = neutralLight;1920 return MaterialApp(21 localizationsDelegates: FLocalizations.localizationsDelegates,22 supportedLocales: FLocalizations.supportedLocales,23 builder: (_, child) => FTheme(24 data: theme,25 child: FToaster(child: FTooltipGroup(child: child!)),26 ),27 theme: theme.toApproximateMaterialTheme(),28 home: const FScaffold(29 // TODO: replace with your widget.30 child: Placeholder(),31 ),32 );33 }34}35Generate a Style
Tip: Run dart run forui style ls to see all available styles.
Generate a FAccordionStyle:
dart run forui style create accordionThis generates an accordion style file which you can add to your theme:
1FAccordionStyle accordionStyle({2 required FColors colors,3 required FTypography typography,4 required FStyle style,5}) => FAccordionStyle(6 titleTextStyle: FVariants.from(7 // This text style is applied when the accordion is NOT hovered OR pressed.8 typography.md.copyWith(fontWeight: .w500, color: colors.foreground),9 variants: {10 // This text style is applied when the accordion is hovered OR pressed.11 [.hovered, .pressed]: .delta(decoration: () => .underline),12 // {@endhiglight}13 },14 ),15 childTextStyle: typography.sm.copyWith(color: colors.foreground),16 iconStyle: .all(IconThemeData(color: colors.mutedForeground, size: 20)),17 focusedOutlineStyle: style.focusedOutlineStyle,18 dividerStyle: FDividerStyle(color: colors.border, padding: .zero),19 tappableStyle: style.tappableStyle.copyWith(20 motion: const .delta(bounceTween: FTappableMotion.noBounceTween),21 ),22 titlePadding: const .symmetric(vertical: 15),23 childPadding: const .only(bottom: 15),24 motion: const FAccordionMotion(),25);26To learn how to customize widget styles, see the customizing widget styles guide.
Generate a Theme
Tip: Run dart run forui theme ls to see all available themes.
Generate a theme based on neutral's light variant:
dart run forui theme create neutral-lightThis generates a theme file which you can:
- add to your generated
main.dart. - add the generated styles to.
12import 'package:flutter/material.dart';34import 'package:forui/forui.dart';56import 'accordion_style.dart';789FThemeData get neutralLight {10 // Change this to false to generate a desktop variant of the theme.11 const touch = true;1213 const colors = FColors(14 brightness: .light,15 systemOverlayStyle: .dark,16 barrier: Color(0x33000000),17 background: Color(0xFFFFFFFF),18 foreground: Color(0xFF0A0A0A),19 primary: Color(0xFF171717),20 primaryForeground: Color(0xFFFAFAFA),21 secondary: Color(0xFFF5F5F5),22 secondaryForeground: Color(0xFF171717),23 muted: Color(0xFFF5F5F5),24 mutedForeground: Color(0xFF737373),25 destructive: Color(0xFFE7000B),26 destructiveForeground: Color(0xFFFAFAFA),27 error: Color(0xFFE7000B),28 errorForeground: Color(0xFFFAFAFA),29 card: Color(0xFFFFFFFF),30 border: Color(0xFFE5E5E5),31 );3233 final typography = _typography(colors: colors, touch: touch);34 final style = _style(colors: colors, typography: typography, touch: touch);3536 return FThemeData(37 colors: colors,38 typography: typography,39 style: style,40 touch: touch,41 );42}4344FTypography _typography({45 required FColors colors,46 required bool touch,47 String fontFamily = 'packages/forui/Inter',48}) {49 assert(50 fontFamily.isNotEmpty,51 'fontFamily ($fontFamily) should not be empty.',52 );53 final color = colors.foreground;54 final font = fontFamily;55 if (touch) {56 return FTypography(57 fontFamily: fontFamily,58 xs3: TextStyle(59 color: color,60 fontFamily: font,61 fontSize: 10,62 height: 1,63 leadingDistribution: .even,64 ),65 xs2: TextStyle(66 color: color,67 fontFamily: font,68 fontSize: 12,69 height: 1,70 leadingDistribution: .even,71 ),72 xs: TextStyle(73 color: color,74 fontFamily: font,75 fontSize: 14,76 height: 1.25,77 leadingDistribution: .even,78 ),79 sm: TextStyle(80 color: color,81 fontFamily: font,82 fontSize: 16,83 height: 1.5,84 leadingDistribution: .even,85 ),86 md: TextStyle(87 color: color,88 fontFamily: font,89 fontSize: 18,90 height: 1.75,91 leadingDistribution: .even,92 ),93 lg: TextStyle(94 color: color,95 fontFamily: font,96 fontSize: 20,97 height: 1.75,98 leadingDistribution: .even,99 ),100 xl: TextStyle(101 color: color,102 fontFamily: font,103 fontSize: 22,104 height: 2,105 leadingDistribution: .even,106 ),107 xl2: TextStyle(108 color: color,109 fontFamily: font,110 fontSize: 30,111 height: 2.25,112 leadingDistribution: .even,113 ),114 xl3: TextStyle(115 color: color,116 fontFamily: font,117 fontSize: 36,118 height: 2.5,119 leadingDistribution: .even,120 ),121 xl4: TextStyle(122 color: color,123 fontFamily: font,124 fontSize: 48,125 height: 1,126 leadingDistribution: .even,127 ),128 xl5: TextStyle(129 color: color,130 fontFamily: font,131 fontSize: 60,132 height: 1,133 leadingDistribution: .even,134 ),135 xl6: TextStyle(136 color: color,137 fontFamily: font,138 fontSize: 72,139 height: 1,140 leadingDistribution: .even,141 ),142 xl7: TextStyle(143 color: color,144 fontFamily: font,145 fontSize: 96,146 height: 1,147 leadingDistribution: .even,148 ),149 xl8: TextStyle(150 color: color,151 fontFamily: font,152 fontSize: 108,153 height: 1,154 leadingDistribution: .even,155 ),156 );157 } else {158 return FTypography(159 fontFamily: fontFamily,160 xs3: TextStyle(161 color: color,162 fontFamily: font,163 fontSize: 8,164 height: 1,165 leadingDistribution: .even,166 ),167 xs2: TextStyle(168 color: color,169 fontFamily: font,170 fontSize: 10,171 height: 1,172 leadingDistribution: .even,173 ),174 xs: TextStyle(175 color: color,176 fontFamily: font,177 fontSize: 12,178 height: 1,179 leadingDistribution: .even,180 ),181 sm: TextStyle(182 color: color,183 fontFamily: font,184 fontSize: 14,185 height: 1.25,186 leadingDistribution: .even,187 ),188 md: TextStyle(189 color: color,190 fontFamily: font,191 fontSize: 16,192 height: 1.5,193 leadingDistribution: .even,194 ),195 lg: TextStyle(196 color: color,197 fontFamily: font,198 fontSize: 18,199 height: 1.75,200 leadingDistribution: .even,201 ),202 xl: TextStyle(203 color: color,204 fontFamily: font,205 fontSize: 20,206 height: 1.75,207 leadingDistribution: .even,208 ),209 xl2: TextStyle(210 color: color,211 fontFamily: font,212 fontSize: 22,213 height: 2,214 leadingDistribution: .even,215 ),216 xl3: TextStyle(217 color: color,218 fontFamily: font,219 fontSize: 30,220 height: 2.25,221 leadingDistribution: .even,222 ),223 xl4: TextStyle(224 color: color,225 fontFamily: font,226 fontSize: 36,227 height: 2.5,228 leadingDistribution: .even,229 ),230 xl5: TextStyle(231 color: color,232 fontFamily: font,233 fontSize: 48,234 height: 1,235 leadingDistribution: .even,236 ),237 xl6: TextStyle(238 color: color,239 fontFamily: font,240 fontSize: 60,241 height: 1,242 leadingDistribution: .even,243 ),244 xl7: TextStyle(245 color: color,246 fontFamily: font,247 fontSize: 72,248 height: 1,249 leadingDistribution: .even,250 ),251 xl8: TextStyle(252 color: color,253 fontFamily: font,254 fontSize: 96,255 height: 1,256 leadingDistribution: .even,257 ),258 );259 }260}261262FStyle _style({263 required FColors colors,264 required FTypography typography,265 required bool touch,266}) {267 const borderRadius = FBorderRadius();268 return FStyle(269 formFieldStyle: .inherit(270 colors: colors,271 typography: typography,272 touch: touch,273 ),274 focusedOutlineStyle: FFocusedOutlineStyle(275 color: colors.primary,276 borderRadius: borderRadius.md,277 ),278 iconStyle: IconThemeData(279 color: colors.foreground,280 size: typography.lg.fontSize,281 ),282 sizes: FSizes.inherit(touch: touch),283 tappableStyle: FTappableStyle(),284 borderRadius: const FBorderRadius(),285 borderWidth: 1,286 pagePadding: const .symmetric(vertical: 8, horizontal: 12),287 shadow: const [288 BoxShadow(color: Color(0x0d000000), offset: Offset(0, 1), blurRadius: 2),289 ],290 );291}292