Files
openclaw/ui/src/app/control-ui-hover-guard.node.test.ts
Peter Steinberger bfe1f33ea0 improve(ui): make Control UI feel native on mobile (#122492)
* improve(ui): make Control UI feel native on mobile

* fix(ui): keep coarse-pointer input floor text-scale aware

* fix(ui): let self-sized controls opt out of the touch input floor

* fix(ui): fold per-control coarse-pointer font floors into the shared touch floor
2026-08-12 00:46:35 -07:00

59 lines
2.1 KiB
TypeScript

// @vitest-environment node
import postcss, { type AtRule, type Rule } from "postcss";
import { describe, expect, it } from "vitest";
import { controlUiHoverGuardPlugin } from "../../config/control-ui-hover-guard.ts";
async function transform(css: string) {
return postcss([controlUiHoverGuardPlugin()]).process(css, { from: undefined });
}
function requireRule(node: unknown): Rule {
expect(node).toMatchObject({ type: "rule" });
return node as Rule;
}
function requireAtRule(node: unknown): AtRule {
expect(node).toMatchObject({ type: "atrule" });
return node as AtRule;
}
describe("Control UI hover guard", () => {
it("wraps a hover rule in a hover-capable media query", async () => {
const result = await transform(".button:hover { color: red; }");
const guard = requireAtRule(result.root.first);
expect(guard.params).toBe("(hover: hover)");
expect(requireRule(guard.first).selector).toBe(".button:hover");
});
it("splits mixed selector lists without moving non-hover selectors", async () => {
const result = await transform(".a:hover, .b:focus { color: red; }");
const [original, guard] = result.root.nodes;
expect(requireRule(original).selector).toBe(".b:focus");
expect(requireRule(requireAtRule(guard).first).selector).toBe(".a:hover");
});
it("does not double-wrap an already guarded hover rule", async () => {
const css = "@media (hover: hover) { .a:hover { color: red; } }";
expect((await transform(css)).css).toBe(css);
});
it("preserves an outer media condition around the hover guard", async () => {
const result = await transform("@media (max-width: 768px) { .a:hover { color: red; } }");
const outer = requireAtRule(result.root.first);
const guard = requireAtRule(outer.first);
expect(outer.params).toBe("(max-width: 768px)");
expect(guard.params).toBe("(hover: hover)");
expect(requireRule(guard.first).selector).toBe(".a:hover");
});
it("passes CSS without hover selectors through byte-identically", async () => {
const css = ".button:focus { color: red; }\n";
expect((await transform(css)).css).toBe(css);
});
});