@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.
- package/dist/{chunk-CSW5GYBU.js → chunk-IDULPYOU.js} +3997 -3734
- package/dist/chunk-IDULPYOU.js.map +1 -0
- package/dist/{chunk-UCY537V4.cjs → chunk-JIKTMXTZ.cjs} +952 -689
- package/dist/chunk-JIKTMXTZ.cjs.map +1 -0
- package/dist/components/chat/approval-request-message.d.ts.map +1 -1
- package/dist/components/chat/chat-container.d.ts.map +1 -1
- package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
- package/dist/components/chat/chat-message-list.d.ts.map +1 -1
- package/dist/components/chat/types/message.types.d.ts +34 -0
- package/dist/components/chat/types/message.types.d.ts.map +1 -1
- package/dist/components/features/index.cjs +14 -2
- package/dist/components/features/index.cjs.map +1 -1
- package/dist/components/features/index.d.ts +1 -0
- package/dist/components/features/index.d.ts.map +1 -1
- package/dist/components/features/index.js +15 -3
- package/dist/components/index.cjs +14 -2
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +13 -1
- package/dist/components/navigation/index.cjs +2 -2
- package/dist/components/navigation/index.js +1 -1
- package/dist/components/providers/theme-provider.d.ts +69 -0
- package/dist/components/providers/theme-provider.d.ts.map +1 -0
- package/dist/components/ui/index.cjs +2 -2
- package/dist/components/ui/index.js +1 -1
- package/dist/components/ui/simple-markdown-renderer.d.ts.map +1 -1
- package/dist/index.cjs +14 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +13 -1
- package/package.json +2 -1
- package/src/components/chat/approval-request-message.tsx +106 -92
- package/src/components/chat/chat-container.tsx +8 -4
- package/src/components/chat/chat-message-enhanced.tsx +51 -9
- package/src/components/chat/chat-message-list.tsx +27 -19
- package/src/components/chat/types/message.types.ts +35 -0
- package/src/components/features/index.ts +15 -0
- package/src/components/providers/theme-provider.tsx +130 -0
- package/src/components/ui/simple-markdown-renderer.tsx +248 -2
- package/src/stories/Theme.stories.tsx +350 -0
- package/src/styles/README.md +271 -174
- package/src/styles/dark_theme.tokens.json +982 -0
- package/src/styles/light_theme.tokens.json +982 -0
- package/src/styles/ods-colors.css +225 -146
- package/src/styles/ods_color_tokens.json +1 -300
- package/dist/chunk-CSW5GYBU.js.map +0 -1
- package/dist/chunk-UCY537V4.cjs.map +0 -1
package/src/styles/README.md
CHANGED
|
@@ -1,30 +1,45 @@
|
|
|
1
1
|
# UI Kit Styles Usage Guide
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
|
-
|
|
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
|
|
11
|
-
├──
|
|
12
|
-
├──
|
|
13
|
-
├── ods-
|
|
14
|
-
├── ods-
|
|
15
|
-
├── ods-
|
|
16
|
-
├── ods-
|
|
17
|
-
├──
|
|
18
|
-
|
|
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
|
|
24
|
-
|
|
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
|
|
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
|
-
|
|
42
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
51
|
-
|
|
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
|
-
|
|
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
|
-
|
|
137
|
+
For previews, side-by-side comparisons, or scoping a theme to a subtree, use the class form:
|
|
57
138
|
|
|
58
|
-
|
|
59
|
-
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
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
|
-
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
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
|
-
/*
|
|
87
|
-
--color-
|
|
88
|
-
--color-bg
|
|
89
|
-
--color-bg-
|
|
90
|
-
--color-
|
|
91
|
-
--color-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
--color-
|
|
96
|
-
--color-
|
|
97
|
-
--color-
|
|
98
|
-
|
|
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
|
|
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
|
-
/*
|
|
108
|
-
--font-family-heading: "Azeret Mono", "SF Mono", Monaco,
|
|
109
|
-
--font-family-body:
|
|
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
|
|
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
|
-
|
|
121
|
-
Tailwind `fontFamily` mappings reference CSS variables, not hardcoded font names:
|
|
230
|
+
Tailwind `fontFamily` references the variables, not raw names:
|
|
122
231
|
|
|
123
|
-
```
|
|
232
|
+
```ts
|
|
124
233
|
// tailwind.config.ts
|
|
125
234
|
fontFamily: {
|
|
126
|
-
sans:
|
|
127
|
-
mono:
|
|
128
|
-
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
|
-
|
|
242
|
+
The `odsTypographyPlugin` ships `text-h1` … `text-h6` composite utilities that bundle family + weight + size + line-height + letter-spacing:
|
|
134
243
|
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
162
|
-
--
|
|
163
|
-
--
|
|
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
|
-
###
|
|
169
|
-
The styles work seamlessly with Tailwind CSS:
|
|
265
|
+
### With Tailwind
|
|
170
266
|
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
<
|
|
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
|
-
|
|
178
|
-
|
|
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
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
|
188
|
-
Access design tokens in CSS-in-JS solutions:
|
|
280
|
+
### With CSS-in-JS
|
|
189
281
|
|
|
190
|
-
```
|
|
191
|
-
const
|
|
192
|
-
background
|
|
282
|
+
```tsx
|
|
283
|
+
const Surface = styled.div`
|
|
284
|
+
background: var(--color-bg-card);
|
|
193
285
|
color: var(--color-text-primary);
|
|
194
|
-
|
|
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
|
-
##
|
|
293
|
+
## Customisation
|
|
201
294
|
|
|
202
|
-
### Adding
|
|
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
|
-
|
|
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
|
|
219
|
-
|
|
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
|
-
--
|
|
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
|
|
235
|
-
|
|
334
|
+
### Styles not loading
|
|
335
|
+
|
|
336
|
+
Import the package path, not the file path:
|
|
337
|
+
|
|
236
338
|
```css
|
|
237
|
-
@import "@flamingo/ui-kit/styles";
|
|
238
|
-
@import "@flamingo/ui-kit/styles/index.css"; /*
|
|
339
|
+
@import "@flamingo/ui-kit/styles"; /* correct */
|
|
340
|
+
@import "@flamingo/ui-kit/styles/index.css"; /* incorrect */
|
|
239
341
|
```
|
|
240
342
|
|
|
241
|
-
###
|
|
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
|
-
|
|
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
|
-
|
|
253
|
-
.my-component {
|
|
254
|
-
color: var(--color-text-primary);
|
|
255
|
-
}
|
|
256
|
-
```
|
|
347
|
+
### `useThemeToggle` returns `dark` even after toggling to light
|
|
257
348
|
|
|
258
|
-
|
|
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
|
-
|
|
351
|
+
### Platform accent not applying
|
|
264
352
|
|
|
265
|
-
1.
|
|
266
|
-
2.
|
|
267
|
-
3.
|
|
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
|
-
|
|
357
|
+
### Component uses brand colour that ignores the theme
|
|
274
358
|
|
|
275
|
-
|
|
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
|
-
|
|
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
|
-
|
|
363
|
+
You're importing both the umbrella (`@flamingo/ui-kit/styles`) and individual ODS files. Pick one.
|
|
285
364
|
|
|
286
|
-
|
|
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. **
|
|
289
|
-
2. **
|
|
290
|
-
3. **
|
|
291
|
-
4. **
|
|
292
|
-
5. **
|
|
293
|
-
6. **
|
|
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.
|