liquid-theme-a11y

Implement WCAG 2.2 accessibility patterns in Shopify Liquid themes. Covers e-commerce-specific components including product cards, carousels, cart drawers, price display, forms, filters, and modals. Use when building accessible theme components, fixing accessibility issues, or reviewing ARIA pattern

By benjaminsehl · 2,557 installs

npx skills add benjaminsehl/liquid-skills --skill liquid-theme-a11y

Source repository · Upstream listing

Accessibility for Shopify Liquid Themes Core Principle Every interactive component must work with keyboard only, screen readers, and reduced motion preferences. Start with semantic HTML — add ARIA only when native semantics are insufficient. Decision Table: Which Pattern? Component HTML Element ARIA Pattern Reference Expandable content <details /<summary None needed [Accordion]( accordion) Modal/dialog <dialog aria modal="true" [Modal]( modal) Tooltip/popup [popover] attribute role="tooltip" fallback [Tooltip]( tooltip) Dropdown menu <nav + <ul aria expanded on triggers [Navigation]( dropdown navigation) Tab interface <div role="tablist/tab/tabpanel" [Tabs]( tabs) Carousel/slider <div role="region" + aria roledescription [Carousel]( carousel) Product card <article aria labelledby [Product card]( product card) Form <form aria invalid , aria describedby [Forms]( forms) Cart drawer <dialog Focus trap [Cart drawer]( cart drawer) Price display <span aria label for context [Prices]( price display) Filters <form + <fieldset aria expanded for disclosures [Filters]( product filters) Page Structure Landmarks Single <header , <main , <footer per page Multiple <nav elements must have distinct aria label All content must live inside a landmark Skip Link Headings One <h1 per page, never skip levels (h1 → h3) Use real heading elements, not styled divs Template: <h1 is typically the page/product title Focus Management Focus Indicators Minimum 3:1 contrast ratio for focus indicators Use :focus visible (not :focus ) to avoid showing on click Never outline: none without a visible replacement Focus Trapping (Modals/Drawers) Trap focus inside modals, drawers, and dialogs Return focus to trigger element on close First focusable element gets focus on open Query all focusable elements: a[href], button:not([disabled]), input:not([disabled]), select, textarea, [tabindex]:not([tabindex=" 1"]) See [focus and keyboard patterns](references/focus and keyboard.md) for full FocusTrap implementation. Component Patterns Product Card Rules: Single tab stop per card (the main link) tabindex=" 1" on mouse only shortcuts (quick add) aria labelledby on <article pointing to the title Descriptive alt text on images; empty alt="" if decorative Carousel Rules: Auto rotation minimum 5 seconds, pause on hover/focus Play/pause button required for auto rotating carousels aria live="polite" on slide container (set to "off" during auto rotation) aria hidden="true" on inactive slides Each slide: role="group" + aria roledescription="slide" Modal Rules: Use native <dialog element aria labelledby pointing to the title Close on Escape key (native with <dialog ) Focus first interactive element on open Return focus to trigger on close Cart Drawer Same as modal pattern but with additional: Live region for cart count updates: <span aria live="polite" aria atomic="true" Clear "remove item" buttons with aria label="{{ 'cart.remove item' t: title: item.title }}" Quantity inputs with associated labels Forms Rules: Every input has a visible <label with matching for / id Use <fieldset /<legend for radio/checkbox groups Error messages: role="alert" + aria describedby linking to input aria invalid="true" on invalid inputs autocomplete attributes on common fields Required fields: required + aria required="true" + visual indicator Product Filters Price Display Use aria label to provide full price context (sale vs. original) aria hidden="true" on the visual strikethrough to avoid duplicate reading Accordion Native <details /<summary provides keyboard and screen reader support automatically. Tabs Arrow keys navigate between tabs (left/right) Only active tab has tabindex="0" , others 1 Dropdown Navigation Tooltip Mobile Accessibility Touch targets: minimum 44x44px, 8px spacing between targets No orientation lock: never restrict to portrait/landscape No hover only content: everything accessible via tap Use dvh instead of vh for mobile viewport units Animation & Motion No flashing above 3 times per second Auto playing animations need pause/stop controls Meaningful animations only — don't animate for decoration Visually Hidden Utility Use for screen reader only content like labels and descriptions. Color Contrast Element Minimum Ratio Normal text (<18px / <14px bold) 4.5:1 Large text (≥18px / ≥14px bold) 3:1 UI components & graphics 3:1 Focus indicators 3:1 Never rely solely on color to convey information — always pair with text, icons, or patterns. References [Component accessibility patterns](references/component patterns.md) [Focus and keyboard patterns](references/focus and keyboard.md)