mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-22 18:51:16 +00:00
* feat(ui): add settings design-language foundation (tokens, settings.css, helpers) * refactor(ui): move settings workspace shell styles into settings.css * refactor(ui): migrate all settings surfaces to the unified settings design language Every settings surface (General quick+advanced schema form, Appearance, Communications, Automation, MCP, Infrastructure, AI Agents, Channels, Connection, About, Profile, Model Providers, Plugins, Skills, Skill Workshop chrome, Devices, Worktrees, Debug, Logs, Activity, Automations, Sessions, Usage chrome) now renders through the settings-ui helpers and settings.css: sections as plain uppercase headings outside one flat group surface, hairline-divided rows, a single toggle/segmented/status vocabulary, status dots instead of pills, and no cards-in-cards or enter animations. Deletes the qs-*/cfg-*/config-section-card/account-card/ plugins-row/cron-editor-card/session-badge/agent-pill families and orphaned shared rules. * style(ui-docs): format design-system docs * fix(ui): make activity statusKind lookup exhaustive for consistent-return lint * fix(ui): address settings design-language review findings Label-wrapped toggle rows with required accessible names, named selects and cron form controls, busy-disabled segmented controls with restored theme-transition anchors, collapsible skill groups, semantic plugin headings, gateway connected status, paired-devices empty state, logs subtitle, cron prompt help, and keyboard-accessible session goal objectives. * fix(ui): harden settings primitives per review round two Wrap row action clusters, fully-inset nav focus ring, restore number steppers in the schema form, cap node capability lines, keep the named Activity region landmark, and associate cron help text via the row label. * fix(ui): skip empty section headings and fix the toggle doc example * docs(ui): import renderSettingsToggleRow in the settings example * fix(ui): rename number stepper delta to avoid shadowing
3.3 KiB
3.3 KiB
Settings Design Language
Every settings surface (the /settings takeover pages plus the Plugins/Skills hubs) uses one structural pattern. Styles live in ui/src/styles/settings.css; templates are built through the helpers in ui/src/components/settings-ui.ts.
Anatomy
.settings-page ← single column, 760px (or --wide: 1120px)
.settings-section ← repeated per topic
.settings-section__heading ← plain uppercase text label, outside any surface
.settings-group ← the ONLY surface (card bg, border, radius-lg)
.settings-row ← title/description left, one control right
.settings-row ← hairline divider between rows
- Sections are typography, not chrome. Grouping comes from whitespace + a small uppercase heading — never a card header.
- Exactly one level of elevation. A group never contains another card, callout, or bordered box. Nested detail uses
.settings-subrows(indented rows), a stacked row, or a drill-in nav row. - Row anatomy: left is title (
--control-ui-text-md, weight 500) over an optional one-line description (muted, sm). Right is exactly one control: toggle, select, segmented, button, plain value, or chevron (nav). Wide editors use thestackedvariant. - Lists are rows too. An entity list (plugin, device, session) is a group whose rows carry an action cluster in the control slot — same anatomy as a toggle row.
Rules
- No status pills. Status is
renderSettingsStatus— a dot + plain text (● Connected). Badges (.settings-count) exist only for genuine counts. - Spacing uses
--space-*tokens (base.css); no hardcoded paddings/gaps. - Motion budget: color/background transitions only. No enter animations, staggered reveals, or hover glows.
- Buttons: default
.btn(quiet).--accentprimary at most once per view. Danger actions live in adanger: truesection at the page bottom. - One control set. Use
renderSettingsToggleRow(preferred: label-wrapped, whole row clickable, accessible name for free) orrenderSettingsTogglewith a requiredariaLabel,renderSettingsSegmented,.settings-select,.settings-input. Do not add another toggle or badge variant. - Every control needs an accessible name. Row titles are plain text, not
<label>s — selects/inputs in a control slot must carryaria-label(usually the row title string). - No new page CSS files for settings surfaces. Page-specific styles belong in
settings.cssonly when a primitive is genuinely missing — extend the system, don't fork it.
Helpers
import {
renderSettingsPage,
renderSettingsSection,
renderSettingsRow,
renderSettingsNavRow,
renderSettingsToggleRow,
renderSettingsSegmented,
renderSettingsStatus,
renderSettingsValue,
renderSettingsEmpty,
} from "../../components/settings-ui.ts";
renderSettingsPage([
renderSettingsSection({ title: t("settings.notifications") }, [
renderSettingsToggleRow({
title: t("settings.systemNotifications"),
description: t("settings.systemNotificationsDesc"),
checked,
onChange,
}),
]),
]);
Custom content inside a group (tables, meters) is allowed as an escape hatch — keep it inside one .settings-group and match row paddings (--space-3 --space-4).