feat(e10): put the 1024x768 size contract inside the primitives
S1c, the last part of S1. The contract now lives in components/ui/ and in one CSS recipe instead of in ~160 call sites: - Minimum target 2.75rem, on coarse pointers only (.touch-target). A 32px icon button is fine with a mouse -- precise pointer, hover to confirm the aim -- and not fine with a thumb, so it grows exactly where there is no precise pointer, which on this app's real second device is the tablet. It grows the real box rather than painting an invisible ::after hit area, because two expanded hit areas on icon buttons 4px apart would overlap and the overlap fires the WRONG button. `link` is excluded: it is text inside a sentence. - 2.75rem rather than 44px so the target obeys the text-size slider like everything else; verified that the type/geometry ladder was already rem-derived off --font-scale, so nothing else was needed there. - The ladder is documented as a closed set in Button.tsx, with the site counts it was derived from, and ui/README.md states the contract. Measured in the browser: fine pointer 36x36 and 34px-tall buttons (unchanged), coarse pointer the same buttons at 44x44 and 44px tall. 1024x768 renders identically. 3x tsc, eslint, knip, prettier and 690 vitest green.
This commit is contained in:
@@ -98,6 +98,18 @@ describe("Button primitive (S5)", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("carries the coarse-pointer minimum target, except on a link", () => {
|
||||
// The 1024x768 comfort contract: the minimum lives in the primitive, so no call site can opt
|
||||
// out of it by accident. A link is text in a sentence and is excluded by design.
|
||||
const { unmount } = render(<Button>Tap</Button>);
|
||||
expect(screen.getByRole("button", { name: "Tap" }).className).toContain("touch-target");
|
||||
unmount();
|
||||
render(<Button variant="link">Read more</Button>);
|
||||
expect(screen.getByRole("button", { name: "Read more" }).className).not.toContain(
|
||||
"touch-target",
|
||||
);
|
||||
});
|
||||
|
||||
it("fullWidth adds the w-full utility", () => {
|
||||
render(<Button fullWidth>Wide</Button>);
|
||||
expect(screen.getByRole("button", { name: "Wide" }).className).toContain("w-full");
|
||||
|
||||
Reference in New Issue
Block a user