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:

PresetConstructorDescription
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

background
foreground
card
cardForeground
muted
mutedForeground
border
input

Semantic Colors

primary
primaryForeground
secondary
accent
destructive
ring

Chat-Specific Colors

userBubble
userBubbleForeground
assistantBubble
assistantBubbleForeground

Colors shown above are from the Dark preset.

Typography

The FlaiTypography class provides a type scale with methods for generating TextStyle objects:

MethodSizeWeightUsage
bodySmall()12px400Captions, timestamps, labels
bodyBase()14px400Body text, messages
bodyLarge()16px400Emphasized body text
heading()20px600Section headings
headingLarge()24px700Page titles
mono()12px400Code, 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:

TokenDefaultUsage
xs4.0Tight gaps, chip padding
sm8.0Small gaps, inline spacing
md16.0Standard padding, margins
lg24.0Section spacing
xl32.0Large gaps, page margins
xxl48.0Hero spacing

Border Radii

Border radius tokens via FlaiRadius:

TokenDefaultiOS Preset
sm4.08.0
md8.012.0
lg12.018.0
xl16.022.0
full99999999

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),
  ),
);