Accessibility audit report: Harbor & Pine Goods
Important: this report is testing and remediation guidance, not legal advice or a compliance guarantee. It describes what we found on the pages listed below on the dates listed above. Sites change, and pages outside the scope were not tested. For legal questions, including any demand letter or lawsuit, speak to a lawyer.
1. Summary
- Pages tested: 5, plus the header, menu, footer and pop-ups on every page (listed in section 2)
- Problems found: 8 (1 blocker, 3 serious, 4 moderate, 0 minor)
The three to fix first:
- The size and color pickers on the product page have no name, so screen reader users can't tell which option they're choosing (finding 1).
- Nothing is announced when a customer presses Add to cart, so screen reader users don't know it worked (finding 2).
- The cart button in the header has no name, so screen reader users hear "link" and nothing else (finding 3).
What already works well: every page has a clear, unique title; the Add to cart and Check out buttons are real buttons with clear names; body text contrast is good; pages reflow at 320 px wide without sideways scrolling; and the checkout entry form fields all have visible labels.
2. Scope
| Page | URL tested | Desktop | Mobile |
|---|---|---|---|
| Home | harborandpine.example/ | Tested | Tested |
| Collection | harborandpine.example/collections/kitchen | Tested | Tested |
| Product | harborandpine.example/products/sage-stoneware-mug | Tested | Tested |
| Cart | harborandpine.example/cart | Tested | Tested |
| Checkout entry (up to the payment step; no order placed) | Reached from the cart's Check out button | Tested | Tested |
Standard used as the yardstick: WCAG 2.2, levels A and AA.
Also tested on every page: the header, main menu and mobile menu drawer, footer, and any pop-up (newsletter or cookie banner).
Not tested: pages outside the table, content behind a login, the payment step itself, emails, PDFs, third-party sites the store links to, and native apps.
3. How we tested
- Automated scan with axe-core at desktop (1280 px) and mobile (390 px) widths. Every automated result was checked by hand; false positives were removed.
- Keyboard only: every control reachable, visible focus, logical order, no traps, menus and pop-ups usable and closable.
- Screen readers: VoiceOver (Safari, macOS and iOS) and NVDA (Firefox, Windows). Names, roles and states of controls; headings; image text; form labels and errors; live updates such as "added to cart".
- Visual: color contrast of text, prices and buttons; zoom to 200% and reflow at 320 px; motion and auto-playing content.
4. Priority levels
| Level | Meaning |
|---|---|
| Blocker | Stops some customers from finding, choosing or buying a product. Fix first. |
| Serious | Makes a key task very hard for some customers. |
| Moderate | Causes confusion or extra effort. |
| Minor | Polish; fix when convenient. |
5. Findings
Highest priority first. Findings 7 and 8 come from a third-party app and are also listed in section 6.
1. The size and color pickers have no name
Blocker
- Where
- Product page, the Size and Color dropdowns under the price (selector:
variant-selects select) - What happens
- The words "Size" and "Color" are shown above each dropdown but aren't linked to it. A screen reader says "popup button, Medium" or "popup button, Sage", with no hint which option it is.
- Who it affects
- Blind and low-vision customers using screen readers, and people using voice control, who can't say "Size" to move to the dropdown. Some will buy the wrong size or give up.
- WCAG 2.2
- 1.3.1 Info and Relationships (Level A); 4.1.2 Name, Role, Value (Level A)
- How to reproduce
- On a Mac, open the product page in Safari and turn on VoiceOver (Command + F5).
- Press Tab until you reach the first dropdown.
- VoiceOver says "Medium, popup button" and never says "Size".
- How to fix
- In the theme code, give each dropdown a real label. The theme's "Pills" style for the variant picker already uses a labeled group, so switching to it in the theme editor (Product information, Variant picker block, Style) also fixes this with no code. To keep dropdowns, edit the snippet:
{%- comment -%} before {%- endcomment -%} <span class="form__label">{{ option.name }}</span> <select name="options[{{ option.name | escape }}]"> {%- comment -%} after {%- endcomment -%} <label class="form__label" for="Option-{{ section.id }}-{{ forloop.index0 }}"> {{ option.name }} </label> <select id="Option-{{ section.id }}-{{ forloop.index0 }}" name="options[{{ option.name | escape }}]"> - Where the fix lives
- Theme:
snippets/product-variant-options.liquid, or the Variant picker block setting in the theme editor - Screenshot
-
The two dropdowns, outlined. The labels above them are plain text, not linked to the dropdowns. - Re-check result
- Filled in after the free re-check.
2. "Added to cart" isn't announced
Serious
- Where
- Product page, after pressing Add to cart (selector:
#cart-notification) - What happens
- A small "Added to your cart" panel slides in at the top right, but keyboard focus stays on the Add to cart button and screen readers say nothing. The panel closes on its own after a few seconds.
- Who it affects
- Screen reader users, who can't tell whether the item was added and may add it two or three times. Keyboard users and people using screen magnifiers may miss the panel before it closes.
- WCAG 2.2
- 4.1.3 Status Messages (Level AA)
- How to reproduce
- Turn on VoiceOver or NVDA and go to the product page.
- Tab to Add to cart and press Enter.
- Nothing is read out. The cart count in the header changes silently.
- How to fix
- Add a status message area once in the theme layout and fill it when the cart updates. Also stop the panel closing on a timer, or move focus into it so people can read it and choose "View cart" or "Continue shopping".
<!-- layout/theme.liquid, just after <body> --> <p id="CartStatus" class="visually-hidden" role="status"></p> // assets/product-form.js, after the item is added document.getElementById('CartStatus').textContent = 'Added to cart: ' + productTitle + '. Cart now has ' + itemCount + ' items.'; - Where the fix lives
- Theme:
layout/theme.liquidandassets/product-form.js - Screenshot
- In a real report: the product page with the "Added to your cart" panel open and focus still on the button.
- Re-check result
- Filled in after the free re-check.
3. The cart button in the header has no name
Serious
- Where
- Site header, every page (counted once) (selector:
a.header__icon--cart) - What happens
- The cart is a shopping bag icon with a number bubble. Screen readers say "link" or "link, 2". The theme's hidden "Cart" text was removed during customization.
- Who it affects
- Screen reader users, who can't find the cart from the header, and voice control users, who can't say "click Cart".
- WCAG 2.2
- 2.4.4 Link Purpose (In Context) (Level A); 4.1.2 Name, Role, Value (Level A)
- How to reproduce
- Turn on a screen reader and Tab through the header.
- After the search and account icons you reach a link read only as "link, 2".
- How to fix
- Hide the icon from screen readers and add text that says what the link is and how many items are in the cart.
<a href="{{ routes.cart_url }}" class="header__icon header__icon--cart" id="cart-icon-bubble"> <span aria-hidden="true">{% render 'icon-cart' %}</span> <span class="visually-hidden"> Cart, {{ cart.item_count }} {{ cart.item_count | pluralize: 'item', 'items' }} </span> </a> - Where the fix lives
- Theme:
sections/header.liquid - Screenshot
- In a real report: the header with the cart icon outlined.
- Re-check result
- Filled in after the free re-check.
4. You can't see where you are in the mobile menu
Serious
- Where
- Menu drawer, every page at mobile width or when zoomed (selector:
.menu-drawer a) - What happens
- Links in the menu drawer show no focus outline, because custom CSS removes it. After the last link, pressing Tab moves focus to the page behind the drawer, where it is hidden under the drawer.
- Who it affects
- Keyboard users, including people who zoom in on a laptop (which switches the store to the mobile menu), and people with low vision.
- WCAG 2.2
- 2.4.7 Focus Visible (Level AA); 2.4.11 Focus Not Obscured (Minimum) (Level AA)
- How to reproduce
- Zoom the browser to 200%, or make the window narrow.
- Tab to the menu button and press Enter.
- Keep pressing Tab. No outline shows on the links, and after "Contact" focus disappears behind the drawer.
- How to fix
- In the theme editor, open Theme settings, then Custom CSS, and remove
.menu-drawer a:focus { outline: none; }. Add a visible focus style instead. Then make the drawer keep focus inside it while open, and close on Escape (Dawn's owntrapFocushelper inassets/global.jsdoes this, so check that the customized drawer still calls it)..menu-drawer a:focus-visible, .menu-drawer button:focus-visible { outline: 3px solid #0b1533; outline-offset: 2px; } - Where the fix lives
- Theme: Custom CSS in Theme settings, and
assets/global.js - Screenshot
- In a real report: the open drawer with focus on a link and no outline showing.
- Re-check result
- Filled in after the free re-check.
5. Product gallery images have no text description
Moderate
- Where
- Product page, the main image and its 5 thumbnails (selector:
.product__media img) - What happens
- The images have no alt text. Screen readers read the file name, such as "H P mug sage 02 underscore 1200 x", or skip the image. The thumbnail buttons are read only as "button".
- Who it affects
- Blind and low-vision customers, who miss details the photos show, such as the glaze color, size in the hand and the handle shape.
- WCAG 2.2
- 1.1.1 Non-text Content (Level A); 4.1.2 Name, Role, Value (Level A) for the thumbnail buttons
- How to reproduce
- With a screen reader on, move to the product images.
- Listen for a file name or "image" with no description.
- How to fix
- In your Shopify admin, open Products, choose the product, click each image and add alt text, for example "Sage green stoneware mug, held in one hand, about 4 inches tall".
- In the theme, make sure the gallery prints that text:
alt="{{ media.alt | escape }}". This theme's customized thumbnail snippet leaves it out. - Give each thumbnail button a name, for example
aria-label="Show image {{ forloop.index }} of {{ product.media.size }}".
- Where the fix lives
- Content in Shopify admin (alt text), and theme:
snippets/product-thumbnail.liquid - Screenshot
- In a real report: the gallery with each image outlined and the text a screen reader reads out.
- Re-check result
- Filled in after the free re-check.
6. Sale prices are hard to read
Moderate
- Where
- Home page product cards and the product page price (selectors:
.price-item--sale,.price-item--regular s) - What happens
- The sale price is light coral (
#E8837A) on white: a contrast ratio of 2.6:1. The crossed-out regular price is light gray (#A3A3A3): 2.5:1. Text this size needs at least 4.5:1. - Who it affects
- Customers with low vision or color vision deficiency, older customers, and anyone shopping on a phone outdoors.
- WCAG 2.2
- 1.4.3 Contrast (Minimum) (Level AA)
- How to reproduce
- Open the home page and find a product on sale.
- Measure the price colors with a contrast checker, such as the one built into your browser's developer tools.
- How to fix
- In the theme editor, open Theme settings, then Custom CSS, and change the two colors. A darker red such as
#B42318keeps the "sale" feel at 6.6:1, and#6B6B6Bfor the old price gives 5.3:1. If the colors come from a color scheme instead, change them in Theme settings, Colors. - Where the fix lives
- Theme: Custom CSS or the color scheme in Theme settings
- Screenshot
-
Current sale price colors (left) and the suggested ones (right). - Re-check result
- Filled in after the free re-check.
7. Star ratings are read as "star, star, star, star, star"
Moderate
- Where
- Product page under the title, and home page product cards. Comes from the reviews app (called "ReviewNest" in this sample) (selector:
.rn-stars img) - What happens
- The rating is five separate star images, each with the alt text "star". Screen readers read "star" five times whether the product is rated 1 or 5, and never say the number of reviews.
- Who it affects
- Screen reader users, who can't tell how well a product is rated.
- WCAG 2.2
- 1.1.1 Non-text Content (Level A); 1.3.1 Info and Relationships (Level A)
- How to reproduce
- With a screen reader on, move to the stars under the product title.
- You hear "star" five times and no rating.
- How to fix
- Check the app's settings for an accessibility or "star style" option first. If there isn't one, send this finding to the app's developer and ask for a single text alternative such as "Rated 4.6 out of 5, 128 reviews". As a stopgap, the theme can print that text from the standard product reviews metafields (
product.metafields.reviews.ratingandreviews.rating_count) if the app fills them in. - Where the fix lives
- App: ReviewNest (settings or developer); theme stopgap in
sections/main-product.liquid - Screenshot
- In a real report: the star rating outlined, with what the screen reader reads out.
- Re-check result
- Filled in after the free re-check.
8. The "Write a review" star picker only works with a mouse
Moderate
- Where
- Product page, the review form opened by "Write a review". Comes from the reviews app (selector:
.rn-form .rn-star-picker span) - What happens
- The stars for choosing a rating are plain elements that only respond to a click. Tab skips over them, so the form can't be sent without a mouse.
- Who it affects
- Keyboard users and screen reader users, who can't leave a review. It doesn't stop a purchase, which is why it isn't a blocker here.
- WCAG 2.2
- 2.1.1 Keyboard (Level A); 4.1.2 Name, Role, Value (Level A)
- How to reproduce
- Open "Write a review" using only the keyboard.
- Press Tab. Focus jumps from the close button to the Name field, skipping the stars.
- How to fix
- This is inside the app, so the store owner can't change it directly. Send the finding to the developer and ask them to use a group of radio buttons ("1 star" to "5 stars") for the rating. If they can't fix it, consider a reviews app whose form works with a keyboard.
- Where the fix lives
- App: ReviewNest (developer)
- Screenshot
- In a real report: the review form with the stars outlined.
- Re-check result
- Filled in after the free re-check.
6. Issues from third-party apps
Problems caused by installed apps (reviews, pop-ups, chat, upsells) are listed here separately. The store owner usually can't change the app's code; the fix is to change settings, swap the app or send the finding to the app's developer.
| App | Problem | Finding | Suggested action |
|---|---|---|---|
| ReviewNest (reviews) | Star rating read as five "star" images, no score | 7 | Check app settings; ask the developer for a text rating; theme stopgap from review metafields |
| ReviewNest (reviews) | Review form star picker needs a mouse | 8 | Send to the developer; consider another reviews app if it isn't fixed |
7. Re-check
One free re-check of the pages in section 2 within 30 days of this report. Reply to the report email when your fixes are live. We'll update the "Re-check result" line on each finding and send a short summary.
8. What this report is and isn't
- It is testing and remediation guidance, not legal advice or a compliance guarantee.
- It covers only the pages and dates listed. Theme updates, new apps or new content can add new problems.
- We don't recommend accessibility overlays or widgets; they don't fix the underlying code.
- Findings are our professional opinion based on the tests described in section 3.