ADA / WCAG Findings Snapshot — Sample Teardown
A worked example of how DueBench documents accessibility findings: what an automated scanner catches, what it misses, and how you can reproduce every check yourself — free, in about 15 minutes. Published 2026-07-16.
| Specimen | "Millbrook Outfitters" — a fictional small e-commerce storefront (outdoor/apparel retail, ~30 SKUs, templated storefront + custom checkout). No such company is asserted to exist; any resemblance to a real business is coincidental. |
| Engagement type | Technical accessibility findings snapshot (static, source/markup-level) — not a live scan of any deployed system |
| Prepared by | DueBench — Code Trust Audit |
| Status | Published sample / capability demonstration |
About this document. The defect patterns below are composites of the kind of thing this methodology (axe-core + WAVE automated scan, plus manual keyboard/visual/code-level review) most commonly surfaces on small-business retail sites — illustrated against representative markup we wrote for this purpose. Every finding is independently reproducible by any reader against their own site using the method described in each entry. This document is not legal advice, does not certify ADA compliance or WCAG conformance, and makes no claim that fixing these items eliminates legal risk. That distinction matters: a January 2025 FTC settlement (finalized April 2025) required accessiBe, a large accessibility-overlay vendor, to pay $1,000,000 over deceptive claims that its automated product could make any website WCAG-compliant and keep it compliant over time. We make no automated-compliance claim and no litigation-protection claim, here or anywhere. See §8 for the full scope statement.
0. Why this exists
Our Code Trust Audit reviews source code for security and "is-it-real" business-logic gaps at three fixed-fee tiers. ADA/WCAG defects are the same kind of thing from a different angle: a verifiable, dated, file-and-rule-level technical finding that a non-technical founder cannot see for themselves and cannot get a straight answer on from a linter alone. This page is the proof-of-capability for that extension — it is not a separately priced service yet (see §9). It exists so that anyone considering this kind of review can see the exact shape of the deliverable first — not so we can claim readiness we don't have.
1. The specimen
"Millbrook Outfitters" is a fictional mid-market storefront: a product listing/grid page, a product detail page, a filter/sort sidebar, a "quick view" modal, and a multi-step checkout form. This is a deliberately ordinary combination — the same page types present on a large share of small-business retail sites, and the defect categories they host (low-contrast text, missing form labels, unnamed controls, missing document language) are the ones that dominate WebAIM's annual Million survey of one million home pages (most recent scan: February 2026). Nothing about this specimen is drawn from a real company's code or content.
2. Executive summary
The snapshot below documents 10 findings across all four WCAG principles (Perceivable, Operable, Understandable, Robust). None of this is exotic: every pattern here is common, well-documented, and has a known fix. Of the 10:
- 3 are automatically detectable (axe-core / WAVE) — the kind of thing any free scanner catches in seconds.
- 6 require a manual keyboard-only walkthrough or a visual/code judgment call — the kind of thing no automated scanner can reliably catch, because it requires understanding what the interface is trying to do, not just parsing its markup. One of them (F-07) actively passes the relevant automated check.
- 1 is a hybrid — covered by an axe-core WCAG 2.2 rule that ships disabled by default, confirmed by manual measurement.
That split is the point of this document as a capability demonstration: an automated scan alone (the $0–60 end of the market) would hand Millbrook a report with 3 items on it and miss the other 7 entirely, including two of the three defects rated Critical below (F-05's modal trap, and F-07's unlabeled checkout inputs — which pass automated label checks, because placeholder text is counted toward the accessible name).
Findings at a glance
| Impact | Count |
|---|---|
| 🔴 Critical | 3 |
| 🟠 Serious | 2 |
| 🟡 Moderate | 3 |
| ⚪ Minor | 2 |
| Total | 10 |
What "Critical" means here: it means a user relying on assistive technology (screen reader, keyboard-only navigation) cannot complete a core task — add an item to cart, understand a required form field, or exit a modal — using only that assistive technology. It does not mean "you will be sued" or "this is illegal." Whether any specific gap creates legal exposure depends on jurisdiction, applicable regulation, and case law, and is a question for a lawyer, not a code-review vendor. See §8.
3. How to read this snapshot
Impact ratings use axe-core's four-level vocabulary (minor / moderate /
serious / critical) rather than a proprietary severity scale, and are then set by task
impact on this interface. Where our rating deliberately departs from axe's own default for a
rule, the finding says so inline (see F-09, F-10). WCAG SC references per finding follow this
methodology's mapping, which is sometimes broader than the single SC tag axe attaches to a rule
(axe tags button-name and label only to 4.1.2, for example); the underlying defect stands
either way.
| Impact | Meaning |
|---|---|
| 🔴 Critical | Blocks a core task entirely for keyboard-only or screen-reader users. |
| 🟠 Serious | Major friction or a significant chance of failure completing the task. |
| 🟡 Moderate | Real barrier for some users; workarounds usually exist. |
| ⚪ Minor | Hygiene / best-practice gap; low individual impact, worth fixing opportunistically. |
WCAG references are to WCAG 2.2 success-criterion numbers (2.2 kept the 2.1 numbering — with one removal, 4.1.1 Parsing, now obsolete — and added nine new success criteria; one of them, 2.5.8 Target Size (Minimum), appears below). Level (A / AA) is noted per finding.
4. Findings summary table
| ID | Impact | Finding | WCAG SC | Level | Detectable by |
|---|---|---|---|---|---|
| F-01 | 🔴 Critical | Icon-only "add to cart" / nav controls with no accessible name | 1.1.1, 4.1.2 | A | Automated (axe: button-name) |
| F-02 | 🟠 Serious | Body/link text contrast below 4.5:1 | 1.4.3 | AA | Automated (axe: color-contrast) |
| F-03 | 🟡 Moderate | Sale price / required-field shown by color alone | 1.4.1 | A | Manual only |
| F-04 | 🟠 Serious | Custom filter/sort control not operable by keyboard | 2.1.1, 4.1.2 | A | Manual only |
| F-05 | 🔴 Critical | "Quick view" modal is a keyboard/focus trap | 2.1.2, 2.4.3 | A | Manual only |
| F-06 | 🟡 Moderate | No skip-navigation link / no bypass mechanism | 2.4.1 | A | Manual (axe's bypass heuristic exists but is unreliable — see F-06) |
| F-07 | 🔴 Critical | Checkout inputs use placeholder text as the only label | 1.3.1, 3.3.2 | A | Manual (passes axe's label rule — placeholder is counted as the accessible name; see F-07) |
| F-08 | ⚪ Minor | Repeated non-descriptive link text ("Read more") | 2.4.4 | A | Manual only |
| F-09 | 🟡 Moderate | Icon-button touch targets below 24×24 CSS px | 2.5.8 | AA | Hybrid (axe WCAG 2.2 rule, off by default + manual measurement) |
| F-10 | ⚪ Minor | Page missing a declared language | 3.1.1 | A | Automated (axe: html-has-lang) |
5. Findings detail
F-01 🔴 Icon-only controls with no accessible name WCAG 1.1.1 Non-text Content (A) · 4.1.2 Name, Role, Value (A)
The pattern. The product grid's "add to cart" and header's cart/search/menu controls are
icon-only <button> elements with no visible text, no aria-label, and no accessible name
exposed to the accessibility tree. Representative pattern (illustrative markup, not scraped source):
<button class="icon-btn cart-add" onclick="addToCart(sku)">
<svg class="icon-cart-plus" aria-hidden="true">...</svg>
</button>
Why it matters. A screen-reader user tabbing through the product grid hears "button, button, button" with no way to tell which product each one adds, or that the icon in the header is a cart at all. This is not a cosmetic gap — it blocks the store's one core conversion action for anyone who cannot see the icon.
How to verify. Run axe-core (browser extension or CI plugin) against the page — rule ID
button-name (and aria-command-name for ARIA-role buttons) fires immediately, no manual step
required. Confirm manually: turn on a screen reader (VoiceOver/NVDA), tab to the control, and
listen to what gets announced.
Fix direction. Add a visible or aria-label accessible name that includes the product
name, e.g. aria-label="Add Millbrook Trail Jacket to cart". Do not rely on a tooltip alone —
tooltips are not exposed to assistive tech by default.
F-02 🟠 Insufficient text contrast WCAG 1.4.3 Contrast (Minimum) (AA)
The pattern. Body copy and secondary links use a light gray (#999999) on white
(#FFFFFF) — a contrast ratio of roughly 2.85:1, below the 4.5:1 minimum for normal-size text
(3:1 would be the bar only for large/bold text, which this isn't). Representative pattern
(illustrative markup, not scraped source):
.product-meta, .footer-links a { color: #999999; background: #ffffff; }
Why it matters. Low-vision users and anyone reading on a bright screen or in sunlight lose this text entirely. This is one of the single most common findings in accessibility scans generally — not because it is exotic, but because default gray design-system tokens are frequently picked for aesthetics without a contrast check.
How to verify. axe-core / WAVE both flag this automatically — rule ID
color-contrast — and both report the exact measured ratio against the exact threshold. No manual
judgment needed to detect it; manual judgment is only needed to confirm the "why" (is this large
text, is it decorative, etc).
Fix direction. Darken to at least #767676 on white (4.54:1) for normal text, or
increase size/weight to qualify for the 3:1 large-text threshold. Re-check with the same tool after
the change — this is the easiest class of fix to verify closes cleanly.
F-03 🟡 Information conveyed by color alone WCAG 1.4.1 Use of Color (A)
The pattern. Sale prices are shown only as red text with a strikethrough on the original price; there is no "Sale" text label, icon, or other non-color signal. Same pattern on the checkout form, where required fields are marked only with a red asterisk-colored label (color, no text like "required"). Representative pattern (illustrative markup, not scraped source):
<span class="price-original" style="text-decoration:line-through">$89.00</span>
<span class="price-sale" style="color:#d32f2f">$62.00</span>
Why it matters. A colorblind user (roughly 1 in 12 men, per WebAIM's published prevalence
estimate for color-vision deficiency) or a screen-reader user gets no signal that anything is on
sale, or that a field is required, until the form rejects their submission. This is a judgment-based
finding, not a parse-based one — the markup is technically valid HTML, so a scanner sees two
<span> elements with no error, not a missing-information problem.
How to verify. Not reliably automatable. Manual check: view the page in grayscale (browser DevTools → Rendering → Emulate vision deficiencies, or a grayscale filter) and confirm every meaningful distinction still reads without color.
Fix direction. Add a text or icon signal alongside color: a "Sale" badge, a "(required)" suffix on the label text itself (not just a red asterisk glyph).
F-04 🟠 Custom filter/sort control not operable by keyboard WCAG 2.1.1 Keyboard (A) · 4.1.2 Name, Role, Value (A)
The pattern. The category filter sidebar is built from <div> elements with
onclick handlers and no tabindex, role, or keyboard event handling (illustrative
markup, not scraped source):
<div class="filter-option" onclick="toggleFilter('waterproof')">Waterproof</div>
Why it matters. A mouse-only interaction pattern like this is invisible to a keyboard-only
user — Tab skips right over it, because a plain <div> is not in the focus order by default
and has no role announcing it as an interactive control even if it were reachable. There is no
visible error; the control simply does not exist for that user.
How to verify. Manual only — this is the class of defect a static-markup scanner is
structurally unable to catch, because "does this thing respond correctly to a keystroke" requires
actually pressing the key. Method: unplug the mouse (or just don't touch it) and Tab through the
entire page; anything you cannot reach or activate with Tab + Enter/Space is a finding.
Fix direction. Either use a real <button>/<input type="checkbox"> (free keyboard
support, free semantics), or if a custom widget is required, add tabindex="0",
role="checkbox" (or appropriate role) with aria-checked, and both keydown
(Enter/Space) and click handlers.
F-05 🔴 "Quick view" modal is a keyboard/focus trap WCAG 2.1.2 No Keyboard Trap (A) · 2.4.3 Focus Order (A)
The pattern. The product grid's "Quick View" modal opens on click, but (a) the trigger
itself is a <div> with no keyboard handler (compounding F-04's pattern), and (b) once opened by
mouse, focus is never programmatically moved into the modal, Escape does not close it, and
background page elements remain in the tab order behind the overlay.
Why it matters. A keyboard user who does manage to trigger the modal (e.g., via a screen reader's own activation method) can end up tabbing through background page content hidden behind a visible overlay, with no way to close it via keyboard — functionally stranded on the page. This is the single worst outcome in this snapshot because it can block the user from reaching checkout at all, not just make one feature harder.
How to verify. Manual only. Method: open the modal, then press Tab repeatedly and watch
where focus goes (does it stay inside the modal, or wander into hidden background content); press
Escape and confirm the modal closes and focus returns to the trigger element.
Fix direction. On open: move focus to the modal (typically its heading or first focusable
element) and constrain Tab/Shift+Tab to loop within it (a "focus trap" in the good
sense — trap focus inside intentionally, not accidentally). Bind Escape to close and return
focus to the trigger. Consider the native <dialog> element, which handles most of this
natively in current browsers.
F-06 🟡 No skip-navigation link WCAG 2.4.1 Bypass Blocks (A)
The pattern. Every page repeats the same header/nav/promo-banner block before reaching page-specific content, and there is no "Skip to main content" link as the first focusable element.
Why it matters. A keyboard or screen-reader user must tab through the same ~15–20 links on every single page load before reaching anything page-specific — a real, cumulative time cost that a sighted mouse user never pays.
How to verify. Manual: load any page fresh and press Tab once. The first stop should be
a (possibly visually hidden until focused) "Skip to main content" link. If the first stop is a logo
or nav item instead, this is a finding. Some automated tools offer a heuristic check for this
pattern but it is unreliable enough that we treat it as manual-only in this methodology.
Fix direction. Add a skip link as the very first focusable element in the DOM, targeting
the main content region (<a href="#main-content" class="skip-link">Skip to main
content</a>), visually hidden by default and shown on focus.
F-07 🔴 Checkout inputs use placeholder text as the only label WCAG 1.3.1 Info and Relationships (A) · 3.3.2 Labels or Instructions (A)
The pattern. The checkout form's shipping-address fields have no <label> element; the
field name appears only as placeholder text inside the input (illustrative markup, not scraped
source):
<input type="text" name="address1" placeholder="Street address" />
<input type="text" name="zip" placeholder="ZIP code" />
Why it matters. Placeholder text disappears the moment the user types, is not reliably announced by every screen reader the way a real label is, and is not programmatically associated with the field at all — a screen reader landing on this input may announce nothing more than "edit text." On the page where the user is about to enter a shipping address and payment details, this is the highest-stakes place in the whole site for a labeling gap to live.
How to verify. Not reliably automatable — and that is the trap. axe-core passes this
markup: under the HTML accessibility-API name computation, a non-empty placeholder is counted
toward the input's accessible name, so the label rule reports no violation (Deque's own rule
documentation calls placeholder-as-name "not a recommended solution" — it satisfies the letter of
the automated check while leaving every problem above in place). Verify manually: inspect each
input for an associated <label>, aria-label, or aria-labelledby; then start typing in
the field and watch the only visible field name disappear.
Fix direction. Add a real, visible <label for="address1">Street address</label> for
every field. Placeholder text can remain as a supplementary hint, never as the only label.
F-08 ⚪ Repeated non-descriptive link text WCAG 2.4.4 Link Purpose (In Context) (A)
The pattern. The blog/product-guide listing repeats "Read more" as the link text on every card, with no distinguishing accessible name (illustrative markup, not scraped source):
<a href="/guides/waterproofing">Read more</a>
<a href="/guides/layering">Read more</a>
Why it matters. A screen-reader user who pulls up a "list of links" for the page (a common navigation shortcut) sees "Read more, Read more, Read more" with no way to tell them apart out of context — even though each link is individually valid HTML.
How to verify. Manual/semantic judgment — axe-core's link-name rule catches empty
links (no text at all), but a link that has some text, just not distinguishing text, requires a
human reading the list of link names in context to notice the pattern.
Fix direction. Make the accessible name distinguishing without necessarily changing the
visible design: visually-hidden text inside the link (Read more <span class="sr-only">about
waterproofing your jacket</span>), or aria-label on the anchor.
F-09 🟡 Icon-button touch targets below minimum size WCAG 2.5.8 Target Size (Minimum) (AA)
The pattern. The size-selector swatches and modal close icon measure roughly 16×16 CSS pixels with no surrounding spacing, below the 24×24 CSS px minimum (with limited exceptions this pattern does not qualify for).
Why it matters. Users with limited fine motor control, or anyone on a touchscreen, frequently mis-tap adjacent controls — on a size-selector row this can silently select the wrong size.
How to verify. Hybrid: axe-core ships a target-size rule tagged WCAG 2.2 Level AA
(wcag22aa/wcag258), but it is disabled by default (enabled: false in the rule
definition) — it runs only if explicitly enabled or when running the wcag22aa tag set. Confirm
with a manual measurement in DevTools (inspect the rendered box size, including padding). axe rates
violations of this rule serious; we keep it Moderate in this snapshot — mis-taps are
recoverable, unlike the Critical task-blockers above (a deliberate, noted departure per §3).
Fix direction. Increase the tappable area to at least 24×24 CSS px (padding counts), or add adequate spacing between adjacent small targets so accidental-adjacent-tap misses don't trigger the wrong action.
F-10 ⚪ Missing page-language declaration WCAG 3.1.1 Language of Page (A)
The pattern. The document's <html> element has no lang attribute (illustrative
markup, not scraped source):
<html>
<head>...
Why it matters. Without a declared language, a screen reader falls back to its default voice/pronunciation rules regardless of the page's actual language, producing mispronounced or hard-to-understand speech output for every single page.
How to verify. axe-core / WAVE both flag this automatically and immediately — rule ID
html-has-lang — one of the simplest, cheapest-to-fix findings in this snapshot. (axe's own
default rating for this violation is serious; we rate it Minor here because on a
single-language English storefront the practical effect is degraded pronunciation rather than task
failure — a deliberate, noted departure per §3. The one-line fix is the same either way.)
Fix direction. <html lang="en"> (or the appropriate BCP 47 code). One-line fix, zero
design impact.
6. Fix roadmap
This week (Critical).
- Add accessible names to icon-only controls, starting with "add to cart" (F-01).
- Add real
<label>elements to every checkout input (F-07). - Fix the quick-view modal's focus handling and
Escape-to-close (F-05).
This sprint (Serious).
- Raise text/link contrast to the 4.5:1 minimum (F-02).
- Make the filter/sort sidebar keyboard-operable (F-04).
Ongoing (Moderate/Minor).
- Add non-color signals for sale price and required fields (F-03).
- Add a skip-navigation link (F-06).
- Differentiate repeated link text (F-08).
- Increase small touch targets to 24×24 CSS px (F-09).
- Declare the page language (F-10).
Retest. As with our security-audit work, one verification pass after fixes land confirms each item is actually closed — re-running the same automated rule and repeating the same manual walkthrough step described in each finding above, not just trusting that the code changed.
7. How to reproduce these checks on your own site (15 minutes, free)
This is deliberately not proprietary — anyone can run this today with no purchase:
- Install the axe DevTools browser extension (free tier) or use WAVE. Run it on your homepage, one listing/grid page, and your checkout/contact form.
- Unplug your mouse (or just don't touch it). Starting from a fresh page load, press
Tabrepeatedly. Note: (a) whether the first stop is a skip link, (b) whether every interactive-looking element on the page actually receives focus, (c) whether you can ever get stuck unable toTabfurther or close something. - Turn on your OS's built-in screen reader (VoiceOver on macOS:
Cmd+F5; Narrator on Windows:Ctrl+Win+Enter) for five minutes on your product/checkout page and just listen. - View the page with a grayscale filter (Chrome DevTools → Rendering tab → "Emulate vision deficiencies") and check whether anything meaningful is conveyed by color alone.
That sequence — automated scan, keyboard walkthrough, five minutes of screen reader, one grayscale pass — is most of the manual half of this methodology. It will not find everything a full review does (business-logic-aware findings like F-05's modal-trap or F-04's custom-widget gap take longer to spot systematically across a whole app), but it will surface a meaningful fraction of what's above in under an hour, for free. We say this openly because the honest version of this offer is "we do this more thoroughly and more consistently than you have time to," not "we have access to something you don't."
8. Scope, methodology & limitations
What this is. A static, source/markup-level accessibility findings snapshot, following the
same manual-primary / automated-supported methodology as our
Code Trust Audit security reviews, adapted with WCAG 2.2
success criteria in place of CVSS/OWASP/CWE, and axe-core's impact vocabulary
(minor/moderate/serious/critical) in place of a proprietary severity scale
(departures from axe's own per-rule defaults are noted inline — §3). "Findings" in this document's
title means technically verifiable observations — reproducible, dated, rule-level checks —
deliberately not "evidence", because nothing here is evidence in any legal sense.
What this is not:
- Not legal advice. Whether any gap here (or on a real site) creates legal exposure under the ADA, state law, or elsewhere depends on jurisdiction, the specific facts, and case law that changes over time. That determination requires a lawyer, not a code-review vendor, and we say so in every engagement.
- Not a compliance certification. No document — ours or anyone's — can certify that a website is "ADA compliant" or fully conforms to WCAG, because conformance is continuous (any future content change can reintroduce a gap) and because the legal standard for private-sector websites in the US is unsettled and enforced through case-by-case litigation and settlements rather than a single codified technical rule. (For contrast: DOJ's 2024 Title II rule does set a specific WCAG 2.1 AA technical standard, but only for state and local government websites, on a phased timeline — compliance deadlines were extended by one year by a DOJ interim final rule in April 2026. That rule does not apply to a private retailer like this specimen. Verified against ada.gov and the Federal Register IFR, 2026-07-14.)
- No litigation-protection claim, ever. We do not say, imply, or allow a client to believe that fixing these items "protects" them from a demand letter or lawsuit. The FTC's January 2025 settlement with accessiBe (finalized April 2025) required a $1,000,000 payment over claims that its automated widget could make any website WCAG-compliant and keep it compliant over time, plus deceptively formatted third-party reviews. If even the narrower "makes you compliant" claim is actionable when unsubstantiated, a "protects you from lawsuits" claim is a line we will never go near — under this brand or any other — and this document is written to make that mistake structurally hard to make.
- Not a scan of a real live system. Nothing here was scraped, scanned, or otherwise obtained from any real company's site. Every markup snippet is written for this document to illustrate a common, well-documented pattern.
- Not a claim about litigation frequency, industry statistics, or third-party endorsement. Any such figures, if added later, must be sourced and dated, not asserted from memory.
Confidentiality note. This entire document concerns a fictional specimen. A real client engagement is confidential, exactly like our security-audit work — this document does not change that policy, it just doesn't implicate it, since there is no real client here.
9. Is this a service you can buy?
Not as a separately priced product — deliberately. Our existing Code Trust Audit tiers already describe a scope/turnaround structure that an ADA/WCAG snapshot could slot into as an added chapter or a parallel spot-check-style review, but we have not set a standalone price for this deliverable, because we won't package something before we've seen real demand for its exact shape. If this is something your team wants, tell us what you'd need — that signal is what turns this from a sample into a service.