Skip to content

Commit 5ae57d2

Browse files
committed
Check the annotation marker stays hoverable in a callout
With the copy button back inside the code frame, an annotated first line in a callout puts the button over the annotation marker, the same overlap #13444 fixes outside callouts. A hit test on the marker covers the callout case. It fails without the annotated button rule and passes with it. That rule also drops the annotated button's top margin, so its position is now compared with an annotated block outside a callout instead of a plain one.
1 parent 51aaee8 commit 5ae57d2

2 files changed

Lines changed: 50 additions & 12 deletions

File tree

‎tests/docs/playwright/html/callout-code-copy-button.qmd‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,18 @@ echo "plain"
1414

1515
:::
1616

17+
## Plain, annotated
18+
19+
::: {#plain-annotated}
20+
21+
```python
22+
import polars as pl # <1>
23+
```
24+
25+
1. Import polars.
26+
27+
:::
28+
1729
## Titled, paragraph only
1830

1931
::: {#titled-paragraph .callout-note}

‎tests/integration/playwright/tests/html-callout-code-copy-button.spec.ts‎

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,18 @@ async function geometry(page: Page, id: string): Promise<Geometry> {
5252
}, id);
5353
}
5454

55-
// Code callouts, with the paragraph-only callout of the same appearance
56-
// they are compared with at the edge where the code sits.
55+
// Code callouts, with the block outside a callout their copy button is
56+
// compared with, and the paragraph-only callout of the same appearance they
57+
// are compared with at the edge where the code sits.
5758
const cases = [
58-
{ id: "titled-first", edge: "top", reference: "titled-paragraph" },
59-
{ id: "titled-last", edge: "bottom", reference: "titled-paragraph" },
60-
{ id: "titled-cell-first", edge: "top", reference: "titled-paragraph" },
61-
{ id: "titled-cell-last", edge: "bottom", reference: "titled-paragraph" },
62-
{ id: "titled-annotated", edge: "top", reference: "titled-paragraph" },
63-
{ id: "collapse-first", edge: null, reference: null },
64-
{ id: "simple-first", edge: "top", reference: "simple-paragraph" },
65-
{ id: "minimal-last", edge: "bottom", reference: "minimal-paragraph" },
59+
{ id: "titled-first", button: "plain", edge: "top", reference: "titled-paragraph" },
60+
{ id: "titled-last", button: "plain", edge: "bottom", reference: "titled-paragraph" },
61+
{ id: "titled-cell-first", button: "plain", edge: "top", reference: "titled-paragraph" },
62+
{ id: "titled-cell-last", button: "plain", edge: "bottom", reference: "titled-paragraph" },
63+
{ id: "titled-annotated", button: "plain-annotated", edge: "top", reference: "titled-paragraph" },
64+
{ id: "collapse-first", button: "plain", edge: null, reference: null },
65+
{ id: "simple-first", button: "plain", edge: "top", reference: "simple-paragraph" },
66+
{ id: "minimal-last", button: "plain", edge: "bottom", reference: "minimal-paragraph" },
6667
] as const;
6768

6869
test.describe("Code copy button in callouts", () => {
@@ -72,9 +73,9 @@ test.describe("Code copy button in callouts", () => {
7273
});
7374
});
7475

75-
for (const { id, edge, reference } of cases) {
76+
for (const { id, button, edge, reference } of cases) {
7677
test(`${id}: copy button sits inside the code frame`, async ({ page }) => {
77-
const plain = await geometry(page, "plain");
78+
const plain = await geometry(page, button);
7879
const code = await geometry(page, id);
7980
expect(code.buttonOffset).not.toBeNull();
8081
expect(Math.abs(code.buttonOffset! - plain.buttonOffset!))
@@ -92,4 +93,29 @@ test.describe("Code copy button in callouts", () => {
9293
});
9394
}
9495
}
96+
97+
// Inside the code frame, the button of an annotated first line must still
98+
// leave the annotation marker hoverable, as it does outside a callout.
99+
test("titled-annotated: copy button does not cover the marker", async ({ page }) => {
100+
const anchor = page.locator(
101+
"div#titled-annotated button.code-annotation-anchor",
102+
);
103+
await expect(anchor).toHaveCount(1);
104+
// elementFromPoint only sees the viewport.
105+
await anchor.scrollIntoViewIfNeeded();
106+
const box = (await anchor.boundingBox())!;
107+
const x = box.x + box.width / 2;
108+
const y = box.y + box.height / 2;
109+
110+
// Hovering the marker also reveals the copy button.
111+
await page.mouse.move(x, y);
112+
const hit = await page.evaluate(
113+
([px, py]) =>
114+
document.elementFromPoint(px, py)?.closest(
115+
".code-annotation-anchor, .code-copy-button",
116+
)?.className ?? null,
117+
[x, y],
118+
);
119+
expect(hit).toContain("code-annotation-anchor");
120+
});
95121
});

0 commit comments

Comments
 (0)