Theming
FlAI uses a complete design token system with 4 built-in presets. Customize colors, typography, spacing, and border radii to match your app's design.
FlaiTheme
Wrap your widget tree with FlaiTheme to provide the theme to all FlAI components:
FlaiTheme(
data: FlaiThemeData.dark(),
child: FlaiChatScreen(
controller: controller,
),
)
Access the theme anywhere in the tree:
final theme = FlaiTheme.of(context);
// Use theme tokens
Container(
color: theme.colors.background,
padding: EdgeInsets.all(theme.spacing.md),
child: Text(
'Hello',
style: theme.typography.bodyBase(
color: theme.colors.foreground,
),
),
)
Theme Presets
FlAI ships with 4 production-ready presets:
| Preset | Constructor | Description |
|---|---|---|
| Light | FlaiThemeData.light() |
Clean white/zinc theme. Similar to ChatGPT light mode. |
| Dark | FlaiThemeData.dark() |
Dark zinc theme. Deep blacks with zinc accents. |
| iOS | FlaiThemeData.ios() |
Apple Messages style. System blue, larger radii. |
| Premium | FlaiThemeData.premium() |
Linear-inspired dark theme. Indigo accents, ultra-dark background. |
Color Tokens
The FlaiColors class defines 22 semantic color tokens used throughout all components:
Base Colors
Semantic Colors
Chat-Specific Colors
Colors shown above are from the Dark preset.
Typography
The FlaiTypography class provides a type scale with methods for generating TextStyle objects:
| Method | Size | Weight | Usage |
|---|---|---|---|
| bodySmall() | 12px | 400 | Captions, timestamps, labels |
| bodyBase() | 14px | 400 | Body text, messages |
| bodyLarge() | 16px | 400 | Emphasized body text |
| heading() | 20px | 600 | Section headings |
| headingLarge() | 24px | 700 | Page titles |
| mono() | 12px | 400 | Code, monospace text |
All methods accept an optional color parameter:
Text(
'Hello world',
style: theme.typography.bodyBase(
color: theme.colors.foreground,
),
)
// Monospace with custom size
Text(
'print("hello")',
style: theme.typography.mono(
color: theme.colors.accent,
fontSize: 14,
),
)
Spacing
Consistent spacing tokens via FlaiSpacing:
| Token | Default | Usage |
|---|---|---|
| xs | 4.0 | Tight gaps, chip padding |
| sm | 8.0 | Small gaps, inline spacing |
| md | 16.0 | Standard padding, margins |
| lg | 24.0 | Section spacing |
| xl | 32.0 | Large gaps, page margins |
| xxl | 48.0 | Hero spacing |
Border Radii
Border radius tokens via FlaiRadius:
| Token | Default | iOS Preset |
|---|---|---|
| sm | 4.0 | 8.0 |
| md | 8.0 | 12.0 |
| lg | 12.0 | 18.0 |
| xl | 16.0 | 22.0 |
| full | 9999 | 9999 |
Custom Themes
Create a fully custom theme using FlaiThemeData and FlaiColors directly:
final myTheme = FlaiThemeData(
colors: FlaiColors(
background: Color(0xFF0F172A),
foreground: Color(0xFFF8FAFC),
card: Color(0xFF1E293B),
cardForeground: Color(0xFFF8FAFC),
popover: Color(0xFF1E293B),
popoverForeground: Color(0xFFF8FAFC),
primary: Color(0xFF38BDF8),
primaryForeground: Color(0xFF0C4A6E),
secondary: Color(0xFF1E293B),
secondaryForeground: Color(0xFFF8FAFC),
muted: Color(0xFF334155),
mutedForeground: Color(0xFF94A3B8),
accent: Color(0xFF38BDF8),
accentForeground: Color(0xFFFFFFFF),
destructive: Color(0xFFEF4444),
destructiveForeground: Color(0xFFFFFFFF),
border: Color(0xFF1E293B),
input: Color(0xFF1E293B),
ring: Color(0xFF38BDF8),
userBubble: Color(0xFF38BDF8),
userBubbleForeground: Color(0xFF0C4A6E),
assistantBubble: Color(0xFF1E293B),
assistantBubbleForeground: Color(0xFFF8FAFC),
),
typography: FlaiTypography(
fontFamily: 'SF Pro Display',
monoFontFamily: 'JetBrains Mono',
),
);
Or modify an existing preset with copyWith:
final customDark = FlaiThemeData.dark().copyWith(
colors: FlaiColors.dark().copyWith(
primary: Color(0xFF38BDF8),
userBubble: Color(0xFF38BDF8),
accent: Color(0xFF38BDF8),
),
);