build(lint): adopt stylelint for Control UI css templates and stylesheets (#113971)

This commit is contained in:
Peter Steinberger
2026-07-25 19:13:46 -07:00
committed by GitHub
parent c53ce6a76d
commit 3807591ff4
8 changed files with 1045 additions and 183 deletions
+2
View File
@@ -399,6 +399,8 @@ const config = {
],
// Platform tools and shell builtins used by package scripts and process-boundary tests.
ignoreBinaries: ["mint", "open", "sleep", "xcrun"],
// The stylelint config lives under config/, not a root default path.
stylelint: { config: ["config/stylelint.config.mjs"] },
project: [
".github/actions/**/*.{js,mjs,cjs,ts,mts,cts}!",
"apps/**/*.{js,mjs,cjs,ts,mts,cts}!",
+25
View File
@@ -0,0 +1,25 @@
// Control UI CSS hygiene: plain stylesheets plus css`` templates in Lit
// components (postcss-lit). Error-class rules only — oxfmt owns formatting.
export default {
extends: "stylelint-config-recommended",
rules: {
// Cascade-order advice, not an error class; 400+ intentional hits in the
// existing token/override cascade make it pure noise here.
"no-descending-specificity": null,
// 17 pre-existing duplicates; merging them reorders the cascade and needs
// per-site visual proof. Tighten in a follow-up, keep new code honest via
// review until then.
"no-duplicate-selectors": null,
// `clip` survives only inside the standard sr-only fallback pattern.
"property-no-deprecated": [true, { ignoreProperties: ["clip"] }],
// `word-break: break-word` is deprecated but swapping it for overflow-wrap
// changes min-content sizing in flex/grid text containers.
"declaration-property-value-keyword-no-deprecated": [true, { ignoreKeywords: ["break-word"] }],
},
overrides: [
{
files: ["**/*.ts"],
customSyntax: "postcss-lit",
},
],
};
+6
View File
@@ -1583,7 +1583,9 @@
"lint:tmp:sqlite-transaction-boundary": "node scripts/check-sqlite-transaction-boundary.mjs",
"lint:tmp:tsgo-core-boundary": "node scripts/check-tsgo-core-boundary.mjs",
"lint:ui:i18n": "pnpm ui:i18n:verify",
"lint:ui:lit": "lit-analyzer \"ui/src/**/*.ts\" --quiet",
"lint:ui:no-raw-window-open": "node scripts/run-oxlint.mjs --openclaw-focused-config --config config/oxlint/boundary-guards.json ui/src",
"lint:ui:styles": "stylelint --config config/stylelint.config.mjs \"ui/src/**/*.css\" \"ui/src/**/*.ts\"",
"lint:web-fetch-provider-boundaries": "node scripts/check-web-fetch-provider-boundaries.mjs",
"lint:web-search-provider-boundaries": "node scripts/check-web-search-provider-boundaries.mjs",
"lint:webhook:no-low-level-body-read": "node scripts/check-webhook-auth-body-order.mjs",
@@ -1983,13 +1985,17 @@
"jscpd": "4.2.4",
"jsdom": "29.1.1",
"lit": "3.3.3",
"lit-analyzer": "^2.0.3",
"oxfmt": "0.60.0",
"oxlint": "1.74.0",
"oxlint-tsgolint": "0.25.0",
"playwright": "1.61.1",
"postcss-lit": "^1.4.1",
"shiki": "4.3.1",
"signal-utils": "0.21.1",
"sigstore": "5.0.0",
"stylelint": "^17.14.1",
"stylelint-config-recommended": "^18.0.0",
"tsdown": "0.22.1",
"tsx": "4.23.1",
"unrun": "0.3.1",
+988 -178
View File
File diff suppressed because it is too large Load Diff
+17 -1
View File
@@ -31,9 +31,25 @@ const uiI18nStatus = run(
if (uiI18nStatus !== 0) {
process.exitCode = uiI18nStatus;
} else {
process.exitCode = run(
const oxlintStatus = run(
process.execPath,
[path.resolve("scripts", "run-oxlint-shards.mjs"), ...process.argv.slice(2)],
{ env: process.env, stdio: "inherit" },
);
if (oxlintStatus !== 0) {
process.exitCode = oxlintStatus;
} else {
// Control UI CSS hygiene: plain stylesheets plus css`` templates in Lit
// components. oxlint cannot see inside tagged CSS templates.
process.exitCode = run(
resolveRepoToolBinPath("stylelint"),
[
"--config",
path.resolve("config", "stylelint.config.mjs"),
"ui/src/**/*.css",
"ui/src/**/*.ts",
],
{ env: process.env, stdio: "inherit" },
);
}
}
+6
View File
@@ -17,6 +17,12 @@ This directory owns Control UI-specific guidance that should not live in the rep
- Prioritization report: `pnpm ui:i18n:report [--surface <name>] [--locale <locale>] [--top <n>]` shows current hardcoded-copy focus areas and locale fallback metadata. It is not a drift gate; use `pnpm ui:i18n:check` for that.
- If locale outputs drift, let the workflow reconcile them or run release prep. Do not manually translate, merge, or hand-maintain generated locale files.
## CSS / Template Linting
- `pnpm lint:ui:styles` runs stylelint over `ui/src` stylesheets and Lit `css` templates (postcss-lit). `pnpm lint` includes it; error-class rules only, oxfmt owns formatting. Config: `config/stylelint.config.mjs`.
- Icons: shared 24x24 Lucide icons go through `strokeIcon()` in `ui/src/components/icons-tools.ts` so stroke presentation attributes stay inline and render inside shadow roots. Icon bodies are `svg\`\``fragments, never`html\`\`` (wrong namespace renders nothing).
- `pnpm lint:ui:lit` is an opt-in lit-analyzer diagnostic for template bindings (slow, ~9 min; known baseline of pre-existing findings). It is not a CI gate.
## Scope
- Keep UI-specific rules here.
+1 -1
View File
@@ -515,7 +515,7 @@ img.chat-avatar {
max-width: 100%;
box-sizing: border-box;
min-width: 0;
word-wrap: break-word;
overflow-wrap: break-word;
}
.chat-group.workspace-conflict .chat-group-messages {
-3
View File
@@ -2720,9 +2720,6 @@ td.data-table-key-col {
gap: 4px;
}
.field-inline.checkbox input[type="checkbox"] {
}
/* ===========================================
Log Stream
=========================================== */