Demo change log

One entry per issue: 30 issues from a mock review of our fictional demo store. It’s the format you get on every job, using your own issue IDs.

Demo store, fictional No client, no real audit. Built to show how we work.

How to read “Verified”

A
axe-core scan, WCAG 2.0, 2.1 and 2.2 A and AA plus best-practice rules, desktop and mobile
R
A scripted retest of this exact issue, by keyboard input and accessibility-tree checks
K#
Step # of the keyboard-only shopping task
SR#
Step # of the virtual screen reader transcript (not VoiceOver)
L
Lighthouse accessibility audit

Every entry starts as “Fixed, pending partner retest”. Your team’s retest decides whether each item passes, and only items that pass are billed.

CHANGELOG.mdDemo store, fictional

The change log: one row per issue ID

Kettlecrest Outfitters, 30 issues, KC-001 to KC-030, target WCAG 2.2 Level AA. Every entry: fixed, pending partner retest.

Every issue in the demo change log: severity, WCAG 2.2 criteria and how it was found
IDIssueSeverityWCAG 2.2 SCFound by
KC-001Page language not setMedium3.1.1Automated (axe)
KC-002Icon-only controls with no name (header, social, pagination)Critical4.1.2, 2.1.1, 2.4.4Automated (axe) + Manual (keyboard)
KC-003Images missing alt or using file namesHigh1.1.1Automated (axe) + Manual (screen reader)
KC-004Zoom disabledHigh1.4.4Automated (axe)
KC-005Low-contrast theme textHigh1.4.3Automated (axe)
KC-006White hero text on light artworkMedium1.4.3Manual (visual); axe reports "needs review" for text over images
KC-007Focus indicator removedCritical2.4.7Manual (keyboard)
KC-008Quick-add buttons unnamed and invisible on focusCritical4.1.2, 2.4.7Automated (axe) + Manual (keyboard)
KC-009Color swatches not keyboard operable, state not exposedCritical2.1.1, 4.1.2, 1.4.1, 1.4.11Manual (keyboard + screen reader)
KC-010Mega menu opens on hover onlyHigh2.1.1, 1.4.13Manual (keyboard)
KC-011Hidden slides stay in the tab orderMedium2.4.3, 2.4.7Manual (keyboard)
KC-012Auto-rotating carousel with no pause; controls not operableHigh2.2.2, 2.1.1, 4.1.2Manual (keyboard + visual)
KC-013Search overlay: no focus management, placeholder labelHigh2.1.1, 2.4.3, 3.3.2, 4.1.2Manual (keyboard + screen reader)
KC-014Newsletter popup traps nobody and lets nobody outCritical2.1.1, 2.4.3, 4.1.2, 3.3.2Manual (keyboard + screen reader)
KC-015Add to cart is silentHigh4.1.3Manual (screen reader)
KC-016Accordion headings are clickable divsHigh2.1.1, 4.1.2Manual (keyboard)
KC-017Collection filters are divs; results change silentlyHigh2.1.1, 4.1.2, 1.4.1, 4.1.3Manual (keyboard + screen reader)
KC-018Size selector is divs with no group labelCritical2.1.1, 1.3.1, 4.1.2Manual (keyboard + screen reader)
KC-019No skip link, no landmarksMedium2.4.1, 1.3.1Automated (axe, best practice) + Manual
KC-020Footer newsletter: placeholder label, unnamed button, silent errorHigh3.3.2, 4.1.2, 3.3.1Automated (axe) + Manual (screen reader)
KC-021Star ratings read as charactersMedium1.1.1, 1.3.1Manual (screen reader)
KC-022Cart drawer is not a dialogCritical2.1.1, 2.4.3, 4.1.2Manual (keyboard + screen reader)
KC-023Missing h1, skipped heading levelsMedium1.3.1, 2.4.6Automated (axe, best practice) + Manual
KC-024Quantity fields unlabeled; -/+ not operableHigh4.1.2, 1.3.1, 2.1.1Automated (axe) + Manual (keyboard)
KC-025"Please select a size" shown visually onlyHigh3.3.1, 4.1.3Manual (screen reader)
KC-026Reviews app: write-a-review form (third-party)High2.1.1, 3.3.2, 3.3.1, 1.4.1, 4.1.2Manual (keyboard + screen reader)
KC-027Reviews app low-contrast text (third-party)Medium1.4.3Automated (axe)
KC-028"Click here" linksLow2.4.4Manual (screen reader)
KC-029Sort select has no labelHigh4.1.2, 1.3.1Automated (axe)
KC-030Gallery thumbnails are divs; main image alt is a file nameHigh1.1.1, 2.1.1Automated (axe) + Manual (keyboard)

Every entry in full

KC-001, Page language not set
Issue
Page language is not set. Screen readers may read the page with the wrong voice and pronunciation.
WCAG 2.2
3.1.1 Language of Page (A)
Severity
Medium
Where
All pages: Document
Found by
Automated (axe)
Files
after/index.html, after/collection.html, after/product.html [layout/theme.liquid]
Change
<html> → <html lang="en">. On a real Shopify theme: lang="{{ request.locale.iso_code }}".
Verified
A (html-has-lang 6 → 0 elements), R (lang="en"), L.
Your retest
Inspect <html> on any page.
Status
Fixed, pending partner retest
KC-002, Icon-only controls with no name (header, social, pagination)
Issue
Icon-only controls have no accessible name. Search and cart are a <span>/<div> (not focusable at all); the menu toggle is a <div>; account, social and “next page” links contain only an SVG.
WCAG 2.2
4.1.2 Name, Role, Value; 2.1.1 Keyboard; 2.4.4 Link Purpose (In Context) (A)
Severity
Critical
Where
All pages; Collection: Header icons, footer social links, pagination
Found by
Automated (axe) + Manual (keyboard)
Files
header, footer and pagination markup in all three pages; after/assets/theme.js (search, cart and menu handlers now bound to buttons)
Change
Search, cart and menu <span>/<div> → <button type="button">. Visually hidden names: “Search”, “Cart, N items” (count stays live in the name), “Menu”, “Log in”, “Kettlecrest on Instagram/YouTube/Pinterest”, “Next page” and “Page 2/3”. Decorative SVGs get aria-hidden="true" focusable="false". Menu button carries aria-expanded + aria-controls.
Verified
A (link-name 41 → 0 elements), R (all named controls found by role + name), K4 (the Tab path now includes button "Search" and button "Cart, 0 items").
Your retest
Tab through the header; screen reader announces “Search, button”, “Cart, 0 items, button”, “Log in, link”.
Status
Fixed, pending partner retest
KC-003, Images missing alt or using file names
Issue
Images have no alt attribute or use the file name as alt (logo, some product cards, hero, promo, popup, mega-menu feature, payment icons).
WCAG 2.2
1.1.1 Non-text Content (A)
Severity
High
Where
All pages: Logo and images
Found by
Automated (axe) + Manual (screen reader)
Files
all pages (logo, cards, hero, promo, popup, mega-menu feature, payment icons); after/assets/theme.js (cart line images)
Change
Logo alt="Kettlecrest Outfitters". Decorative/redundant images alt="": hero art, promo art, popup art, card images (the product name sits in the same card), cart line images. Payment icons: “Credit and debit cards”, “Digital wallets”. File-name alts removed. On Shopify: fix in the image snippet (image_tag with alt: product.title or alt: ''), not image by image.
Verified
A (image-alt 48 → 0), R (no missing or file-name alts), SR2 ("image, Ridgeline 40L Pack in Forest, front view").
Your retest
List images with a screen reader or inspect alt.
Status
Fixed, pending partner retest
KC-004, Zoom disabled
Issue
Pinch zoom is disabled (maximum-scale=1, user-scalable=no).
WCAG 2.2
1.4.4 Resize Text (AA)
Severity
High
Where
All pages: Viewport meta
Found by
Automated (axe)
Files
all pages [layout/theme.liquid]
Change
width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no → width=device-width, initial-scale=1.
Verified
A (meta-viewport 6 → 0), R, L.
Your retest
Pinch-zoom on a phone.
Status
Fixed, pending partner retest
KC-005, Low-contrast theme text
Issue
Text below 4.5:1 contrast: announcement bar (white on sage, about 2.6:1), vendor labels, compare-at prices, muted copy, sale badge, sale price, breadcrumbs, footer links and copyright.
WCAG 2.2
1.4.3 Contrast (Minimum) (AA)
Severity
High
Where
All pages: Theme typography and badges
Found by
Automated (axe)
Files
after/assets/theme.css
Change
Fixed at the token level, not per element: --muted/--vendor #9b9b9b/#a8a8a8 → #636363; announcement --sage #8fa58f → #4a6350; sale badge #e0876a → #a8432a; sale price ember → #a8432a; compare-at #b5b5b5 → #636363; footer links/copy #7d857f/#6f7871 → #c4ccc6/#b8c0ba; placeholders darkened; link hover color #c4572a → #a8432a. Look and palette unchanged.
Verified
A (color-contrast 0 elements after on every scan, incl. hover state of the mega menu), R.
Your retest
Contrast checker on the listed selectors.
Status
Fixed, pending partner retest
KC-006, White hero text on light artwork
Issue
White slide text sits directly on light artwork (peach sky). Measured contrast behind the eyebrow text is below 4.5:1.
WCAG 2.2
1.4.3 Contrast (Minimum) (AA)
Severity
Medium
Where
Home: Hero carousel
Found by
Manual (visual); axe reports "needs review" for text over images
Files
after/assets/theme.css (.slide::after, .slide-content)
Change
Added a dark gradient overlay behind the slide text (left-to-right on desktop, bottom-up on mobile). On Shopify this is usually the slideshow section’s “overlay opacity” setting; we set it in CSS here.
Verified
R: the check hides the text, screenshots the exact text boxes on all three slides and measures white against the brightest background pixel. Worst case after: 7.2:1 for the 13px eyebrow (was 1.4:1). axe can only mark text over images as "needs review", so this one is measured directly.
Your retest
Pause the carousel on slide 1 and sample the sky behind “FALL 2026”.
Status
Fixed, pending partner retest
KC-007, Focus indicator removed
Issue
Focus indicator removed everywhere (*:focus { outline: none }) with no replacement. Keyboard users cannot see where they are.
WCAG 2.2
2.4.7 Focus Visible (AA)
Severity
Critical
Where
All pages: Global CSS
Found by
Manual (keyboard)
Files
after/assets/theme.css
Change
Deleted *:focus { outline: none } and the element list after it. Added a two-tone :focus-visible ring (3px #1d4ed8 outline, 2px offset, 5px white inner ring) that keeps at least 3:1 against light and dark sections; footer and demo banner use a light ring. Custom controls (swatches, sizes, stars) draw the ring on their label.
Verified
R (8 of 8 first tab stops show a visible style change), K12 (focus visible on every control used in the task).
Your retest
Tab through each page.
Status
Fixed, pending partner retest
KC-008, Quick-add buttons unnamed and invisible on focus
Issue
Quick-add buttons have no accessible name, and stay invisible (opacity: 0) until mouse hover, including when focused.
WCAG 2.2
4.1.2 Name, Role, Value; 2.4.7 Focus Visible (A, AA)
Severity
Critical
Where
Home; Collection: Product card quick-add
Found by
Automated (axe) + Manual (keyboard)
Files
product cards on home and collection [snippets/card-product.liquid]; after/assets/theme.css
Change
Visually hidden name per product (“Quick add Ridgeline 40L Pack to cart”); type="button"; SVG hidden. .card:focus-within .quick-add, .quick-add:focus-visible { opacity: 1 }. Button moved after the product title in source order so Tab reads the name before the action (still positioned top-right). The duplicate image link in each card is removed from the tab order (tabindex="-1" aria-hidden="true"), halving tab stops in the grid.
Verified
A (button-name 30 → 0), R (4/4 named; opacity 1 when focused).
Your retest
Tab through a product grid.
Status
Fixed, pending partner retest
KC-009, Color swatches not keyboard operable, state not exposed
Issue
Color swatches are clickable <div>s: not focusable, no role or name, and the selected swatch is shown only by a faint ring color change that is not exposed to assistive tech.
WCAG 2.2
2.1.1 Keyboard; 4.1.2 Name, Role, Value; 1.4.1 Use of Color; 1.4.11 Non-text Contrast (A, AA)
Severity
Critical
Where
Product: Color swatches
Found by
Manual (keyboard + screen reader)
Files
after/product.html (color options), after/assets/theme.css, after/assets/theme.js
Change
<div class="swatch"> ×3 → <fieldset><legend>Color</legend> with <input type="radio" name="color"> + <label> per color (input visually hidden, label keeps the round swatch, color name as visually hidden text). Checked state: thick dark ring + white checkmark (not color alone). JS listens to change instead of click, so arrow keys work natively. Image alt updates with the color.
Verified
R (Arrow Right selects Slate; checkmark present), K5 (Tab reaches the group, Right Arrow selects Slate), SR2 ("group, Color", "radio, Forest, checked, position 1, set size 3"), SR3.
Your retest
Tab to Color, use arrow keys; VoiceOver: “Slate, selected, radio button, 2 of 3”.
Status
Fixed, pending partner retest
KC-010, Mega menu opens on hover only
Issue
The “Shop” mega menu opens only on mouse hover (CSS :hover). Keyboard and touch users cannot reach its 12 links; hover content cannot be dismissed with Escape.
WCAG 2.2
2.1.1 Keyboard; 1.4.13 Content on Hover or Focus (A, AA)
Severity
High
Where
All pages: Main navigation mega menu
Found by
Manual (keyboard)
Files
header markup (all pages), after/assets/theme.css, after/assets/theme.js
Change
WAI-ARIA APG disclosure navigation. “Shop” is now <button aria-expanded aria-controls="mega-shop">; Enter/Space toggles; Escape closes and returns focus to the button; focus leaving the item closes it. Mouse hover still opens it (with a 150 ms close delay so the pointer can travel), and Escape dismisses hover-opened content too. The former “Shop” link destination is the first item in the panel (“Shop all gear”). Nav is a labelled <nav> list.
Verified
R (Enter opens with aria-expanded=true, Tab enters submenu, Escape closes and returns focus).
Your retest
Tab to Shop, Enter, Tab through the 14 links, Escape.
Status
Fixed, pending partner retest
KC-011, Hidden slides stay in the tab order
Issue
Hidden slides are only faded out (opacity: 0), so their “Shop” links stay in the tab order and focus lands on invisible links.
WCAG 2.2
2.4.3 Focus Order; 2.4.7 Focus Visible (A, AA)
Severity
Medium
Where
Home: Hero carousel slides
Found by
Manual (keyboard)
Files
after/assets/theme.css
Change
Inactive slides get visibility: hidden with a delayed transition, so the cross-fade looks identical but hidden slides leave the tab order and the accessibility tree.
Verified
R (0 links in hidden slides reachable).
Your retest
Tab into the hero: only the visible slide’s link is reached.
Status
Fixed, pending partner retest
KC-012, Auto-rotating carousel with no pause; controls not operable
Issue
The carousel auto-rotates every 5 seconds with no pause/stop control. Previous/next arrows and dots are <span>/<div>s with no name and no keyboard access.
WCAG 2.2
2.2.2 Pause, Stop, Hide; 2.1.1 Keyboard; 4.1.2 Name, Role, Value (A)
Severity
High
Where
Home: Hero carousel controls
Found by
Manual (keyboard + visual)
Files
after/index.html (hero), after/assets/theme.css, after/assets/theme.js
Change
APG auto-rotating carousel: section with aria-roledescription="carousel" and label; slides are role="group" aria-roledescription="slide" aria-label="1 of 3"; visible pause/play button first among the controls (“Stop/Start automatic slide show”); prev/next and dots are real buttons with names and aria-current; rotation pauses on hover and stops when keyboard focus enters; aria-live is off while rotating and polite when stopped; no autoplay under prefers-reduced-motion. Controls stay visible on mobile; dots now have 24×24 px targets.
Verified
R (pause stops rotation over 5.6 s; prev/next named). During testing this check caught a bug in our first version (a mouse click on "Stop" was undone by the focus handler); fixed before sign-off.
Your retest
Press the pause button and wait; Tab into the carousel and confirm it stops.
Status
Fixed, pending partner retest
KC-013, Search overlay: no focus management, placeholder label
Issue
Search opens as an overlay without moving focus into it. The input’s only label is placeholder text; the close “×” is a <span>; Escape does not close it.
WCAG 2.2
2.1.1 Keyboard; 2.4.3 Focus Order; 3.3.2 Labels or Instructions; 4.1.2 Name, Role, Value (A)
Severity
High
Where
All pages: Search overlay
Found by
Manual (keyboard + screen reader)
Files
search markup (all pages), after/assets/theme.css, after/assets/theme.js
Change
Overlay → native <dialog aria-label="Search"> opened with showModal() (page behind becomes inert); <form role="search"> with a label for the input; close is a named button; Escape closes; focus returns to the Search button.
Verified
R (dialog opens, focus in labelled search box, Escape returns focus).
Your retest
Enter on Search, type, Escape.
Status
Fixed, pending partner retest
KC-014, Newsletter popup traps nobody and lets nobody out
Issue
The first-visit popup is not a dialog: focus stays behind it, Tab moves through the page underneath, Escape does nothing, and the close “×” and “No thanks” are not focusable. Keyboard users cannot dismiss it.
WCAG 2.2
2.1.1 Keyboard; 2.4.3 Focus Order; 4.1.2 Name, Role, Value; 3.3.2 Labels or Instructions (A)
Severity
Critical
Where
All pages (first visit): Newsletter popup (app)
Found by
Manual (keyboard + screen reader)
Files
popup markup (all pages), after/assets/theme.css, after/assets/theme.js
Change
Native modal <dialog aria-labelledby="popup-title">; title is an <h2>; close and “No thanks” are buttons; Escape closes; email has a visible label, autocomplete="email" and an associated error (aria-describedby, aria-invalid); success state receives focus and no longer auto-closes after 1.5 s. The popup does not open if another dialog is already open. Business behavior (first visit, 1 s delay) unchanged. Note for the partner: if the popup comes from an app, this lands as a theme override or a vendor ticket; flagged at quote time.
Verified
R (dialog role + name, focus inside, labelled field, Escape closes), K1–K3.
Your retest
Private window, wait for the popup, Tab and Escape.
Status
Fixed, pending partner retest
KC-015, Add to cart is silent
Issue
Adding to cart updates the badge and opens the drawer silently. Screen reader users get no confirmation that anything happened.
WCAG 2.2
4.1.3 Status Messages (AA)
Severity
High
Where
Product; Home; Collection: Add to cart feedback
Found by
Manual (screen reader)
Files
cart drawer markup (all pages), after/assets/theme.js
Change
After an add, focus moves to a visible confirmation inside the cart dialog (“Added to your cart: Ridgeline 40L Pack, Slate / L. Cart has 1 item.”), which is also the dialog’s aria-describedby. Later cart edits (quantity, remove) are announced through a polite role="status" region inside the dialog. Same behavior for quick-add.
Verified
R (focus + dialog description contain the confirmation), K9, SR5 ("dialog, Your cart, Added to your cart: Ridgeline 40L Pack, Slate / L. Cart has 1 item.").
Your retest
With VoiceOver, add to cart and listen.
Status
Fixed, pending partner retest
KC-016, Accordion headings are clickable divs
Issue
Accordion headings (Details, Shipping & returns, Lifetime repairs) are clickable <div>s: not focusable and no expanded/collapsed state.
WCAG 2.2
2.1.1 Keyboard; 4.1.2 Name, Role, Value (A)
Severity
High
Where
Product: Accordion
Found by
Manual (keyboard)
Files
after/product.html, after/assets/theme.css (and the accordion JS removed from theme.js)
Change
<div class="accordion-item"> → native <details>/<summary>; same look (marker hidden, chevron rotates on [open]). Less JavaScript than before.
Verified
R (Enter on "Shipping & returns" expands it).
Your retest
Tab to each heading, Enter/Space.
Status
Fixed, pending partner retest
KC-017, Collection filters are divs; results change silently
Issue
Filter options are <div>s styled as checkboxes: not focusable, checked state is a color fill only and not exposed; the result count changes silently; “Clear all” is a <span>.
WCAG 2.2
2.1.1 Keyboard; 4.1.2 Name, Role, Value; 1.4.1 Use of Color; 4.1.3 Status Messages (A, AA)
Severity
High
Where
Collection: Filters
Found by
Manual (keyboard + screen reader)
Files
after/collection.html, after/assets/theme.css, after/assets/theme.js
Change
Native checkboxes in <fieldset><legend>Category</legend> (accent-color keeps the brand color; the native checkmark is the non-color indicator); “Clear all filters” button; results count in role="status" so “4 products” is announced; hidden headings “Filters” and “Products” for navigation.
Verified
R (Space checks "Camp", status reads "4 products", clear button present).
Your retest
Tab to Category, Space, listen for the count.
Status
Fixed, pending partner retest
KC-018, Size selector is divs with no group label
Issue
Sizes are <div>s with no group label; not focusable; selected and sold-out states are not exposed (sold out is light gray strike-through only).
WCAG 2.2
2.1.1 Keyboard; 1.3.1 Info and Relationships; 4.1.2 Name, Role, Value (A)
Severity
Critical
Where
Product: Size selector
Found by
Manual (keyboard + screen reader)
Files
after/product.html, after/assets/theme.css, after/assets/theme.js
Change
<fieldset><legend>Size</legend> with a radio per size; XL is disabled with “(sold out)” in its name (strike-through kept visually). Checked style unchanged (dark fill). The fieldset references the add-to-cart error (see KC-025).
Verified
R (arrow keys select L; XL disabled + "sold out"), K6, SR2 ("radio, XL (sold out), not checked, disabled, position 4, set size 4"), SR4.
Your retest
Tab to Size, arrows.
Status
Fixed, pending partner retest
KC-019, No skip link, no landmarks
Issue
No skip link and no landmarks: header, navigation, main content and footer are all <div>s.
WCAG 2.2
2.4.1 Bypass Blocks; 1.3.1 Info and Relationships (A)
Severity
Medium
Where
All pages: Page structure
Found by
Automated (axe, best practice) + Manual
Files
all pages, after/assets/theme.css
Change
“Skip to content” link (first tab stop, visible on focus) → <main id="main" tabindex="-1">. <header>, <nav aria-label="Main">, <main>, <footer> with labelled footer navs; announcement bar is a labelled region; the demo label is an <aside aria-label="Demo notice">; breadcrumbs are <nav aria-label="Breadcrumb"> with aria-current="page".
Verified
A (region 252 → 0 and landmark-one-main 6 → 0), R (first Tab = skip link, Enter moves focus to main; landmarks present).
Your retest
Tab once, Enter; open the screen reader landmark list.
Status
Fixed, pending partner retest
KC-020, Footer newsletter: placeholder label, unnamed button, silent error
Issue
Email field uses placeholder as its only label; the submit button is an arrow icon with no name; the error message is not associated with the field or announced and is red text only.
WCAG 2.2
3.3.2 Labels or Instructions; 4.1.2 Name, Role, Value; 3.3.1 Error Identification (A)
Severity
High
Where
All pages: Footer newsletter form
Found by
Automated (axe) + Manual (screen reader)
Files
footer markup (all pages), after/assets/theme.css, after/assets/theme.js
Change
Visible “Email address” label, autocomplete="email"; arrow button named “Subscribe”; error text is specific (“Enter an email address in the format name@example.com.”), has a warning icon, is linked by aria-describedby, field gets aria-invalid="true" and focus returns to it; success message in role="status". Error color lightened for the dark footer (#ff9b85).
Verified
A (button-name on the form → 0), R (invalid submit sets aria-invalid, error associated, focus on field).
Your retest
Submit “abc” with a screen reader.
Status
Fixed, pending partner retest
KC-021, Star ratings read as characters
Issue
Ratings are “★★★★☆” characters with no text alternative; screen readers read “black star, black star...” or nothing useful.
WCAG 2.2
1.1.1 Non-text Content; 1.3.1 Info and Relationships (A)
Severity
Medium
Where
Home; Collection; Product: Star ratings
Found by
Manual (screen reader)
Files
cards (home, collection), after/product.html (rating line and reviews)
Change
Star glyphs wrapped in aria-hidden="true"; visually hidden text “Rated 4.6 out of 5,” and “(128 reviews)”. Reviews summary and breakdown get a text equivalent and a labelled list.
Verified
R (8/8 card ratings), SR2 ("Rated 4.6 out of 5." instead of "★★★★★").
Your retest
Read a product card with a screen reader.
Status
Fixed, pending partner retest
KC-022, Cart drawer is not a dialog
Issue
The cart drawer is not a dialog: opening it leaves focus on the page behind, Escape does nothing, the close “×” is a <span>, focus is not returned, and when closed it is only moved off-screen so its links stay in the tab order.
WCAG 2.2
2.1.1 Keyboard; 2.4.3 Focus Order; 4.1.2 Name, Role, Value (A)
Severity
Critical
Where
All pages: Cart drawer
Found by
Manual (keyboard + screen reader)
Files
cart drawer markup (all pages), after/assets/theme.css, after/assets/theme.js
Change
Off-canvas <div> → native modal <dialog aria-labelledby="cart-title"> (slide-in animation kept, disabled under reduced motion); page behind is inert while open; close and remove are named buttons (“Close cart”, “Remove Ridgeline 40L Pack”); cart quantity fields labelled; Escape closes; focus returns to whatever opened it (Add to cart, quick-add or the cart button); after removing an item focus goes to the cart heading. Closed drawer is display: none, so its links leave the tab order.
Verified
R (closed drawer out of tab order; dialog "Your cart"; focus inside; Escape returns focus to the cart button), K8, K10, K11, SR5, SR6 ("button, Add to cart" after Escape).
Your retest
Add to cart, Tab around inside the drawer, Escape.
Status
Fixed, pending partner retest
KC-023, Missing h1, skipped heading levels
Issue
No <h1> on any page; heading levels skip (h3 then h5, h6 in the footer and reviews); the product name, hero titles and popup title are styled <div>s.
WCAG 2.2
1.3.1 Info and Relationships; 2.4.6 Headings and Labels (A, AA)
Severity
Medium
Where
All pages: Headings
Found by
Automated (axe, best practice) + Manual
Files
all pages, after/assets/theme.css (keeps the original typography on the new heading elements)
Change
One <h1> per page: logo on home (Dawn-style), “Shop all gear” on the collection, product name on the product page. Hero, section, popup, cart, footer and mega-menu titles → <h2>; card, value-prop and review titles → <h3>. Visual sizes unchanged.
Verified
A (heading-order 8 → 0, page-has-heading-one 6 → 0), R (1×h1 and no skipped levels on each page), SR1 (H key now lands on "heading, Ridgeline 40L Pack, level 1").
Your retest
Headings list on each page.
Status
Fixed, pending partner retest
KC-024, Quantity fields unlabeled; -/+ not operable
Issue
Quantity inputs have no label; the - and + controls are <span>s (not focusable, no names).
WCAG 2.2
4.1.2 Name, Role, Value; 1.3.1 Info and Relationships; 2.1.1 Keyboard (A)
Severity
High
Where
Product; Cart drawer: Quantity selector
Found by
Automated (axe) + Manual (keyboard)
Files
after/product.html, after/assets/theme.js (cart lines), after/assets/theme.css
Change
Visible “Quantity” label; -/+ are buttons named “Decrease quantity” / “Increase quantity”; each cart line quantity has its own label.
Verified
A (label 6 → 0), R, SR2 ("spinbutton, Quantity, 1").
Your retest
Tab through the buy box.
Status
Fixed, pending partner retest
KC-025, "Please select a size" shown visually only
Issue
“Please select a size” appears visually only: not announced and not associated with the size group.
WCAG 2.2
3.3.1 Error Identification; 4.1.3 Status Messages (A, AA)
Severity
High
Where
Product: Add to cart validation
Found by
Manual (screen reader)
Files
after/product.html, after/assets/theme.js
Change
Error region is role="alert" (announced when filled) and is referenced by the size fieldset’s aria-describedby; message says what to do: “Select a size to add this pack to your cart.”
Verified
R (alert role; linked to size group).
Your retest
Press Add to cart with no size, screen reader on.
Status
Fixed, pending partner retest
KC-026, Reviews app: write-a-review form (third-party)
Issue
“Write a review” is a <div>; the star rating input is <span>s; fields use placeholder as label; errors are not associated or announced and invalid fields are marked by a red border only.
WCAG 2.2
2.1.1 Keyboard; 3.3.2 Labels or Instructions; 3.3.1 Error Identification; 1.4.1 Use of Color; 4.1.2 Name, Role, Value (A)
Severity
High
Where
Product: Reviews app: write-a-review form (third-party)
Found by
Manual (keyboard + screen reader)
Files
reviews markup in after/product.html, after/assets/theme.css, after/assets/theme.js
Change
“Write a review” → button with aria-expanded/aria-controls; star input → radio group “Rating (optional)” with “1 star”…“5 stars”; visible labels for Name, Email, Review title, Review; errors linked with aria-describedby, aria-invalid, warning icon + thicker border (not color alone); first invalid field receives focus; thank-you message is focused. Review list is a list of review items with <h3> titles and <time>. Third-party note: on a real store this is app markup. We fix it through the app’s template override when it offers one; otherwise we document it and send the vendor a ticket. This is agreed at quote time, not discovered at the end.
Verified
A, R (aria-expanded; 4/4 labelled fields; 5 rating radios; empty submit focuses first invalid field).
Your retest
Tab to the reviews, open the form, submit empty.
Status
Fixed, pending partner retest
KC-027, Reviews app low-contrast text (third-party)
Issue
Review metadata and helper text are very low contrast (#aaa, #bbb, #ccc, #9ccc65 on white).
WCAG 2.2
1.4.3 Contrast (Minimum) (AA)
Severity
Medium
Where
Product: Reviews app styling (third-party)
Found by
Automated (axe)
Files
after/assets/theme.css (overrides scoped to .tp-*)
Change
#aaa/#bbb/#ccc/#777/#9ccc65 → #595959/#4f4f4f/#2e6b30; “Powered by” line 11px → 12px.
Verified
A, R (0 review-widget nodes below 4.5:1).
Your retest
Contrast checker on the review list.
Status
Fixed, pending partner retest
KC-028, "Click here" links
Issue
Ambiguous link text: “Click here” (announcement bar, promo, size guide, shipping policy) and “Learn more” / “View all” without context.
WCAG 2.2
2.4.4 Link Purpose (In Context) (A)
Severity
Low
Where
Home; Product: Link text
Found by
Manual (screen reader)
Files
after/index.html, after/product.html, announcement bar on all pages
Change
“Click here” ×4 → “Shipping and returns details”, “Read the pack size guide”, “See the Ridgeline size guide”, “Read the full shipping and returns policy”; “Learn more” → “Learn more about lifetime repairs”; “View all” → “View all best sellers”.
Verified
R (no ambiguous link text on home or product).
Your retest
Screen reader links list.
Status
Fixed, pending partner retest
KC-029, Sort select has no label
Issue
The sort <select> has no label; “Sort by” is only the first option.
WCAG 2.2
4.1.2 Name, Role, Value; 1.3.1 Info and Relationships (A)
Severity
High
Where
Collection: Sort select
Found by
Automated (axe)
Files
after/collection.html, after/assets/theme.css
Change
<label for="sort-by">Sort by</label> beside the select; the “Sort by” placeholder option removed (Featured is the default).
Verified
A (select-name 2 → 0), R.
Your retest
Tab to the select.
Status
Fixed, pending partner retest
KC-030, Gallery thumbnails are divs; main image alt is a file name
Issue
Gallery thumbnails are clickable <div>s (not keyboard operable) whose images have no alt; the main image’s alt is its file name and does not change with color.
WCAG 2.2
1.1.1 Non-text Content; 2.1.1 Keyboard (A)
Severity
High
Where
Product: Image gallery
Found by
Automated (axe) + Manual (keyboard)
Files
after/product.html, after/assets/theme.js, after/assets/theme.css
Change
Thumbnails → buttons whose images have alt “Front view” / “Side view” / “Back view”, active one marked aria-current="true"; main image alt is generated from product, color and view (“Ridgeline 40L Pack in Slate, side view”) and updates with each change.
Verified
A (image-alt on gallery → 0), R (after choosing Slate + side view the alt reads "Ridgeline 40L Pack in Slate, side view"), SR2.
Your retest
Tab to the thumbnails, change color, inspect the main image.
Status
Fixed, pending partner retest

Get this for one of your audits

Send us one client’s audit findings. We quote a fixed price for an agreed list of fixes, and you get a change log like this one.