mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(ui): align shadow-DOM token fallbacks with real token values (#113684)
Shadow-DOM components carried fallback colors that never matched the actual tokens: panel-tab-strip fell back to teal #4ec9a8 for the coral --accent, resizable-divider to Bootstrap blue #007bff, and --border to a generic #333. Align all fallbacks with the claw-family values in styles/base.css so token-less rendering matches the product palette. Also document the intentionally dark image-lightbox chrome and the terminal theme's hand-mirrored token values, and regenerate the drifted values in ui/docs/design-system/color-tokens.md (--muted, --muted-strong, --primary, --danger, --info, light status colors) from base.css truth.
This commit is contained in:
committed by
GitHub
parent
47601cf5b4
commit
fdc8d472c7
@@ -1,6 +1,6 @@
|
||||
# Color Tokens
|
||||
|
||||
All tokens are defined in `ui/src/styles/base.css` under `:root` (dark mode default) and `:root[data-theme-mode="light"]` (light override). Theme families may override accent tokens while keeping shared surface tokens.
|
||||
All tokens are defined in `ui/src/styles/base.css` under `:root` (dark mode default) and `:root[data-theme-mode="light"]` (light override). Values in this doc are the default claw family; the knot (`data-theme="openknot"`/`openknot-light`) and dash (`dash`/`dash-light`) families override surface, accent, and status tokens in their own `base.css` blocks, each with its own WCAG audit comment.
|
||||
|
||||
> Contrast ratios are measured against `--bg` (`#0e1015`) in dark mode using WCAG relative luminance formula. AA requires ≥4.5:1 for normal text, ≥3:1 for large text and UI components.
|
||||
|
||||
@@ -30,12 +30,12 @@ Light mode uses a warm paper palette: ivory backgrounds, warm gray borders (`#e8
|
||||
|
||||
## Text
|
||||
|
||||
| Token | Dark Value | Contrast on `--bg` | Use |
|
||||
| ---------------- | ---------- | ------------------ | ---------------------------------------------------- |
|
||||
| `--text` | `#d4d4d8` | ~12.9:1 ✅ | Body copy, labels |
|
||||
| `--text-strong` | `#f4f4f5` | ~17.3:1 ✅ | Headings, emphasis |
|
||||
| `--muted` | `#838387` | ~5.0:1 ✅ | Placeholder, metadata |
|
||||
| `--muted-strong` | `#75757d` | ~4.2:1 | Secondary text, captions; avoid for normal body text |
|
||||
| Token | Dark Value | Contrast on `--bg` | Use |
|
||||
| ---------------- | ---------- | ------------------ | -------------------------------------------------- |
|
||||
| `--text` | `#d4d4d8` | ~12.9:1 ✅ | Body copy, labels |
|
||||
| `--text-strong` | `#f4f4f5` | ~17.3:1 ✅ | Headings, emphasis |
|
||||
| `--muted` | `#8b8b94` | ~5.6:1 ✅ | Placeholder, metadata |
|
||||
| `--muted-strong` | `#898990` | ~5.5:1 ✅ | Secondary text, captions; prefer `--text` for body |
|
||||
|
||||
## Accent (Primary — Red)
|
||||
|
||||
@@ -46,7 +46,7 @@ Light mode uses a warm paper palette: ivory backgrounds, warm gray borders (`#e8
|
||||
| `--accent-muted` | `#ff5c5c` | Same as accent (aliased) | — |
|
||||
| `--accent-subtle` | `rgba(255,92,92,0.1)` | Badge backgrounds, tinted fills | Not for text on dark bg (fails contrast) |
|
||||
| `--accent-glow` | `rgba(255,92,92,0.2)` | Focus rings, glow effects | Not as background |
|
||||
| `--primary` | `#ff5c5c` | Component library `primary` alias | — |
|
||||
| `--primary` | `#d13c3c` | Filled primary buttons (white text, ~4.8:1 AA) | Not interchangeable with `--accent` |
|
||||
|
||||
## Accent 2 (Teal)
|
||||
|
||||
@@ -58,13 +58,17 @@ Light mode uses a warm paper palette: ivory backgrounds, warm gray borders (`#e8
|
||||
|
||||
## Semantic
|
||||
|
||||
| Token | Dark Value | Light Value | Contrast on `--bg` | Use |
|
||||
| --------------- | ---------- | ----------- | ------------------ | --------------------------------------------- |
|
||||
| `--ok` | `#22c55e` | `#15803d` | ~8.4:1 ✅ | Success states, token meter low |
|
||||
| `--warn` | `#f59e0b` | `#d97706` | ~8.9:1 ✅ | Warnings, degraded states |
|
||||
| `--danger` | `#ef4444` | `#dc2626` | ~5.1:1 ✅ | Errors, destructive actions, token meter high |
|
||||
| `--info` | `#3b82f6` | `#2563eb` | ~5.2:1 ✅ | Informational, token meter mid |
|
||||
| `--destructive` | `#ef4444` | — | ~5.1:1 ✅ | Destructive action labels |
|
||||
| Token | Dark Value | Light Value | Contrast on dark `--bg` | Use |
|
||||
| --------------- | ---------- | ----------- | ----------------------- | ---------------------------------------------- |
|
||||
| `--ok` | `#22c55e` | `#166534` | ~8.4:1 ✅ | Success states, token meter low |
|
||||
| `--warn` | `#f59e0b` | `#92400e` | ~8.9:1 ✅ | Warnings, degraded states |
|
||||
| `--danger` | `#f87171` | `#b91c1c` | ~6.9:1 ✅ | Errors, destructive text, token meter high |
|
||||
| `--info` | `#60a5fa` | `#1d4ed8` | ~7.5:1 ✅ | Informational, token meter mid |
|
||||
| `--destructive` | `#d32f2f` | `#dc2626` | ~3.8:1 (fill only) | Destructive button fills (with `#fafafa` text) |
|
||||
|
||||
Each `--x` has `-muted` (0.75 alpha) and `-subtle` (0.08 alpha) rgba siblings that must stay in sync with the base hex — the base doubles as label text on its own subtle tint, and re-tinting one without the other silently drops the pair below AA. Bases stay literal hex because `widget-theme.ts` publishes them to MCP app guest documents where `color-mix()` would not resolve. See the audit comments in `base.css` for the per-theme measurements.
|
||||
|
||||
The dark `--destructive` value is the claw-family override (`:root[data-theme="dark"]`); the shared `:root` fallback is `#ef4444`.
|
||||
|
||||
## Border
|
||||
|
||||
@@ -90,4 +94,4 @@ Light mode uses a warm paper palette: ivory backgrounds, warm gray borders (`#e8
|
||||
- ❌ `--accent-subtle` as text colour — fails contrast on dark backgrounds
|
||||
- ❌ Mixing `--ok` and `--accent-2` for "green success" — use `--ok` only
|
||||
- ❌ Using `--danger` for non-error states (e.g. "hot feature") — reserve for errors and destructive actions
|
||||
- ❌ `--muted-strong` for normal body text — below 4.5:1 on dark `--bg`; use `--text` instead
|
||||
- ❌ `--muted-strong` for normal body text — passes AA on `--bg` but not on every hover/input surface; use `--text` instead
|
||||
|
||||
@@ -57,6 +57,9 @@ class OpenClawImageLightbox extends OpenClawLitElement {
|
||||
overflow: hidden;
|
||||
border: 1px solid color-mix(in srgb, var(--border-strong) 80%, transparent);
|
||||
border-radius: var(--radius-lg);
|
||||
/* Deliberately darker than any theme surface: the lightbox is a
|
||||
photo-viewer chrome that stays near-black in light mode too, so the
|
||||
white text and white-alpha borders below assume this literal. */
|
||||
background: #07090f;
|
||||
box-shadow: 0 28px 90px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ export const panelTabStripStyles = css`
|
||||
}
|
||||
.tabstrip-tab__icon {
|
||||
display: inline-flex;
|
||||
color: var(--accent, #4ec9a8);
|
||||
color: var(--accent, #ff5c5c);
|
||||
}
|
||||
.tabstrip-tab.is-exited .tabstrip-tab__icon {
|
||||
color: var(--muted, #8a919e);
|
||||
@@ -160,9 +160,9 @@ export const panelTabStripStyles = css`
|
||||
color: var(--muted, #8a919e);
|
||||
}
|
||||
.tabstrip-tab__badge {
|
||||
border: 1px solid color-mix(in srgb, var(--accent, #4ec9a8) 45%, transparent);
|
||||
border: 1px solid color-mix(in srgb, var(--accent, #ff5c5c) 45%, transparent);
|
||||
border-radius: 999px;
|
||||
color: var(--accent, #4ec9a8);
|
||||
color: var(--accent, #ff5c5c);
|
||||
font-size: 9px;
|
||||
line-height: 14px;
|
||||
padding: 0 5px;
|
||||
|
||||
@@ -47,7 +47,7 @@ class ResizableDivider extends OpenClawLitElement {
|
||||
left: 50%;
|
||||
width: 1px;
|
||||
transform: translateX(-50%);
|
||||
background: var(--border, #333);
|
||||
background: var(--border, #1e2028);
|
||||
transition:
|
||||
background 150ms ease-out,
|
||||
width 150ms ease-out;
|
||||
@@ -56,10 +56,10 @@ class ResizableDivider extends OpenClawLitElement {
|
||||
:host(.dragging)::after,
|
||||
:host(:focus-visible)::after {
|
||||
width: 2px;
|
||||
background: var(--accent, #007bff);
|
||||
background: var(--accent, #ff5c5c);
|
||||
}
|
||||
:host(:focus-visible) {
|
||||
outline: 2px solid var(--accent, #007bff);
|
||||
outline: 2px solid var(--accent, #ff5c5c);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
:host([orientation="horizontal"]) {
|
||||
|
||||
@@ -29,6 +29,10 @@ const ANSI = {
|
||||
brightWhite: "#ffffff",
|
||||
} as const;
|
||||
|
||||
// Dark mirrors the claw tokens in styles/base.css (`--bg` #0e1015,
|
||||
// `--accent` #ff5c5c) — keep them in sync when the tokens change. Light is a
|
||||
// deliberate neutral cool white: the light theme families diverge (ivory,
|
||||
// cool white, parchment) and the canvas gets only a binary mode.
|
||||
const DYNAMIC_COLORS = {
|
||||
dark: { background: "#0e1015", cursor: "#ff5c5c", foreground: "#d7dae0" },
|
||||
light: { background: "#f7f8fa", cursor: "#1b1e26", foreground: "#1b1e26" },
|
||||
|
||||
Reference in New Issue
Block a user