diff --git a/packages/cli/src/commands/layout-audit.browser.js b/packages/cli/src/commands/layout-audit.browser.js index c8ee8b6c67..c250014f03 100644 --- a/packages/cli/src/commands/layout-audit.browser.js +++ b/packages/cli/src/commands/layout-audit.browser.js @@ -1348,6 +1348,7 @@ for (const hit of stack) { if (!isForeignElement(element, hit)) return null; // Pair-specific exemptions excuse this hit only; keep walking for deeper occluders. + if (hasIgnoreFlag(hit)) continue; if (sharedPreserve3d(element, hit)) continue; if (isCrossSceneTransitionOverlap(element, hit)) continue; const matte = seenMattes && matteFrameFor(hit); diff --git a/packages/cli/src/commands/layout-audit.browser.test.ts b/packages/cli/src/commands/layout-audit.browser.test.ts index f3a42a208d..900c29824f 100644 --- a/packages/cli/src/commands/layout-audit.browser.test.ts +++ b/packages/cli/src/commands/layout-audit.browser.test.ts @@ -3251,6 +3251,17 @@ describe("layout-audit.browser occlusion", () => { expect(issues.some((issue) => issue.code === "text_occluded")).toBe(false); }); + it("does not count an element marked data-layout-ignore as covering the text", () => { + const style = { backgroundColor: "rgb(10, 10, 10)" }; + const issues = (overlayAttrs?: string) => + auditOcclusionScene({ overlayAttrs, overlayStyle: style, topmostId: "overlay" }); + + expect(issues().some((issue) => issue.code === "text_occluded")).toBe(true); + expect(issues("data-layout-ignore").some((issue) => issue.code === "text_occluded")).toBe( + false, + ); + }); + it("respects the data-layout-allow-occlusion opt-out", () => { const issues = auditOcclusionScene({ headlineAttrs: "data-layout-allow-occlusion", @@ -3636,13 +3647,14 @@ function auditCoverageScene(options: { function auditOcclusionScene(options: { headlineAttrs?: string; + overlayAttrs?: string; overlayStyle: Partial>; topmostId: string; }): ReturnType { document.body.innerHTML = `
Headline copy
-
+
`; installOcclusionGeometry({