-
Notifications
You must be signed in to change notification settings - Fork 450
Axe overlay polish: left-align report and scroll highlighted elements clear of it #14680
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
bdc04d9
Left-align the axe report overlay instead of inheriting page centering
cwickham b016240
Scroll highlighted elements clear of the axe report overlay
cwickham 702a7e8
Add changelog entries for axe overlay polish
cwickham 1f9dce1
Add PR link to changelog entries
cwickham 7ea8e76
Make the fixed axe overlay a focusable region so it can scroll by key…
cwickham 268b116
Add regression test that the report overlay passes axe-core's own scan
cwickham 3dc2133
Act on a single scroll target per axe report node hover
cderv 044702a
Revert "Act on a single scroll target per axe report node hover"
cderv File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| --- | ||
| format: | ||
| html: | ||
| axe: | ||
| output: document | ||
| --- | ||
|
|
||
| ## Long Document | ||
|
|
||
| The dozen violations below inflate the report to its `max-height: 50vh`, so the | ||
| fixed overlay really covers the lower half of the viewport — with only one | ||
| violation the report is short and even default centered scrolling clears it. | ||
|
|
||
| [low contrast 1]{#c1 style="color: #eee; background: #fff;"} | ||
|
|
||
| [low contrast 2]{#c2 style="color: #eee; background: #fff;"} | ||
|
|
||
| [low contrast 3]{#c3 style="color: #eee; background: #fff;"} | ||
|
|
||
| [low contrast 4]{#c4 style="color: #eee; background: #fff;"} | ||
|
|
||
| [low contrast 5]{#c5 style="color: #eee; background: #fff;"} | ||
|
|
||
| [low contrast 6]{#c6 style="color: #eee; background: #fff;"} | ||
|
|
||
| [low contrast 7]{#c7 style="color: #eee; background: #fff;"} | ||
|
|
||
| [low contrast 8]{#c8 style="color: #eee; background: #fff;"} | ||
|
|
||
| [low contrast 9]{#c9 style="color: #eee; background: #fff;"} | ||
|
|
||
| [low contrast 10]{#c10 style="color: #eee; background: #fff;"} | ||
|
|
||
| [low contrast 11]{#c11 style="color: #eee; background: #fff;"} | ||
|
|
||
| [low contrast 12]{#c12 style="color: #eee; background: #fff;"} | ||
|
|
||
| Filler so the page scrolls well past one viewport; the hovered violation sits | ||
| near the bottom where centering it would put it under the report overlay. | ||
|
|
||
| ::: {style="height: 3000px;"} | ||
| ::: | ||
|
|
||
| ::: {#bottom-contrast style="color: #eee; background: #fff;"} | ||
| This full-width block near the bottom of the page violates contrast rules, so | ||
| its bounding box overlaps the report overlay horizontally. | ||
| ::: | ||
|
|
||
| ::: {style="height: 400px;"} | ||
| ::: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
cderv marked this conversation as resolved.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| /* | ||
| * axe-overlay-scroll.test.ts | ||
| * | ||
| * Tests the scroll-target computation the axe document reporter uses to keep a | ||
| * highlighted element from landing underneath the fixed report overlay. | ||
| * | ||
| * `overlayAwareScrollTop` is a pure function of viewport-relative rects and | ||
| * scroll state, so these tests need no DOM: each case hand-constructs the rects | ||
| * and asserts either the returned scrollTop or null (which tells the caller to | ||
| * keep the default `scrollIntoView({block: "center"})` behavior). | ||
| * | ||
| * Copyright (C) 2020-2025 Posit Software, PBC | ||
| */ | ||
|
|
||
| import { unitTest } from "../test.ts"; | ||
| import { assertEquals } from "testing/asserts"; | ||
| import { overlayAwareScrollTop } from "../../src/resources/formats/html/axe/axe-check.js"; | ||
|
|
||
| // A bottom-right overlay in a 1280x720 viewport: top edge at y=400, left edge | ||
| // at x=800. The unobscured band above it is [0, 400], centered at y=200. | ||
| const overlay = { top: 400, left: 800 }; | ||
| const viewportHeight = 720; | ||
|
|
||
| unitTest( | ||
| "overlayAwareScrollTop - no horizontal overlap returns null", | ||
| // deno-lint-ignore require-await | ||
| async () => { | ||
| // Element's right edge (700) is left of the overlay's left edge (800), so | ||
| // default centering can't put it under the overlay. | ||
| assertEquals( | ||
| overlayAwareScrollTop( | ||
| { top: 600, right: 700, height: 100 }, | ||
| overlay, | ||
| viewportHeight, | ||
| 1000, | ||
| ), | ||
| null, | ||
| ); | ||
| }, | ||
| ); | ||
|
|
||
| unitTest( | ||
| "overlayAwareScrollTop - overlapping element is centered in the band above the overlay", | ||
| // deno-lint-ignore require-await | ||
| async () => { | ||
| // Element at viewport y=600, height 100. Centering it at the band's center | ||
| // (y=200) means its top must land at y=150, i.e. scroll down 450 more: | ||
| // 1000 + 600 - (400/2 - 100/2) = 1450. | ||
| assertEquals( | ||
| overlayAwareScrollTop( | ||
| { top: 600, right: 1100, height: 100 }, | ||
| overlay, | ||
| viewportHeight, | ||
| 1000, | ||
| ), | ||
| 1450, | ||
| ); | ||
| }, | ||
| ); | ||
|
|
||
| unitTest( | ||
| "overlayAwareScrollTop - element taller than the band is top-aligned with a margin", | ||
| // deno-lint-ignore require-await | ||
| async () => { | ||
| // Height 500 exceeds the 400px band, so align its start just inside the | ||
| // viewport top instead of centering: 1000 + 600 - 16 = 1584. | ||
| assertEquals( | ||
| overlayAwareScrollTop( | ||
| { top: 600, right: 1100, height: 500 }, | ||
| overlay, | ||
| viewportHeight, | ||
| 1000, | ||
| ), | ||
| 1584, | ||
| ); | ||
| }, | ||
| ); | ||
|
|
||
| unitTest( | ||
| "overlayAwareScrollTop - scrollTop is clamped at the document top", | ||
| // deno-lint-ignore require-await | ||
| async () => { | ||
| // Centering would need scrollTop 0 + 50 - 150 = -100; clamp to 0. | ||
| assertEquals( | ||
| overlayAwareScrollTop( | ||
| { top: 50, right: 1100, height: 100 }, | ||
| overlay, | ||
| viewportHeight, | ||
| 0, | ||
| ), | ||
| 0, | ||
| ); | ||
| }, | ||
| ); | ||
|
|
||
| unitTest( | ||
| "overlayAwareScrollTop - degenerate band (overlay covers the viewport) returns null", | ||
| // deno-lint-ignore require-await | ||
| async () => { | ||
| // Overlay top edge nearly at the viewport top leaves no usable band to | ||
| // scroll the element into; fall back to default centering. | ||
| assertEquals( | ||
| overlayAwareScrollTop( | ||
| { top: 600, right: 1100, height: 100 }, | ||
| { top: 20, left: 100 }, | ||
| viewportHeight, | ||
| 1000, | ||
| ), | ||
| null, | ||
| ); | ||
| }, | ||
| ); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.