Shopify Builds>Capabilities>Accessibility remediation at component level

Accessibility Remediation at Component Level on Shopify

Definition

Code-level accessibility work on individual components: ARIA-correct disclosure and accordion patterns, focus management in drawers and modals, accessible names derived from hrefs, live regions, form error linking, motion held behind a reduced-motion query, and generated ids composed from the call site so a snippet rendered three times in one document stays unique — including repairing heading semantics injected by vendor widgets.

The Evidence

  • Scope of this page: 19 eligible builds of 35 gated. Sixteen excluded under the 2026-09-07 publication ruling; one held. Only the nineteen are described, counted or cited on this page, and every count below is drawn from them.
  • Split by storefront: LUS Brands 10, Nudestix 5, Three Ships 4.
  • Split by attribution: 10 built on top of vendor theme code and disclosed as such on their own pages, 9 Deploi-authored.
  • Evidence quality: eleven carry code plus client working records. Eight are documented from the code; no client-side record of the decision survives.
  • Confidence: 10 strong, 9 moderate.
  • Twelve of the 19 have published build pages.
  • Status: live, verified 2026-09-07.
  • Not claimed: no conformance audit, no WCAG level, no site-level accessibility statement about any storefront named here.

How It's Actually Built

Four shapes recur across the nineteen, and none of them is a widget you install.

Make ids survive being rendered more than once. A snippet written for one place ends up in three. On LUS Brands the country selector renders in the announcement bar, the desktop header and the mobile drawer of the same document, so every option id inside it arrived three times over. Ids were rebuilt as {{ localPosition }}-country-{{ country.iso_code | downcase }}, prefixed by the render position the call site passes in; the language picker takes the same parameter for its list and label ids — AnnouncementLanguage, HeaderLanguage, HeaderLanguageMobile. ISO codes are stable, unique and safe in an attribute. Localized country names are none of those.

Delete ARIA that's wrong before adding ARIA that's right. In the same selector, role="combobox" sat on a plain filter input that is not a combobox, and two <ul> elements carried a role="list" they already had. Three attributes removed, none added. The correction is often a deletion.

Borrow the theme's behavior contract instead of forking it. The Three Ships PDP accordion in pdp-accordion.liquid reuses the theme's own collapsible data attributes and supplies only markup and styling — an <h2> wrapping the .pdp-accordion__title button, aria-controls pointing at PdpAccordionPanel--<block_id>. One accordion system on the page, a different visual treatment on top of it.

Treat motion as a preference the visitor already expressed. The theme-wide section reveal on LUS Brands hides sections before paint from an inline <style> block wrapped in @media (prefers-reduced-motion: no-preference), mirrored by a <noscript> block that forces everything visible. On Nudestix, the rotating announcement bar carries a pause/play toggle that rewrites its own aria-label to match the action it will perform, and the <play-pause> element fronting muted autoplay hero video mirrors the video's real play, pause and ended events rather than a class it toggles itself — so the control stays honest when the browser stops playback.

Keyboard order gets the same literal treatment: in de_pagination.liquid, an arrow with nowhere to go renders as a non-focusable <span aria-disabled="true"> rather than a dead link.

The Buy-vs-Build Position

The corpus's own verdict is one sentence: "Done at code level throughout, including repairing heading semantics injected by bought widgets — the overlay path is never taken."

An accessibility overlay is a purchased script that adjusts a page at runtime and offers visitors a preferences panel. It's a genuinely contested product category, and this page isn't where that argument gets settled. The difference you can check is timing: an overlay acts on the page after the theme rendered it; this work changes what the theme renders. A duplicated id, a role naming the wrong control, a button with no accessible name — all decided in Liquid, and that's where these were fixed.

One narrowing, since the verdict says widgets: across the nineteen eligible builds the vendor code we corrected is theme code — Dawn's country selector, a premium theme's collapsible contract. Widget-side correction lives next door in vendor widget remediation. The commercial argument sits in the accessibility remediation buy-or-build analysis.

The Builds

Twelve of the nineteen eligible builds have a page of their own. The others named below have no page written yet.

LUS Brands — Dawn 15.4.1

Nudestix — Dawn 6.0.2

  • Rotating announcement carousel above the header, with pause control — a real pause/play toggle whose aria-label is rewritten to match the action, over a bar that reserves its own height. Medium, global.
  • Accessible play/pause web component for autoplaying hero video — a <play-pause> custom element resolving its video by selector, with listeners removed on disconnect. Low, home and global.
  • Mega-menu disclosure behavior — the body scroll lock releases only after checking no other panel is open, and closes route through the header-menu host so the theme's own aria-expanded bookkeeping stays intact. Low, global.
  • Pagination snippet with branded arrows — a fork of Dawn's pagination with a rewritten page URL for the shade-level collection templates. Low, listing and blog.
  • NUDESKIN scrolling caption band — two caption lines with a template-aware variant class. Low, listing and landing.

Three Ships — Palo Alto 5.8.0 by Presidio Creative, a paid premium theme

  • PDP content accordion that borrows the premium theme's collapsible contract — an <h2> around the trigger and aria-controls onto a block-scoped panel id, driven by the theme's existing collapsible behavior. Medium, product.
  • Inline size picker on cart and PDP upsell cards — unavailable variants render as disabled pills; the submit button reads "Select option" until one is chosen. Medium, cart and product.
  • Buttons list section built on the theme's collection-list renderer — button rows reusing the vendor renderer rather than a second markup path. Low, product, listing and landing.
  • Design-token layer extended with brand webfonts — brand @font-face declarations added to the theme's generated CSS custom-property layer. Medium, global.

What This Rests On

  • Liquid section schema and settings — in 16 of the 19; the settings that decide what renders, and therefore what has to be labeled.
  • Theme blocks — in 6; repeatable blocks are why ids have to be composed from block.id rather than a loop index.
  • Metafields — in 3; the FAQ content these accordions expose comes from a page metafield, not from section settings.
  • Shopify Markets — in 3; market and language selectors are the components that get rendered three times.
  • Section Rendering API — in 2; when a fragment is replaced, its ids and roles have to survive the swap.
  • Intersection Observer API — in 1; entrance animation is triggered here, which is why the reduced-motion query wraps it.

Two things this rests on have no Shopify documentation page, because they're browser platform: the prefers-reduced-motion media query, and the WAI-ARIA attributes — aria-expanded, aria-controls, aria-current, aria-disabled, role — that most of this work is either adding, composing or deleting.

What Varies by Storefront

The three storefronts produce three different kinds of fix, and the theme base is most of the reason.

LUS Brands runs Dawn 15.4.1, and its work is dominated by one class of defect: Dawn's own snippets being correct in isolation and wrong when the theme renders them more than once in a document. Country selector, language picker, icon block, FAQ items — the common repair is composing every generated id from something the call site supplies. That is not a Dawn criticism; it's what happens when a base theme is extended past the layout it shipped with.

Nudestix runs Dawn 6.0.2 and the components in question are largely its own, so the work is behavioral rather than structural: a control for motion that autoplays, a disclosure that has to release the body scroll lock only when the last panel closes, an announcement bar that reserves its height before its script runs.

Three Ships runs Palo Alto 5.8.0 by Presidio Creative, a paid premium theme. Here the discipline is restraint. The accordion reuses the vendor's collapsible data attributes and changes only markup and styling; the buttons section calls the vendor's own collection renderer instead of introducing a second one. Every one of those decisions keeps a single interaction pattern on the page, and it means a theme update has less of our code to collide with.

Where This Gets Hard

Scope, stated plainly. This page covers 19 of the 36 gated builds that carry this capability. The other seventeen are held out and not counted anywhere on it. The publication ruling that cleared this page sets the test: a build is usable as accessibility evidence only if its own engineering record raises nothing about accessibility and it touches nothing we've fenced from accessibility claims. Sixteen builds fail that test; one more is held for unrelated reasons. What this page describes is component-level practice — ids, roles, accessible names, focus order, motion preferences — on the components listed above. It is not an audit, and it is not a claim that any of these three storefronts is accessible.

The subset is the argument. Nineteen of thirty-six. The test is deliberately blunt: a component we have any open accessibility question about is not evidence of accessibility practice, whatever else is good in it. Publishing the full thirty-six would have made this page longer and worth less.

Component-level correctness is not a site-level verdict, and the gap between them is large. No conformance audit against WCAG has been run on these storefronts by anyone in this corpus. Correct components can sit inside an incorrect page: reading order, color contrast, focus management across a route change, forms, third-party markup nobody here wrote. If what you need is a conformance position, what you need first is an audit, and it isn't this.

Vendor code changes underneath you. Half of this work is edits inside Dawn's and Palo Alto's own snippets. A theme update overwrites them silently and nothing tells you it happened, so every fix carries a re-apply-and-retest obligation for as long as the theme is maintained. Maintenance line, not launch cost — and the reason to keep the diff against a vendor theme as small as the Three Ships components keep theirs.

Where we'd advise against starting here. If what you need is a compliance position on a deadline, component work is the slow path and it produces no document. And if nobody will own the retest after the next theme update, these fixes decay quietly: the roles come back, the ids drift, nothing surfaces it.

Related Capabilities

Answers to Help You Make Smart Decisions

What does component-level accessibility work actually change on a Shopify theme?

Four things, mostly. The id and aria-controls pairs that connect a trigger to the panel it opens. The role on an element, including removing one that describes the wrong control. The accessible name a button or link exposes. And whether motion runs at all, which belongs to the visitor's prefers-reduced-motion setting rather than to a theme toggle.

Why do duplicate DOM ids show up in a Shopify theme?

Because a snippet written once gets rendered more than once. A country selector built for the header ends up in the announcement bar and the mobile drawer too, and every id inside it arrives three times over. The repair is to pass the call site into the snippet and compose ids from it, so each instance owns its own.

Does an accessibility overlay replace this work?

They act at different moments, and that's the useful way to compare them. An overlay adjusts a page after it has rendered; code-level work changes what the theme renders in the first place. Defects that live in the source markup — a duplicated id, a wrong role, a missing accessible name — get corrected where the markup is written, and on these three storefronts that's the path taken.

Does this mean these storefronts are accessible?

No, and we won't imply otherwise. Nineteen builds with correct semantics is a set of correct components, not a verdict about a site. Nobody in this corpus has run a conformance audit against WCAG on any of the three, and a page that lists accessibility work while leaving that unsaid is inviting you to assume it.

Ready to Fix Accessibility Where the Markup Is Written?

If someone has handed you a list of component defects — duplicate ids, a control with no name, a carousel nobody can pause — that's theme work, and it's the kind we do. Contact us today to go through what your components actually emit, before anyone promises anyone a compliance position.

Builds

Audience-targeted announcement bar with sticky-height measurement

Dawn's announcement bar, extended so each announcement block carries an audience setting, the section counts the matching blocks before it renders, and that count decides whether the page gets no bar, a static line or a carousel — with slide numbering that matches what's actually on screen, and a pinned height the rest of the layout can read.

LUS Brands

Arched-label icon grid PDP block

A six-slot row of circular badge icons with captions that curve over them — an SVG `textPath` per label, an arc id composed from `block.id` so the block can repeat, and layout driven entirely by custom properties the merchandiser sets.

LUS Brands

Kids FAQ page: single-level variant of the FAQ engine

A second FAQ page for the kids sub-brand that shares the help center's content model — the same page metafield, the same accordion contract — but drops the category layer, so a shorter list of questions reads as one flat, keyboard-operable accordion with its own tone and its own way out.

LUS Brands

Theme-wide section reveal that replaces Dawn's per-element scroll animations

One entrance animation for every top-level section on the storefront, applied from the layout rather than authored into each section — with the hide decided before first paint, the reveal driven by an intersection observer, and reduced-motion and no-JavaScript visitors never hidden from anything.

LUS Brands

House pagination component with result counter for blog and collection grids

A self-contained `de_pagination` snippet: pill page buttons, prev and next arrows that become non-focusable spans at the ends of the range, and a computed result-range line, rendered by the blog index and the collection grid from one file.

LUS Brands

Country/market selector hardened for three simultaneous instances

Dawn's country selector, rendered three times on every page, with every option id namespaced by the position that rendered it and three ARIA attributes removed — so the three instances stop colliding and the vendor's own localization script needed no change at all.

LUS Brands

Dawn media gallery hardened for hidden slides and deferred video

A surgical patch to Dawn's `media-gallery` custom element so that selecting, reordering and announcing media all skip slides the server has hidden for the current variant — and so a variant with no matching thumbnail degrades to a sensible slide instead of an exception.

LUS Brands

Variant-aware PDP hero banner driven by a 'heroic' metaobject

An editorial hero below the buy box that resolves its art, headline and copy from a per-variant metaobject, and refetches its own content through the Section Rendering API when the shopper switches variant.

LUS Brands

Pill variant picker with merchandiser-named size labels

Dawn prints an option value and nothing else. We extended its picker so a size pill carries two lines — a merchandiser's word for that size above the size itself — and falls back to positional defaults when nobody has written one.

LUS Brands

Vertical filter rail and an in-place mobile filter accordion replacing Dawn's drill-down drawer

Dawn's facets snippet was rebuilt into a sidebar rail with color swatches and show-more truncation, an accordion mobile drawer where every group opens in place, and a single sort control that physically relocates between breakpoints.

LUS Brands

Accessible link-label helpers for repeated CTAs

Two Liquid snippets that resolve a real conflict between two link-naming rules — identical link text on different destinations versus an accessible name that must contain the visible label — by deriving a name from the link's href and emitting it only when it differs from what the shopper can see.

Nudestix

Rotating announcement carousel above the header, with pause control

An auto-rotating promo bar rendered by the layout above the header: a looped Swiper of up to ten text blocks that reserves its height before any script runs, waits for the carousel library on a bounded retry, and gives the shopper a real pause control whose label always says what it will do next.

Nudestix

Metafield-driven PDP content system: auto-built accordions, need-to-know strip and campaign widgets

A layered content resolver on the Nudestix product page: legacy description HTML parsed into accordions at render time, three of them overridden per shade from metafields, with icon strips, badges and campaign widgets assembled from 29 metafield keys around them.

Nudestix

Shade swatch rendering and per-variant content payload

The swatches are the visible half. The other half is a hidden input per variant carrying that shade's copy, ingredients, SEO fields and badges — a data contract three separate features read without asking the server anything.

Nudestix

Accessible play/pause web component for autoplaying hero video

A `<play-pause>` custom element that gives a muted, autoplaying hero video a real keyboard-reachable control — self-wiring from a selector in its own markup, so Swiper can clone and reorder slides without any script knowing how many there are.

Nudestix

PDP content accordion that borrows the premium theme's collapsible contract

A product-page accordion block that reuses Palo Alto's own `data-collapsible-*` behavior wiring while supplying its own heading semantics, CSS-variable theming and a responsive table layout for the long-form panels merchandisers author per product.

Three Ships

Inline size picker on cart and PDP upsell cards

Size pills added inside the premium theme's own upsell card, so a multi-variant upsell in the cart drawer, on the cart page or in a product-page "pair with" module can be sized and added where it stands instead of sending the shopper somewhere else.

Three Ships