mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-16 14:40:45 +00:00
Introduce a native dialog-backed Control UI modal primitive and migrate the exec approval, gateway URL confirmation, and dreaming restart confirmation prompts to it. The modal primitive provides aria-modal semantics, shadow-root-local labels/descriptions, focus trapping, safe initial focus, Escape cancellation, and focus restoration while preserving the existing prompt content and decision semantics. Validation: - pnpm lint --threads=8 - pnpm --dir ui test src/ui/components/modal-dialog.test.ts src/ui/views/exec-approval.test.ts src/ui/navigation.browser.test.ts - pnpm test:ui - pnpm exec oxfmt --check --threads=1 ui/src/ui/components/modal-dialog.ts ui/src/styles/config-quick.test.ts - git diff --check CI note: checks-node-core-support-boundary is failing in test/scripts/docker-build-helper.test.ts on an unrelated package-acceptance assertion; the failing files are identical to origin/main and outside this UI-only PR.
55 lines
2.3 KiB
TypeScript
55 lines
2.3 KiB
TypeScript
import { existsSync, readFileSync } from "node:fs";
|
|
import { resolve } from "node:path";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
const cssPath = [
|
|
resolve(process.cwd(), "ui/src/styles/config-quick.css"),
|
|
resolve(process.cwd(), "..", "ui/src/styles/config-quick.css"),
|
|
].find((candidate) => existsSync(candidate));
|
|
if (!cssPath) {
|
|
throw new Error(`config-quick.css not found from cwd: ${process.cwd()}`);
|
|
}
|
|
const css = readFileSync(cssPath, "utf8");
|
|
|
|
describe("config-quick styles", () => {
|
|
it("includes the local user identity quick-settings styles", () => {
|
|
expect(css).toContain(".qs-identity-grid");
|
|
expect(css).toContain(".qs-identity-card__source");
|
|
expect(css).toContain(".qs-identity-card__issue");
|
|
expect(css).toContain(".qs-identity-card__repair");
|
|
expect(css).toContain(".qs-identity-card__error");
|
|
expect(css).toContain(".qs-assistant-avatar");
|
|
expect(css).toContain(".qs-user-avatar");
|
|
expect(css).toContain(".qs-card--personal");
|
|
});
|
|
|
|
it("includes the dashboard quick-settings density layout", () => {
|
|
expect(css).toContain(".qs-card--model");
|
|
expect(css).toContain(".qs-card--automations");
|
|
expect(css).toContain(".qs-side-stack");
|
|
expect(css).toContain("grid-template-rows: auto 1fr;");
|
|
expect(css).toContain(".qs-identity-card__actions");
|
|
expect(css).toContain("grid-template-columns: repeat(12, minmax(0, 1fr));");
|
|
expect(css).toContain("grid-column: 1 / -1;");
|
|
expect(css).toContain("grid-column: span 4;");
|
|
expect(css).toContain("grid-template-columns: repeat(2, minmax(0, 1fr));");
|
|
expect(css).toContain("align-items: stretch;");
|
|
expect(css).toContain("display: contents;");
|
|
expect(css).toContain(".qs-card--appearance {\n order: 4;");
|
|
expect(css).toContain(".qs-card--appearance");
|
|
expect(css).toContain("order: 4");
|
|
expect(css).toContain(".qs-card--automations");
|
|
expect(css).toContain("order: 6");
|
|
});
|
|
|
|
it("includes explicit context profile layout hooks", () => {
|
|
expect(css).toContain(".qs-profiles");
|
|
expect(css).toContain(".qs-profile-state--pending");
|
|
expect(css).toContain(".qs-profile-panel__actions-row");
|
|
});
|
|
|
|
it("avoids transition-all in the quick settings surface", () => {
|
|
expect(css).not.toContain("transition: all");
|
|
});
|
|
});
|