Verified against GitHub Copilot Chat · 2026-08-03
Point Copilot at the accessibility failures a visual review would miss
An accessibility-focused review prompt for a UI diff that walks through keyboard operability, screen-reader semantics, focus visibility, and color contrast against the actual rendered markup, instead of a general checklist recited without checking whether each item applies here.
The prompt
Ready to copy — highlighted parts are example details you can swap.
Review the SavedSearchDropdown component on the /reports page for accessibility, grounded in the actual markup below, not a general checklist recited without checking whether each item actually applies here. MARKUP OR DIFF The current render output of SavedSearchDropdown.tsx, pasted below, including its button and list markup. INTERACTION PATTERN a disclosure dropdown — a button that reveals a list of options and should close on Escape or an outside click CONTRAST CONTEXT Text color is var(--text-secondary) at #6b7280 on a white background in light theme. EXISTING CONVENTIONS IN THIS CODEBASE This codebase uses the useFocusTrap hook from lib/a11y/focus-trap.ts for every existing modal and dropdown. CHECK EACH OF THESE AGAINST THE ACTUAL MARKUP, NOT IN THE ABSTRACT 1. Keyboard operability — every interactive element reachable and operable using Tab, Shift+Tab, Enter, and Escape where relevant, in an order that matches the visual reading order. For a disclosure dropdown — a button that reveals a list of options and should close on Escape or an outside click specifically, name the exact keyboard behavior expected — for example, a modal should trap focus inside itself while open and return focus to the element that opened it on close, not merely be reachable by Tab like a normal element on the page. 2. Screen-reader semantics — whether the actual elements used communicate their role and state correctly without a screen reader running, based purely on the markup: a clickable div with no role or button semantics is not a button to assistive technology no matter how it looks, and a toggle with no aria-pressed or aria-expanded state gives a screen-reader user no way to know whether it is currently on or off, open or closed. 3. Focus visibility — whether a visible focus indicator survives on every interactive element in this markup, specifically checking for any outline removal in the styles without a replacement focus style, which is one of the single most common and most damaging accessibility regressions in UI code. 4. Color contrast — using Text color is var(--text-secondary) at #6b7280 on a white background in light theme., state the actual contrast ratio for text against its background and against WCAG's 4.5:1 threshold for normal text and 3:1 for large text, rather than a subjective 'looks readable' judgment; if the exact colors are not resolvable from what is given, say so rather than estimating a ratio that sounds authoritative but is not actually computed. 5. Error and status messaging — if this pattern can show an error or a status change, confirm it is announced to a screen reader, not just rendered visually, since a validation error that only appears as a red border communicates nothing to someone who cannot see the border appear. OUTPUT For each of the five checks: PASS or a specific FINDING with the exact line or attribute at fault and the concrete fix, not a general recommendation to add ARIA attributes. If a disclosure dropdown — a button that reveals a list of options and should close on Escape or an outside click or This codebase uses the useFocusTrap hook from lib/a11y/focus-trap.ts for every existing modal and dropdown. makes a check inapplicable to this markup, say so explicitly rather than silently omitting it. Match any fix to This codebase uses the useFocusTrap hook from lib/a11y/focus-trap.ts for every existing modal and dropdown. already used elsewhere in this codebase rather than introducing a second, differently styled way of solving the same accessibility requirement.
Customize
Optional — swap in your own details for the highlighted parts above.
Why this works
Grounding each check against the actual pasted markup, rather than reciting a general accessibility checklist, targets the real failure mode of a bare 'check accessibility' request: it reliably produces true-but-generic ARIA advice that is not actually tethered to whether that advice applies to this specific markup at all, which reads as thorough without being checkable against anything concrete. Requiring the keyboard behavior to be stated per interaction pattern, rather than as one generic operability rule, reflects a genuine fact about accessibility requirements — a modal's expected keyboard behavior, trapping focus and returning it on close, is meaningfully different from a disclosure dropdown's, which mainly needs to close on Escape or an outside click, and a generic checklist has no way to know which specific expectation applies to the widget actually in front of it. Requiring an actual computed contrast ratio against a specific WCAG threshold, rather than a subjective readability judgment, matters because 'looks readable' is not a substitute for a number checked against 4.5:1 or 3:1 — and explicitly instructing the model to say so when the exact colors are not resolvable, rather than estimate a ratio that sounds authoritative, closes off a specific way a confident-sounding number can be wrong without anyone noticing it was never actually computed. Separating screen-reader semantics from visual review addresses the actual gap a sighted code review structurally cannot close on its own — a clickable div that looks exactly like a button to a sighted reviewer communicates nothing about its role to a screen reader, and a toggle with no aria-pressed state gives no signal at all about its current state to someone who cannot see it, which are both failures a review focused on how the UI looks will never surface because looking right and being semantically correct are simply different properties of the same markup.
What you get back
1. Keyboard: dropdown opens on Enter or Space, but Escape does not close it — missing a keydown handler for Escape. 2. Semantics: the trigger is a real button element with aria-expanded, but the list has no listbox role associated with it — screen readers cannot tell the button controls this specific list. 3. Focus: outline removal is set on the trigger with no replacement focus style — flagged, needs a visible focus ring restored. 4. Contrast: 3.9:1 for the disabled-option text against the dropdown background — below the 4.5:1 threshold for normal text. 5. Status messaging: not applicable, this pattern has no error or status state.
Verified against
GitHub Copilot Chat Copilot Chat 1.271 (VS Code) · 2026-08-03
Changelog
- 2026-08-03 — Initial publish, verified against Copilot Chat 1.271 (VS Code).
Need this built into your business?
If a prompt isn't enough — custom software, built and maintained for you — that's Scult's day job.
EXPLORE CUSTOM SOFTWARE
