@flamingo-stack/openframe-frontend-core 0.0.201 → 0.0.202

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/{chunk-CSW5GYBU.js → chunk-IDULPYOU.js} +3997 -3734
  2. package/dist/chunk-IDULPYOU.js.map +1 -0
  3. package/dist/{chunk-UCY537V4.cjs → chunk-JIKTMXTZ.cjs} +952 -689
  4. package/dist/chunk-JIKTMXTZ.cjs.map +1 -0
  5. package/dist/components/chat/approval-request-message.d.ts.map +1 -1
  6. package/dist/components/chat/chat-container.d.ts.map +1 -1
  7. package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
  8. package/dist/components/chat/chat-message-list.d.ts.map +1 -1
  9. package/dist/components/chat/types/message.types.d.ts +34 -0
  10. package/dist/components/chat/types/message.types.d.ts.map +1 -1
  11. package/dist/components/features/index.cjs +14 -2
  12. package/dist/components/features/index.cjs.map +1 -1
  13. package/dist/components/features/index.d.ts +1 -0
  14. package/dist/components/features/index.d.ts.map +1 -1
  15. package/dist/components/features/index.js +15 -3
  16. package/dist/components/index.cjs +14 -2
  17. package/dist/components/index.cjs.map +1 -1
  18. package/dist/components/index.js +13 -1
  19. package/dist/components/navigation/index.cjs +2 -2
  20. package/dist/components/navigation/index.js +1 -1
  21. package/dist/components/providers/theme-provider.d.ts +69 -0
  22. package/dist/components/providers/theme-provider.d.ts.map +1 -0
  23. package/dist/components/ui/index.cjs +2 -2
  24. package/dist/components/ui/index.js +1 -1
  25. package/dist/components/ui/simple-markdown-renderer.d.ts.map +1 -1
  26. package/dist/index.cjs +14 -2
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.js +13 -1
  29. package/package.json +2 -1
  30. package/src/components/chat/approval-request-message.tsx +106 -92
  31. package/src/components/chat/chat-container.tsx +8 -4
  32. package/src/components/chat/chat-message-enhanced.tsx +51 -9
  33. package/src/components/chat/chat-message-list.tsx +27 -19
  34. package/src/components/chat/types/message.types.ts +35 -0
  35. package/src/components/features/index.ts +15 -0
  36. package/src/components/providers/theme-provider.tsx +130 -0
  37. package/src/components/ui/simple-markdown-renderer.tsx +248 -2
  38. package/src/stories/Theme.stories.tsx +350 -0
  39. package/src/styles/README.md +271 -174
  40. package/src/styles/dark_theme.tokens.json +982 -0
  41. package/src/styles/light_theme.tokens.json +982 -0
  42. package/src/styles/ods-colors.css +225 -146
  43. package/src/styles/ods_color_tokens.json +1 -300
  44. package/dist/chunk-CSW5GYBU.js.map +0 -1
  45. package/dist/chunk-UCY537V4.cjs.map +0 -1
@@ -1,30 +1,45 @@
1
1
  # UI Kit Styles Usage Guide
2
2
 
3
3
  ## Overview
4
- This directory contains the complete styling system for @flamingo/ui-kit, including the ODS (Open Design System) and application-specific styles.
4
+
5
+ This directory contains the complete styling system for `@flamingo/ui-kit` — the ODS (Open Design System) design tokens, the **light/dark theme system**, platform brand overrides, and a small set of vendor stylesheets.
6
+
7
+ Two orthogonal axes drive the visual layer:
8
+
9
+ | Axis | Attribute | Sits on | Controls |
10
+ | -------- | ------------------------------------ | ---------- | ----------------------------------------------------- |
11
+ | Theme | `data-theme="light \| dark"` | `<html>` | Surfaces, text, borders, status colors |
12
+ | Platform | `data-app-type="openframe \| …"` | `<body>` | Brand accent + links only (never bg/text/border) |
13
+
14
+ They compose cleanly because they live on different elements and reference the same `--ods-*` primitives.
5
15
 
6
16
  ## File Structure
7
17
 
8
18
  ```
9
19
  ui-kit/src/styles/
10
- ├── index.css # Main entry point - imports everything
11
- ├── app-globals.css # Application-specific global styles
12
- ├── ods-colors.css # Color tokens and semantic aliases
13
- ├── ods-design-tokens.css # Spacing, typography, shadows
14
- ├── ods-dynamic-theming.css # Platform-specific theme variations
15
- ├── ods-fluid-typography.css # Responsive typography system
16
- ├── ods-interaction-states.css # Hover, focus, active states
17
- ├── ods-responsive-tokens.css # Breakpoints and responsive utilities
18
- └── README.md # This file
20
+ ├── index.css # Main entry point imports everything below
21
+ ├── index.d.ts # Side-effect import declaration (no runtime API)
22
+ ├── app-globals.css # Global resets, body styling, heading defaults
23
+ ├── ods-colors.css # Tier 1 primitives + Tier 2 semantic aliases (theme-aware)
24
+ ├── ods-design-tokens.css # Spacing, radii, shadows, durations, typography vars
25
+ ├── ods-interaction-states.css # Hover / focus / active / disabled state classes
26
+ ├── ods-responsive-tokens.css # Breakpoints, fluid font-size clamps
27
+ ├── dark_theme.tokens.json # Source of truth for dark primitives (1:1 with ods-colors.css)
28
+ ├── light_theme.tokens.json # Source of truth for light primitives
29
+ ├── storybook-fonts.css # Direct font CSS for Storybook (Next.js apps use next/font)
30
+ ├── vendor-react-easy-crop.css # Vendor override for react-easy-crop
31
+ ├── vendor-react-scroll.css # Vendor override for react-scroll
32
+ └── README.md # This file
19
33
  ```
20
34
 
21
35
  ## How to Use
22
36
 
23
- ### 1. Basic Import (Recommended)
24
- Import the complete styling system in your main CSS file:
37
+ ### 1. Basic import (recommended)
38
+
39
+ Import the complete styling system once in your root CSS:
25
40
 
26
41
  ```css
27
- /* app/globals.css or src/styles/globals.css */
42
+ /* app/globals.css */
28
43
  @import "@flamingo/ui-kit/styles";
29
44
 
30
45
  @tailwind base;
@@ -33,82 +48,177 @@ Import the complete styling system in your main CSS file:
33
48
  ```
34
49
 
35
50
  This single import includes:
36
- - All ODS design tokens (colors, typography, spacing, etc.)
37
- - Application-specific global styles (React Easy Crop, Markdown editor, etc.)
38
- - Platform-aware theming
39
- - Utility classes and component styles
40
51
 
41
- ### 2. Individual File Imports (Advanced)
42
- If you need granular control, you can import specific files:
52
+ - All ODS design tokens (colors, typography, spacing, shadows, durations)
53
+ - Both light **and** dark theme primitives (one is active at a time via `data-theme`)
54
+ - Platform brand overrides (accent + links)
55
+ - Global resets and vendor overrides
43
56
 
44
- ```css
45
- /* Import only ODS design tokens */
46
- @import "@flamingo/ui-kit/styles/ods-colors.css";
47
- @import "@flamingo/ui-kit/styles/ods-design-tokens.css";
48
- @import "@flamingo/ui-kit/styles/ods-dynamic-theming.css";
57
+ ### 2. Wrap the app in `ThemeProvider`
58
+
59
+ CSS alone is not enough — something has to set `data-theme` on `<html>` and persist the user's preference. That's `ThemeProvider`:
60
+
61
+ ```tsx
62
+ // app/layout.tsx (Next.js App Router)
63
+ import { ThemeProvider } from "@flamingo/ui-kit/components/features";
64
+
65
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
66
+ return (
67
+ <html lang="en" suppressHydrationWarning>
68
+ <body data-app-type="openframe">
69
+ <ThemeProvider>{children}</ThemeProvider>
70
+ </body>
71
+ </html>
72
+ );
73
+ }
74
+ ```
75
+
76
+ > `suppressHydrationWarning` on `<html>` is required — `next-themes` writes `data-theme` before React hydrates.
77
+
78
+ ### 3. Build a toggle with `useThemeToggle`
79
+
80
+ The kit is **headless by design** — apps own their button visuals.
81
+
82
+ ```tsx
83
+ "use client";
84
+ import { useThemeToggle } from "@flamingo/ui-kit/components/features";
85
+ import { Button } from "@flamingo/ui-kit/components/ui";
86
+ import { Moon, Sun } from "lucide-react";
87
+
88
+ export function ThemeToggle() {
89
+ const { isDark, toggle, mounted } = useThemeToggle();
90
+ return (
91
+ <Button
92
+ variant="outline"
93
+ size="icon"
94
+ onClick={toggle}
95
+ aria-label={isDark ? "Switch to light theme" : "Switch to dark theme"}
96
+ >
97
+ {mounted && (isDark ? <Sun /> : <Moon />)}
98
+ </Button>
99
+ );
100
+ }
101
+ ```
49
102
 
50
- /* Import app-specific styles */
51
- @import "@flamingo/ui-kit/styles/app-globals.css";
103
+ A live demo of all three patterns (`Showcase`, `ToggleOnly`, `SideBySide`) lives in Storybook under **Foundations / Theme** (`src/stories/Theme.stories.tsx`).
104
+
105
+ ## Theme System
106
+
107
+ ### Defaults & contract
108
+
109
+ - **Modes**: `light` and `dark` only. No `system` mode (`enableSystem={false}`).
110
+ - **Default**: `dark`.
111
+ - **Persistence**: `localStorage` key `ods-theme` (exported as `THEME_STORAGE_KEY`).
112
+ - **Attribute**: `data-theme` on `<html>` (exported as `THEME_ATTRIBUTE`).
113
+ - **Anti-flash**: handled by `next-themes`'s pre-paint script — no hand-rolled `<ThemeScript>` needed.
114
+
115
+ ### Architecture
116
+
117
+ ```
118
+ ┌─────────────────────────────────────────────────────────────────────┐
119
+ │ Tier 1 — Primitives (--ods-*) THEME-SCOPED │
120
+ │ :root, [data-theme="dark"], .theme-dark → dark values (default) │
121
+ │ [data-theme="light"], .theme-light → light values │
122
+ ├─────────────────────────────────────────────────────────────────────┤
123
+ │ Tier 2 — Semantic aliases (--color-*) THEME-AGNOSTIC │
124
+ │ var(--color-bg) → var(--ods-system-greys-background) │
125
+ │ …auto-follows whichever tier-1 set is active │
126
+ ├─────────────────────────────────────────────────────────────────────┤
127
+ │ Platform overrides ([data-app-type="…"]) ACCENT ONLY │
128
+ │ Override --color-accent-* / --color-link-* / --ods-accent │
129
+ │ Reference --ods-* so they follow the active theme automatically │
130
+ └─────────────────────────────────────────────────────────────────────┘
52
131
  ```
53
132
 
54
- **Note**: Individual imports are not exposed in package.json exports and are for internal use only.
133
+ Components never read tier 1 directly they always reference tier 2 (`--color-*`) or its Tailwind equivalents (`bg-ods-*`, `text-ods-*`, `border-ods-*`). That's why the same JSX renders correctly in both themes.
134
+
135
+ ### Escape hatches
55
136
 
56
- ## What's Included
137
+ For previews, side-by-side comparisons, or scoping a theme to a subtree, use the class form:
57
138
 
58
- ### ODS Design System
59
- - **Colors**: Comprehensive color palette with semantic aliases
60
- - **Typography**: Fluid responsive typography with clamp() functions
61
- - **Spacing**: Consistent spacing tokens for margins, padding, gaps
62
- - **Interactive States**: Hover, focus, active, disabled state definitions
63
- - **Platform Theming**: Automatic theme switching based on `NEXT_PUBLIC_APP_TYPE`
139
+ ```tsx
140
+ <div className="theme-light">
141
+ {/* renders with light primitives regardless of <html> data-theme */}
142
+ </div>
64
143
 
65
- ### Application-Specific Styles
66
- - **React Easy Crop**: Complete styling for image cropping components
67
- - **Markdown Editor**: Dark theme styling for @uiw/react-md-editor
68
- - **Markdown Preview**: Styled markdown rendering
69
- - **Utility Classes**: Scrollbar hiding, mobile zoom prevention, etc.
70
- - **Platform Body Styling**: Platform-specific body background and text colors
71
- - **Vendor Components**: Logo containers, thumbnails, and display utilities
144
+ <div className="theme-dark">
145
+ {/* renders with dark primitives */}
146
+ </div>
147
+ ```
148
+
149
+ There is also a `.theme-high-contrast` opt-in for accessibility.
150
+
151
+ ### Source of truth
152
+
153
+ `dark_theme.tokens.json` and `light_theme.tokens.json` are the canonical token values; `ods-colors.css` mirrors them 1:1. Update tokens by editing both the JSON and the CSS in lockstep (the JSON exists so design tools / token transformers can consume it).
72
154
 
73
155
  ## Platform Support
74
156
 
75
- The styles automatically adapt based on your `NEXT_PUBLIC_APP_TYPE` environment variable:
157
+ Platforms set **brand accent + link colors only** (and a couple of intentional brand scrims). They never touch surfaces, text or borders — those are owned by the theme.
76
158
 
77
- - **openmsp**: Yellow accent (#FFC008), dark theme
78
- - **flamingo**: Pink accent (#F357BB), light theme
79
- - **openframe**: Cyan accent (#5EFAF0), dark theme
80
- - **flamingo-teaser**: Yellow accent (#FFC008), dark theme
159
+ | `data-app-type` | Accent | Notes |
160
+ | ----------------- | ---------------------------- | ------------------------------------ |
161
+ | `openframe` | Yellow `--ods-open-yellow-base` | Cyan links |
162
+ | `openmsp` | Yellow `--ods-open-yellow-base` | |
163
+ | `flamingo` | Pink `--ods-flamingo-pink-base` | Dark scrim by-design |
164
+ | `flamingo-teaser` | Pink `--ods-flamingo-pink-base` | |
165
+ | `tmcg` | Pink `--ods-flamingo-pink-base` | Cards share page background; dark scrim |
166
+ | `marketing-hub` | Pink `--ods-flamingo-pink-base` | |
167
+ | `product-hub` | Green `--ods-attention-green-success` | |
168
+ | `revenue-hub` | Yellow-warning `--ods-attention-yellow-warning` | |
169
+ | `people-hub` | Cyan `--ods-flamingo-cyan-base` | |
170
+ | `company-hub` | Red `--ods-attention-red-error` | |
81
171
 
82
- ## CSS Variables Available
172
+ Adding a new platform = add one `[data-app-type="…"]` block in `ods-colors.css`. Because the block references `--ods-*` primitives (not raw hex), the new platform inherits dark/light flipping for free.
173
+
174
+ ## Key CSS Variables
175
+
176
+ ### Surfaces & text (Tier 2 — what components actually use)
83
177
 
84
- ### Color System
85
178
  ```css
86
- /* Primary color system */
87
- --color-accent-primary /* Platform-specific accent color */
88
- --color-bg /* Main background */
89
- --color-bg-card /* Card backgrounds */
90
- --color-text-primary /* Primary text color */
91
- --color-text-secondary /* Secondary text color */
92
- --color-border-default /* Default border color */
93
-
94
- /* Status colors */
95
- --color-success /* Success green */
96
- --color-error /* Error red */
97
- --color-warning /* Warning amber */
98
- --color-info /* Info cyan */
179
+ --color-bg /* Page background */
180
+ --color-bg-card /* Card / panel surface */
181
+ --color-bg-card-secondary /* Secondary card layer */
182
+ --color-bg-surface /* Raised surface (e.g. inputs) */
183
+ --color-bg-overlay /* Modal scrim */
184
+ --color-bg-backdrop /* Heavier scrim */
185
+
186
+ --color-text-primary
187
+ --color-text-secondary
188
+ --color-text-tertiary
189
+ --color-text-muted
190
+ --color-text-on-accent
191
+
192
+ --color-border-default
193
+ --color-border-hover
194
+ --color-border-focus
195
+ --color-divider
196
+ ```
197
+
198
+ ### Accent & status
199
+
200
+ ```css
201
+ --color-accent-primary /* Platform-set */
202
+ --color-accent-hover
203
+ --color-accent-active
204
+ --color-focus-ring
205
+
206
+ --color-success / -hover / -secondary
207
+ --color-error / -hover / -secondary
208
+ --color-warning / -hover / -secondary
209
+ --color-info / -hover
99
210
  ```
100
211
 
101
212
  ### Typography
102
213
 
103
- All typography is driven by CSS variables defined in `ods-design-tokens.css`. Both the Tailwind config and component styles reference these variables as a single source of truth.
214
+ All typography is driven by CSS variables defined in `ods-design-tokens.css`. Both Tailwind and component styles read these single source of truth.
104
215
 
105
- #### Font Families
106
216
  ```css
107
- /* Base font family tokens (defined in ods-design-tokens.css) */
108
- --font-family-heading: "Azeret Mono", "SF Mono", Monaco, Inconsolata, "Roboto Mono", Consolas, "Courier New", monospace;
109
- --font-family-body: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
217
+ /* Font families */
218
+ --font-family-heading: "Azeret Mono", "SF Mono", Monaco, …, monospace;
219
+ --font-family-body: "DM Sans", -apple-system, BlinkMacSystemFont, …, sans-serif;
110
220
 
111
- /* Per-heading font family tokens (reference base tokens) */
221
+ /* Per-heading family overrides */
112
222
  --font-h1-family: var(--font-family-heading);
113
223
  --font-h2-family: var(--font-family-heading);
114
224
  --font-h3-family: var(--font-family-body);
@@ -117,90 +227,72 @@ All typography is driven by CSS variables defined in `ods-design-tokens.css`. Bo
117
227
  --font-h6-family: var(--font-family-heading);
118
228
  ```
119
229
 
120
- #### Tailwind Font Family Integration
121
- Tailwind `fontFamily` mappings reference CSS variables, not hardcoded font names:
230
+ Tailwind `fontFamily` references the variables, not raw names:
122
231
 
123
- ```typescript
232
+ ```ts
124
233
  // tailwind.config.ts
125
234
  fontFamily: {
126
- sans: ["var(--font-family-body)"],
127
- mono: ["var(--font-family-heading)"],
128
- body: ["var(--font-family-body)"],
235
+ sans: ["var(--font-family-body)"],
236
+ mono: ["var(--font-family-heading)"],
237
+ body: ["var(--font-family-body)"],
129
238
  heading: ["var(--font-family-heading)"],
130
239
  }
131
240
  ```
132
241
 
133
- This means `font-sans`, `font-mono`, `font-body`, `font-heading` all resolve through CSS variables, ensuring consistency with the rest of the design system.
242
+ The `odsTypographyPlugin` ships `text-h1` `text-h6` composite utilities that bundle family + weight + size + line-height + letter-spacing:
134
243
 
135
- #### Typography Utility Classes
136
- The `odsTypographyPlugin` in `tailwind.config.ts` provides composite typography classes that bundle font-family, weight, size, line-height, and letter-spacing:
244
+ | Class | Family | Weight | Size | Line-height | Extras |
245
+ | ----------- | ------------------ | ------------------ | ----------------------------- | ---------------------------------------- | ------------------- |
246
+ | `text-h1` | `--font-h1-family` | `--font-h1-weight` | `--font-size-h1-title` | `--font-line-space-h1-main-title` | `-0.02em` |
247
+ | `text-h2` | `--font-h2-family` | `--font-h2-weight` | `--font-size-h2-sub-title` | `--font-line-space-h2-sub-title` | `-0.02em` |
248
+ | `text-h3` | `--font-h3-family` | `--font-h3-weight` | `--font-size-h3-body` | `--font-line-space-h3-body` | `-0.02em` |
249
+ | `text-h4` | `--font-h4-family` | `--font-h4-weight` | `--font-size-h4-body` | `--font-line-space-h4-body` | — |
250
+ | `text-h5` | `--font-h5-family` | `--font-h5-weight` | `--font-size-h5-caption` | `--font-line-space-h5-caption` | `-0.02em` uppercase |
251
+ | `text-h6` | `--font-h6-family` | `--font-h6-weight` | `--font-size-h6-caption` | `--font-line-space-h6-caption` | — |
137
252
 
138
- | Class | Font | Weight | Size | Line Height | Letter Spacing |
139
- |-------|------|--------|------|-------------|----------------|
140
- | `text-h1` | `--font-h1-family` | `--font-h1-weight` | `--font-size-h1-title` | `--font-line-space-h1-main-title` | `-0.02em` |
141
- | `text-h2` | `--font-h2-family` | `--font-h2-weight` | `--font-size-h2-sub-title` | `--font-line-space-h2-sub-title` | `-0.02em` |
142
- | `text-h3` | `--font-h3-family` | `--font-h3-weight` | `--font-size-h3-body` | `--font-line-space-h3-body` | `-0.02em` |
143
- | `text-h4` | `--font-h4-family` | `--font-h4-weight` | `--font-size-h4-body` | `--font-line-space-h4-body` | - |
144
- | `text-h5` | `--font-h5-family` | `--font-h5-weight` | `--font-size-h5-caption` | `--font-line-space-h5-caption` | `-0.02em` + uppercase |
145
- | `text-h6` | `--font-h6-family` | `--font-h6-weight` | `--font-size-h6-caption` | `--font-line-space-h6-caption` | - |
253
+ Plus size-only utilities (`text-heading-1` `text-heading-6`) when you want a different font-family but the heading's size + line-height. Fluid scaling via `clamp()` is defined in `ods-responsive-tokens.css`.
146
254
 
147
- Additionally, Tailwind `fontSize` utilities are available for size + line-height only:
255
+ ### Spacing & radii
148
256
 
149
- ```typescript
150
- // Usage: text-heading-1, text-heading-2, etc.
151
- 'heading-1': ['var(--font-size-h1-title)', { lineHeight: 'var(--font-line-space-h1-main-title)' }],
152
- 'heading-2': ['var(--font-size-h2-sub-title)', { lineHeight: 'var(--font-line-space-h2-sub-title)' }],
153
- // ...
154
- ```
155
-
156
- #### Responsive Typography
157
- Font sizes use `clamp()` functions for fluid scaling between breakpoints. The actual values are defined in `ods-responsive-tokens.css`.
158
-
159
- ### Spacing
160
257
  ```css
161
- /* Consistent spacing scale */
162
- --space-1 through --space-20
163
- --space-px, --space-0_5, etc.
258
+ --space-px, --space-0_5, --space-1 --space-20
259
+ --radius, --radius-sm, --radius-md, --radius-lg, --radius-xl
260
+ --shadow-card, --shadow-card-hover, --shadow-modal, --shadow-focus
164
261
  ```
165
262
 
166
263
  ## Component Integration
167
264
 
168
- ### Using with Tailwind
169
- The styles work seamlessly with Tailwind CSS:
265
+ ### With Tailwind
170
266
 
171
- ```jsx
172
- // Typography utilities apply all styles at once
173
- <h1 className="text-h1">Main Title</h1>
174
- <h2 className="text-h2">Subtitle</h2>
175
- <p className="font-body text-heading-3">Body text with heading-3 size</p>
267
+ ```tsx
268
+ <h1 className="text-h1">Main title</h1>
269
+ <p className="text-body text-ods-text-secondary">Body copy</p>
176
270
 
177
- // Platform-aware colors automatically applied
178
- <button className="bg-ods-accent text-ods-text-on-accent">
179
- Platform Button
271
+ <button className="bg-ods-accent text-ods-text-on-accent hover:bg-ods-accent-hover">
272
+ Platform-coloured button
180
273
  </button>
181
274
 
182
- // Font family utilities
183
- <span className="font-heading">Azeret Mono text</span>
184
- <span className="font-body">DM Sans text</span>
275
+ <div className="bg-ods-card border border-ods-border text-ods-text-primary">
276
+ Card surface — auto-flips between themes
277
+ </div>
185
278
  ```
186
279
 
187
- ### CSS-in-JS Integration
188
- Access design tokens in CSS-in-JS solutions:
280
+ ### With CSS-in-JS
189
281
 
190
- ```jsx
191
- const StyledComponent = styled.div`
192
- background-color: var(--color-bg-card);
282
+ ```tsx
283
+ const Surface = styled.div`
284
+ background: var(--color-bg-card);
193
285
  color: var(--color-text-primary);
194
- font-family: var(--font-family-body);
286
+ border: 1px solid var(--color-border-default);
195
287
  padding: var(--space-4);
196
288
  border-radius: var(--radius-lg);
289
+ box-shadow: var(--shadow-card);
197
290
  `;
198
291
  ```
199
292
 
200
- ## Customization
293
+ ## Customisation
201
294
 
202
- ### Adding Custom Styles
203
- For project-specific styles, add them after the ui-kit import:
295
+ ### Adding custom styles
204
296
 
205
297
  ```css
206
298
  @import "@flamingo/ui-kit/styles";
@@ -209,85 +301,90 @@ For project-specific styles, add them after the ui-kit import:
209
301
  @tailwind components;
210
302
  @tailwind utilities;
211
303
 
212
- /* Your custom styles here */
213
- .my-custom-component {
304
+ .my-component {
214
305
  background: var(--color-accent-primary);
306
+ color: var(--color-text-on-accent);
215
307
  }
216
308
  ```
217
309
 
218
- ### Overriding Design Tokens
219
- To override specific tokens, define them after the import:
310
+ ### Overriding tokens
311
+
312
+ Override after the import, in the appropriate selector. **Theme-scoped** tokens must be overridden inside the matching selector so they flip:
220
313
 
221
314
  ```css
222
315
  @import "@flamingo/ui-kit/styles";
223
316
 
317
+ /* Theme-stable override (applies to both themes) */
224
318
  :root {
225
- /* Override specific tokens */
226
- --color-accent-primary: #custom-color;
227
319
  --font-family-body: "Inter", sans-serif;
228
- --space-custom: 2.5rem;
320
+ --radius-lg: 12px;
321
+ }
322
+
323
+ /* Theme-scoped override (per-theme) */
324
+ :root[data-theme="dark"] {
325
+ --ods-system-greys-background: #0a0a0a;
326
+ }
327
+ :root[data-theme="light"] {
328
+ --ods-system-greys-background: #ffffff;
229
329
  }
230
330
  ```
231
331
 
232
332
  ## Troubleshooting
233
333
 
234
- ### Styles Not Loading
235
- Ensure you're importing the correct path:
334
+ ### Styles not loading
335
+
336
+ Import the package path, not the file path:
337
+
236
338
  ```css
237
- @import "@flamingo/ui-kit/styles"; /* Correct */
238
- @import "@flamingo/ui-kit/styles/index.css"; /* Incorrect */
339
+ @import "@flamingo/ui-kit/styles"; /* correct */
340
+ @import "@flamingo/ui-kit/styles/index.css"; /* incorrect */
239
341
  ```
240
342
 
241
- ### Platform Theming Not Working
242
- 1. Check that `NEXT_PUBLIC_APP_TYPE` is set correctly
243
- 2. Verify the value matches supported platforms
244
- 3. Ensure the import is in your root CSS file
343
+ ### Theme flashes wrong colour on first paint
245
344
 
246
- ### CSS Variables Undefined
247
- Make sure you're importing the ui-kit styles before using any CSS variables:
248
- ```css
249
- /* Import first */
250
- @import "@flamingo/ui-kit/styles";
345
+ You're missing `suppressHydrationWarning` on `<html>` or you're not wrapping in `ThemeProvider`. Both are required for `next-themes`'s pre-paint script to do its job.
251
346
 
252
- /* Then use variables */
253
- .my-component {
254
- color: var(--color-text-primary);
255
- }
256
- ```
347
+ ### `useThemeToggle` returns `dark` even after toggling to light
257
348
 
258
- ### Duplicate Styles
259
- If you see duplicate styles, ensure you're not importing both:
260
- - Individual ODS files AND the main styles
261
- - The ui-kit styles AND manual copies of the same styles
349
+ You're reading `theme` before `mounted === true`. Until hydration completes, the hook returns the default (`dark`). Gate UI on `mounted` to avoid hydration mismatch — the [Showcase story](../stories/Theme.stories.tsx) shows the pattern.
262
350
 
263
- ## Best Practices
351
+ ### Platform accent not applying
264
352
 
265
- 1. **Always import the complete styles** unless you have specific needs for granular imports
266
- 2. **Use CSS variables** instead of hardcoded values for consistency
267
- 3. **Use `text-h1`..`text-h6` utilities** for headings they apply the full typography stack (family, weight, size, line-height, letter-spacing)
268
- 4. **Use `font-heading` / `font-body`** for font-family only — they reference CSS variables, not hardcoded fonts
269
- 5. **Leverage platform theming** by using accent colors and semantic tokens
270
- 6. **Test across all platforms** when making style changes
271
- 7. **Keep custom styles minimal** - prefer using design system tokens
353
+ 1. `data-app-type` must be on `<body>` (or any ancestor of the components).
354
+ 2. The value must match one of the supported keys (see the Platform Support table).
355
+ 3. Make sure your root CSS imports `@flamingo/ui-kit/styles`.
272
356
 
273
- ## Migration from Legacy Styles
357
+ ### Component uses brand colour that ignores the theme
274
358
 
275
- If migrating from individual style files:
359
+ That's by design for the few theme-stable shades (`--ods-*-dark`, `--ods-*-light`) and third-party social brand colours. Use a tier-2 alias (`--color-*`) when you want theme-aware behaviour.
276
360
 
277
- 1. Remove individual `@import` statements for ODS files
278
- 2. Replace with single `@import "@flamingo/ui-kit/styles"`
279
- 3. Delete duplicate style files from your project
280
- 4. Replace hardcoded font names with CSS variable references (e.g. `"DM Sans"` -> `var(--font-family-body)`)
281
- 5. Update any hardcoded colors/spacing to use CSS variables
282
- 6. Test that platform theming still works correctly
361
+ ### Duplicate styles in the bundle
283
362
 
284
- ## Contributing
363
+ You're importing both the umbrella (`@flamingo/ui-kit/styles`) and individual ODS files. Pick one.
285
364
 
286
- When adding new styles to the ui-kit:
365
+ ## Best Practices
366
+
367
+ 1. **Wrap in `ThemeProvider` once** at the app root and use `useThemeToggle()` for UI — never set `data-theme` manually from app code.
368
+ 2. **Use tier-2 aliases (`--color-*` / `bg-ods-*` / `text-ods-*`)** in components, not tier-1 primitives or raw hex.
369
+ 3. **Use `text-h1` … `text-h6`** for headings — they apply the full typography stack.
370
+ 4. **Use `font-heading` / `font-body`** for font-family only.
371
+ 5. **Test in both themes** — the easiest way is the `Foundations/Theme/SideBySide` Storybook story.
372
+ 6. **Never hardcode colours, font-families, or pixel sizes** (see project CLAUDE.md, Core Rule 2).
373
+ 7. **Keep platform overrides to accent-only**. Surfaces / text / borders are the theme's job.
374
+
375
+ ## Migration Notes
376
+
377
+ - The legacy `ods-dynamic-theming.css` and `ods-fluid-typography.css` have been folded into `ods-colors.css` and `ods-responsive-tokens.css` respectively — drop those imports if you still reference them.
378
+ - Previous releases conflated *platform* and *theme* (e.g. "openframe = dark only"). Theme is now a **per-user** choice that exists independently of platform; both axes compose. If you previously branched layout on platform to imply theme, switch to reading `useTheme()`.
379
+ - Hardcoded `"DM Sans"` / `"Azeret Mono"` references should become `var(--font-family-body)` / `var(--font-family-heading)`.
380
+
381
+ ## Contributing
287
382
 
288
- 1. **Design tokens** go in the appropriate `ods-*.css` file
289
- 2. **Application-specific styles** go in `app-globals.css`
290
- 3. **Platform-specific overrides** go in `ods-dynamic-theming.css`
291
- 4. **Typography changes** must update both CSS variables in `ods-design-tokens.css` and the plugin in `tailwind.config.ts`
292
- 5. **Update this README** when adding new features or changing structure
293
- 6. **Test across all platforms** before committing changes
383
+ 1. **Token values** edit both the `*.tokens.json` AND `ods-colors.css` (they must stay in sync).
384
+ 2. **New design tokens** the appropriate `ods-*.css` file. Add a tier-2 alias if components are expected to consume it.
385
+ 3. **Global resets / body styling** `app-globals.css`.
386
+ 4. **Platform brand overrides** bottom of `ods-colors.css`.
387
+ 5. **Typography changes** update CSS variables in `ods-design-tokens.css` **and** the `odsTypographyPlugin` in `tailwind.config.ts`.
388
+ 6. **Theme system changes** update `src/components/providers/theme-provider.tsx` and the Storybook demo (`src/stories/Theme.stories.tsx`).
389
+ 7. **Update this README** when adding new files, new platforms, or changing the theme contract.
390
+ 8. **Test in both themes** and across at least two platforms before committing.