diff --git a/ui/docs/design-system/README.md b/ui/docs/design-system/README.md new file mode 100644 index 00000000000..40dc4631d69 --- /dev/null +++ b/ui/docs/design-system/README.md @@ -0,0 +1,20 @@ +# OpenClaw Design System + +OpenClaw's visual language is a **dark-first, glass-surface system** built around a deep charcoal base (`#0e1015`), a punchy signature red accent (`#ff5c5c`), and layered frosted-glass surfaces that create depth without solid panels. Motion is crisp and purposeful — fast micro-interactions (100ms) with spring-loaded expansions. All interactive elements meet WCAG 2.1 AA contrast requirements on dark backgrounds. + +## Contents + +| File | What it covers | +| ---------------------------------------- | --------------------------------------------------------------------------------------- | +| [glass-surfaces.md](./glass-surfaces.md) | Two glass tiers, exact CSS values, no-solid-panels rule, `@supports` fallback | +| [color-tokens.md](./color-tokens.md) | All design tokens with values, usage, contrast ratios, and anti-patterns | +| [motion.md](./motion.md) | Duration scale, easing functions, `prefers-reduced-motion` pattern, animation inventory | +| [accessibility.md](./accessibility.md) | WCAG checklist: contrast, focus, tap targets, ARIA, skip link, focus trap | + +## Guiding Principles + +1. **Glass, not solid** — Surfaces use `backdrop-filter` blur + semi-transparent backgrounds. No flat opaque panels in the main chrome. +2. **Depth through layering** — The background scale (`--bg`, `--bg-accent`, `--bg-elevated`, `--bg-hover`, `--bg-muted`) communicates hierarchy without heavy borders. +3. **Accent with restraint** — Signature red (`--accent: #ff5c5c`) for primary actions only; teal (`--accent-2`) for secondary/status. +4. **Motion serves meaning** — Animations telegraph state changes; they never play for decoration alone. +5. **Accessible by default** — Every component ships with focus-visible styles, correct ARIA roles, and ≥4.5:1 contrast on text. diff --git a/ui/docs/design-system/accessibility.md b/ui/docs/design-system/accessibility.md new file mode 100644 index 00000000000..63722c22cf5 --- /dev/null +++ b/ui/docs/design-system/accessibility.md @@ -0,0 +1,140 @@ +# Accessibility + +OpenClaw targets **WCAG 2.1 AA**. This checklist applies to every UI component — use it when building new components and during PR review. + +--- + +## Contrast Minimums + +| Context | Minimum Ratio | Notes | +| ----------------------------------------- | ---------------- | -------------------------------------------------- | +| Normal body text (< 18px / < 14px bold) | **4.5:1** | Use `--text` (#d4d4d8) or stronger on `--bg` | +| Large text (≥ 18px regular / ≥ 14px bold) | **3:1** | Headings in chat thread | +| UI component boundaries (inputs, buttons) | **3:1** | Border colours against adjacent background | +| Focus indicators | **3:1** (AA) | `--focus-ring` / `--focus-glow` already compliant | +| Placeholder text | Best-effort ≥3:1 | `--muted` (#838387) is ~5:1 on `--bg` — acceptable | + +> Verify with [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/) or browser DevTools accessibility panel. + +--- + +## Checklist + +### 1. Focus Visible + +- [ ] All interactive elements have a visible `:focus-visible` style +- [ ] Use `--focus-ring` box-shadow pattern from `base.css` — do not remove the outline without replacing it +- [ ] Never use `outline: none` alone; replace with `box-shadow: var(--focus-ring)` and `outline: none` + +```css +/* Correct pattern */ +.my-button:focus-visible { + outline: none; + box-shadow: var(--focus-ring); +} +``` + +### 2. Minimum Tap / Click Target Size + +- [ ] All interactive controls are ≥ **44×44px** on mobile / touch targets +- [ ] Icon-only buttons add invisible padding to reach 44px (`min-width: 44px; min-height: 44px`) +- [ ] Verify on the mobile breakpoint (`@media (max-width: 768px)`) + +### 3. Skip Link + +- [ ] A visually-hidden skip link (`#skip-to-main`) is present in the document root +- [ ] The link becomes visible on focus +- [ ] Target element has `tabindex="-1"` to accept programmatic focus + +```html + +``` + +```css +.skip-link { + position: absolute; + left: -9999px; + top: 0; + z-index: 9999; +} +.skip-link:focus { + left: 1rem; + top: 1rem; + /* ... visible styles */ +} +``` + +### 4. Focus Trap + +- [ ] Modal dialogs trap focus inside while open (Tab/Shift+Tab cycle within the modal) +- [ ] Closing the modal returns focus to the trigger element +- [ ] Escape key closes the modal + +### 5. ARIA Labels + +- [ ] Icon-only buttons have `aria-label` describing the action (not the icon name) +- [ ] Progress bars use `role="progressbar"` with `aria-valuenow`, `aria-valuemin`, `aria-valuemax` +- [ ] Live regions updating async content use `aria-live="polite"` (or `"assertive"` for critical alerts) +- [ ] Decorative SVG icons have `aria-hidden="true"` + +```html + + + + +
+
+
+``` + +### 6. Tab Role Pattern + +When building a tab interface: + +- [ ] Tab container: `role="tablist"` +- [ ] Each tab: `role="tab"`, `aria-selected="true|false"`, `aria-controls="panel-id"` +- [ ] Each panel: `role="tabpanel"`, `id` matching `aria-controls`, `aria-labelledby` pointing to its tab +- [ ] Keyboard: Arrow keys move between tabs; Tab moves into the panel; Shift+Tab exits + +```html +
+ + +
+
+ +``` + +### 7. Reduced Motion + +- [ ] No animation plays without being suppressible via `prefers-reduced-motion` +- [ ] The global reset in `base.css` covers transitions — test with "Reduce motion" enabled in OS settings +- [ ] Infinite loaders (`shimmer`, spinners) have explicit `animation: none` in reduced-motion context + +### 8. Semantic HTML + +- [ ] Use native elements (`