mobile bluesky app made with flutter
lazurite.stormlightlabs.org/
mobile
bluesky
flutter
1# Theming System
2
3## Overview
4
5- Many Material 3 components rely on the broader set of tone-based
6 surfaces/containers and "onSurfaceVariant/outlineVariant" emphasis roles.
7- Material 3 is explicitly designed around *color roles* applied consistently
8 across UI.
9- Flutter has been expanding Material 3 ColorScheme roles (tone surfaces +
10 containers, and more accent roles), and some older roles are deprecated (e.g.,
11 background/onBackground, surfaceVariant).
12
13## Architecture
14
15### Core Types
16
17**ThemePack** (`lib/src/app/theming/theme_pack.dart`)
18
19- Collection of theme variants (e.g., "Oxocarbon" pack with light/dark variants)
20- Contains metadata: id, name, author
21- Provides accessors: `lightVariant`, `darkVariant`, `getVariant(id)`
22
23**ThemeVariant** (`lib/src/app/theming/theme_variant.dart`)
24
25- Single brightness variant with a Material 3 ColorScheme
26- Built from ThemeSpec palette definitions
27- Contains: id, brightness, derivedScheme
28
29**ThemeSpec** (`lib/src/app/theming/theme_spec.dart`)
30
31- Palette definition for a theme variant
32- Maps raw colors to M3 ColorScheme roles
33- Defines: surfaces, containers, outlines, accents, typography, shapes
34
35**ThemeFactory** (`lib/src/app/theming/theme_factory.dart`)
36
37- Builds complete ThemeData from ThemeVariant
38- Centralizes component themes (NavBar, Chips, Cards, ListTiles, Dividers, Inputs)
39- Ensures consistent M3 role usage across all components
40
41### Principles (Material 3)
42
43- Use semantic color roles (surface containers, outlineVariant,
44 onSurfaceVariant) rather than raw hex values sprinkled through widgets.
45- Create hierarchy with tone-based surfaces/containers rather than heavy
46 dividers.
47- Navigation components must have a clear active indicator (selected state).
48- Chips have specific color roles in spec (filter chip uses onSurfaceVariant +
49 outline and optionally surfaceContainerLow).
50
51## Material 3 Role Usage
52
53### Surface Containers (Hierarchy)
54
55Tone-based surfaces create visual hierarchy without heavy elevation:
56
57```text
58surfaceContainerLowest ← dialogs, sheets (highest elevation)
59surfaceContainerHigh ← embeds, elevated cards
60surfaceContainer ← default containers
61surfaceContainerLow ← posts, cards (slightly elevated)
62surface ← base background
63surfaceDim/surfaceBright ← adaptive surface tones
64```
65
66### Component Patterns
67
68#### NavigationBar
69
70- Active indicator: uses container role (NOT primary tint overlay)
71- Selected icons/labels: onSurface
72- Unselected icons/labels: onSurfaceVariant
73
74#### FilterChips (Feed selector)
75
76- Unselected: outline + onSurfaceVariant
77- Selected: secondaryContainer + onSecondaryContainer
78
79#### Cards (Posts)
80
81- Use surfaceContainerLow for slight elevation from background
82- Embeds use surfaceContainerHigh (higher than parent post)
83
84#### Dividers
85
86- Default: outlineVariant (subtle)
87- Emphasized boundaries: outline
88
89#### Text Emphasis
90
91- Body text: onSurface (highest legibility)
92- Metadata (handle, timestamp): onSurfaceVariant
93
94## Creating Theme Packs
95
96### 1. Define Palette
97
98Map your palette to M3 surface/container/outline/accent roles:
99
100```dart
101final mySpec = ThemeSpec(
102 // Base surfaces
103 surface: Color(0xFF1A1A1A),
104 surfaceDim: Color(0xFF121212),
105 surfaceBright: Color(0xFF242424),
106
107 // Container ladder (dark theme: lowest is darkest)
108 surfaceContainerLowest: Color(0xFF0F0F0F),
109 surfaceContainerLow: Color(0xFF1E1E1E),
110 surfaceContainer: Color(0xFF242424),
111 surfaceContainerHigh: Color(0xFF2E2E2E),
112 surfaceContainerHighest: Color(0xFF393939),
113
114 // Outlines
115 outline: Color(0xFF525252),
116 outlineVariant: Color(0xFF393939),
117
118 // Text
119 onSurface: Color(0xFFF2F4F8),
120 onSurfaceVariant: Color(0xFFB0B0B0),
121
122 // Accents
123 primary: Color(0xFF0085FF),
124 onPrimary: Color(0xFFFFFFFF),
125 secondary: Color(0xFF78A9FF),
126 onSecondary: Color(0xFF000000),
127 // ... other accent roles
128);
129```
130
131### 2. Create Variants
132
133```dart
134final darkVariant = ThemeVariant(
135 id: 'mypack-dark',
136 brightness: Brightness.dark,
137 spec: myDarkSpec,
138);
139
140final lightVariant = ThemeVariant(
141 id: 'mypack-light',
142 brightness: Brightness.light,
143 spec: myLightSpec,
144);
145```
146
147### 3. Build ThemePack
148
149```dart
150final myPack = ThemePack(
151 id: 'mypack',
152 name: 'My Pack',
153 author: 'Me',
154 variants: [darkVariant, lightVariant],
155);
156```
157
158### 4. Validate with Role Lint Tests
159
160Role lint checks ensure:
161
162- All required M3 roles are defined
163- Hierarchy integrity (surface != surfaceContainerLow, etc.)
164- Container ladder ordering matches brightness (dark: lowest is darkest, light: lowest is lightest)
165- Emphasis differentiation (onSurface != onSurfaceVariant)
166
167## Accent Strategy by Theme Type
168
169### High-contrast themes (Oxocarbon, One Dark)
170
171- Use vivid primary colors
172- Strong secondary/tertiary for highlights
173
174### Pastel themes (Catppuccin, Rosé Pine, Nord)
175
176- Keep accents restrained
177- Use secondary for chips, tertiary for highlights
178- Avoid overwhelming soft palettes with saturated accents