RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/Cursor rules/Shopify/horizon

Cursor rule

.cursor/rules/product-card-accessibility.mdc

Product card accessibility compliance pattern

Cursor rules

Quality

40/100

Scores the file, not the repository.

Length

1,087 words

1 headings · 6 code blocks

Repository

428

— · pushed 17 days ago

Last changed

3 days ago

First indexed 3 days ago.
Shopify/horizon/.cursor/rules/product-card-accessibility.mdcRawGitHub
1---
2description: Product card accessibility compliance pattern
3globs: *.vue, *.jsx, *.tsx, *.html, *.php, *.js, *.ts, *.liquid
4alwaysApply: false
5---
6# Product Card Component Accessibility Standards
7 
8Ensures product card components follow WCAG compliance and implement proper single tab-stop navigation for keyboard and screen reader users.
9 
10<rule>
11name: product_card_accessibility_standards
12description: Enforce product card component accessibility standards and single tab-stop navigation compliance
13filters:
14 - type: file_extension
15 pattern: "\\.(vue|jsx|tsx|html|liquid|php|js|ts)$"
16 
17actions:
18 - type: enforce
19 conditions:
20 # Product card missing article wrapper
21 - pattern: "(?i)<(div|section)[^>]*(?:product.*card|card.*product)[^>]*>"
22 pattern_negate: "<article"
23 message: "Product cards should be wrapped with the article element for semantic structure."
24 
25 # Product card missing proper link structure
26 - pattern: "(?i)<article[^>]*(?:product.*card|card.*product)[^>]*>"
27 pattern_negate: "<a[^>]*>.*?</a>"
28 message: "Product cards must contain a link element for keyboard navigation and screen reader accessibility."
29 
30 # Product title not wrapped in link
31 - pattern: "(?i)<(h1|h2|h3|h4|h5|h6)[^>]*(?:product.*title|title.*product)[^>]*>"
32 pattern_negate: "<a[^>]*>.*?</a>"
33 message: "Product titles should be wrapped in link elements to provide proper navigation context."
34 
35 # Heading not wrapping link element
36 - pattern: "(?i)<(h1|h2|h3|h4|h5|h6)[^>]*(?:product.*title|title.*product)[^>]*>"
37 pattern_negate: "<a[^>]*>"
38 message: "Product card headings should wrap link elements to maintain proper heading semantics."
39 
40 # Missing product image alt text
41 - pattern: "(?i)<img[^>]*(?:product|card)[^>]*>"
42 pattern_negate: "alt=\"[^\"]+\""
43 message: "Product card images must have descriptive alt text for screen reader users."
44 
45 # Empty alt text on product images
46 - pattern: "(?i)<img[^>]*(?:product|card)[^>]*alt=\"\"[^>]*>"
47 message: "Product card images should not have empty alt text; provide descriptive text or use alt=\"\" only for decorative images."
48 
49 # Product price missing proper semantic structure
50 - pattern: "(?i)<(div|span)[^>]*(?:price|cost)[^>]*>"
51 pattern_negate: "(<span[^>]*aria-label|aria-label=\"[^\"]*price[^\"]*\")"
52 message: "Product prices should have proper semantic labeling for screen readers."
53 
54 # Product description not in paragraph element
55 - pattern: "(?i)<(div|span)[^>]*(?:product.*description|description.*product)[^>]*>"
56 pattern_negate: "<p"
57 message: "Product descriptions should be wrapped in paragraph elements for proper semantic structure."
58 
59 # Missing focus indicators
60 - pattern: "(?i)<a[^>]*(?:product.*card|card.*product)[^>]*>"
61 pattern_negate: "(focus|hover|active)"
62 message: "Product card links should have visible focus indicators for keyboard navigation."
63 
64 # Product card without proper positioning context
65 - pattern: "(?i)<article[^>]*(?:product.*card|card.*product)[^>]*>"
66 pattern_negate: "(position.*relative|position: relative)"
67 message: "Product card containers should have position: relative for proper link overlay positioning."
68 
69 # Product card missing aria-labelledby
70 - pattern: "(?i)<article[^>]*(?:product.*card|card.*product)[^>]*>"
71 pattern_negate: "aria-labelledby=\"[^\"]+\""
72 message: "Product card articles should have aria-labelledby referencing the heading ID for better screen reader context."
73 
74 # Product card heading missing ID
75 - pattern: "(?i)<(h1|h2|h3|h4|h5|h6)[^>]*(?:product.*title|title.*product)[^>]*>"
76 pattern_negate: "id=\"[^\"]+\""
77 message: "Product card headings should have unique ID attributes for aria-labelledby reference."
78 
79 # Mouse-only link missing tabindex="-1"
80 - pattern: "(?i)<a[^>]*class=\"[^\"]*product-link-mouse[^\"]*\"[^>]*>"
81 pattern_negate: "tabindex=\"-1\""
82 message: "Mouse-only product links should have tabindex='-1' to remove them from tab order."
83 
84 - type: suggest
85 message: |
86 **Product Card Component Accessibility Best Practices:**
87 
88 **Required Structure:**
89 - **article element:** Wrap each product card with the article element for semantic meaning
90 - **Single tab-stop:** Each product card should contain only one keyboard tab-stop
91 - **Link overlay:** Use absolutely positioned link that covers the entire card area
92 - **Heading wraps link:** The heading should wrap the link element to maintain proper heading semantics
93 
94 **ARIA and Semantic Requirements:**
95 - **article role:** Implicit with article element, provides semantic structure
96 - **aria-labelledby:** Reference to the heading ID for article labeling
97 - **Heading ID:** Unique ID attribute for aria-labelledby reference
98 - **Link text:** Product title should be descriptive and unique
99 - **Image alt text:** Provide descriptive alt text for product images
100 - **Price text:** Use visible text for pricing information
101 - **Description text:** Use paragraph elements for product descriptions
102 
103 **Keyboard Navigation Requirements:**
104 - **Single tab-stop:** Each product card should be navigable with one tab key press
105 - **Enter key:** Activate the link to navigate to product detail page
106 - **Focus indicators:** Provide clear visual focus indicators for keyboard users
107 - **Logical order:** Ensure tab order follows visual layout
108 - **Mouse-only links:** Use tabindex="-1" to remove mouse-only links from tab order
109 
110 **CSS Positioning Requirements:**
111 - **position: relative:** Set on card container for absolute positioning context
112 - **position: absolute:** Set on link element to cover card area
113 - **z-index:** Ensure link appears above other card content
114 - **pointer-events:** May need to manage pointer events for interactive elements
115 
116 **Implementation Patterns:**
117 
118 **Basic Product Card Structure:**
119```html
120 <article class="product-card" aria-labelledby="product-123-title">
121 <a href="/product/123" class="product-link-mouse" aria-hidden="true" tabindex="-1"></a>
122 <h2 id="product-123-title" class="product-title">
123 <a href="/product/123" class="product-link">Product Name</a>
124 </h2>
125 <img src="product-image.jpg" alt="Product description" class="product-image">
126 <div class="product-price">$29.99</div>
127 <p class="product-description">Product description text...</p>
128 </article>
129```
130 
131 **CSS for Visual Layout:**
132```css
133 .product-card {
134 position: relative;
135 display: flex;
136 flex-direction: column;
137 }
138 
139 .product-title {
140 order: 2; /* Move heading after image visually */
141 margin: 0;
142 padding: 16px;
143 }
144 
145 .product-image {
146 order: 1; /* Move image before heading visually */
147 width: 100%;
148 height: 200px;
149 object-fit: cover;
150 }
151```
152 
153 **CSS for Link Overlay:**
154```css
155 .product-card {
156 position: relative;
157 /* Other card styling */
158 }
159 
160 .product-link {
161 position: absolute;
162 top: 0;
163 left: 0;
164 right: 0;
165 bottom: 0;
166 z-index: 1;
167 text-decoration: none;
168 /* Ensure link text is visible */
169 color: inherit;
170 }
171 
172 .product-title {
173 /* Style the title within the link */
174 margin: 0;
175 padding: 1rem;
176 }
177```
178 
179 **Advanced Product Card with Interactive Elements:**
180```html
181 <article class="product-card" aria-labelledby="product-123-title">
182 <a href="/product/123" class="product-link-mouse" aria-hidden="true" tabindex="-1"></a>
183 <h2 id="product-123-title" class="product-title">
184 <a href="/product/123" class="product-link">Product Name</a>
185 </h2>
186 <img src="product-image.jpg" alt="Product description" class="product-image">
187 <div class="product-price">$29.99</div>
188 <button class="add-to-cart">Add to Cart</button>
189 </article>
190```
191 
192 **CSS for Advanced Layout:**
193```css
194 .product-card {
195 position: relative;
196 display: flex;
197 flex-direction: column;
198 }
199 
200 .product-title {
201 order: 2; /* Heading appears after image visually */
202 margin: 0;
203 padding: 16px;
204 }
205 
206 .product-image {
207 order: 1; /* Image appears before heading visually */
208 width: 100%;
209 height: 200px;
210 object-fit: cover;
211 }
212 
213 .product-content {
214 order: 3; /* Content appears after heading */
215 padding: 0 16px 16px;
216 position: relative;
217 }
218```
219 
220 **CSS for Interactive Elements:**
221```css
222 .product-card {
223 position: relative;
224 }
225 
226 .product-link {
227 position: absolute;
228 top: 0;
229 left: 0;
230 right: 0;
231 bottom: 0;
232 z-index: 1;
233 /* Allow clicks to pass through to buttons */
234 pointer-events: none;
235 }
236 
237 .product-title {
238 pointer-events: auto;
239 }
240 
241 .add-to-cart {
242 position: relative;
243 z-index: 2;
244 /* Ensure button is above link overlay */
245 }
246```
247 
248 **JavaScript Considerations:**
249 - Ensure proper event handling for interactive elements within cards
250 - Manage pointer events appropriately for overlay links
251 - Test keyboard navigation flow with screen readers
252 - Verify that screen readers can access all card content
253 - Consider implementing skip links for large product grids
254 
255 **Accessibility Notes:**
256 - Screen readers will announce the link text (product title) when focusing
257 - Other card content remains discoverable through normal screen reader navigation
258 - The article element provides semantic structure for screen readers
259 - Ensure sufficient color contrast for all text elements
260 - Test with various screen reader and browser combinations
261 - Consider implementing skip links for large product grids (10+ items)
262 
263 **Testing Requirements:**
264 - Navigate using Tab key only - each card should be one tab-stop
265 - Use screen reader to verify all content is accessible
266 - Test with keyboard-only navigation
267 - Verify focus indicators are visible and clear
268 - Test with high contrast mode enabled
269 
270metadata:
271 priority: high
272 version: 1.0
273</rule>
274description:
275globs:
276alwaysApply: false
277---
278 

Sections

  • Product Card Component Accessibility Standards

What it covers

ui

Glob targeting

  • *.vue
  • *.jsx
  • *.tsx
  • *.html
  • *.php
  • *.js
  • *.ts
  • *.liquid

Format

Cursor rules

The most expressive format here. Many small .mdc files, each with frontmatter declaring when it should load, so a rule about migrations only enters context when a migration is open. Costs the most to maintain and only one editor reads it.

What the corpus says about it

Repository

Owner
Shopify
Language
—
License
—
Archived
no

All configs in this repo

Also in Shopify/horizon

Diff this repo’s formats

One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?

The other instruction files in this repository
RepositoryFormatStackCoversScoreChanged
Shopify/horizon.cursor/rules/accordion-accessibility.mdc · 428Cursor rulesunclassifiedui40/1003 days ago
Shopify/horizon.cursor/rules/animation-accessibility.mdc · 428Cursor rulesunclassifiedui40/1003 days ago
Shopify/horizon.cursor/rules/blocks.mdc · 428Cursor rulesunclassifiedstylearchtypesdatabase+262/1003 days ago
Shopify/horizon.cursor/rules/breadcrumb-accessibility.mdc · 428Cursor rulesunclassifiedui36/1003 days ago
Shopify/horizon.cursor/rules/carousel-accessibility.mdc · 428Cursor rulesunclassifiedui32/1003 days ago
Shopify/horizon.cursor/rules/cart-drawer-accessibility.mdc · 428Cursor rulesunclassifiedui40/1003 days ago
Shopify/horizon.cursor/rules/chat-window-accessibility.mdc · 428Cursor rulesunclassifiedstyleui24/1003 days ago
Shopify/horizon.cursor/rules/color-contrast-accessibility.mdc · 428Cursor rulesunclassifiedlint-formatui44/1003 days ago
Shopify/horizon.cursor/rules/color-swatch-accessibility.mdc · 428Cursor rulesunclassifiedui40/1003 days ago
Shopify/horizon.cursor/rules/commit-messages.mdc · 428Cursor rulesunclassifiedsetuplint-formattypesgit62/1003 days ago
Shopify/horizon.cursor/rules/css-standards.mdc · 428Cursor rulesunclassifiedstylearchuiperformance+349/1003 days ago
Shopify/horizon.cursor/rules/disclosure-accessibility.mdc · 428Cursor rulesunclassifiedui40/1003 days ago
Shopify/horizon.cursor/rules/dropdown-navigation-accessibility.mdc · 428Cursor rulesunclassifiedstyleui36/1003 days ago
Shopify/horizon.cursor/rules/flip-card-accessibility.mdc · 428Cursor rulesunclassifiedstyleui36/1003 days ago
Shopify/horizon.cursor/rules/form-accessibility.mdc · 428Cursor rulesunclassifiedui32/1003 days ago
Shopify/horizon.cursor/rules/javascript-standards.mdc · 428Cursor rulesunclassifiedstylearchtypesui+254/1003 days ago
Shopify/horizon.cursor/rules/landmark-accessibility.mdc · 428Cursor rulesunclassifiedui40/1003 days ago
Shopify/horizon.cursor/rules/liquid.mdc · 428Cursor rulesunclassifiedbuildstyletypesdatabase+277/1003 days ago
Shopify/horizon.cursor/rules/locales.mdc · 428Cursor rulesunclassifiedarch49/1003 days ago
Shopify/horizon.cursor/rules/localization.mdc · 428Cursor rulesunclassifiedstyle54/1003 days ago
Diff against .cursor/rules/accordion-accessibility.mdc Diff against .cursor/rules/animation-accessibility.mdc Diff against .cursor/rules/blocks.mdc Diff against .cursor/rules/breadcrumb-accessibility.mdc Diff against .cursor/rules/carousel-accessibility.mdc Diff against .cursor/rules/cart-drawer-accessibility.mdc Diff against .cursor/rules/chat-window-accessibility.mdc Diff against .cursor/rules/color-contrast-accessibility.mdc Diff against .cursor/rules/color-swatch-accessibility.mdc Diff against .cursor/rules/commit-messages.mdc Diff against .cursor/rules/css-standards.mdc Diff against .cursor/rules/disclosure-accessibility.mdc Diff against .cursor/rules/dropdown-navigation-accessibility.mdc Diff against .cursor/rules/flip-card-accessibility.mdc Diff against .cursor/rules/form-accessibility.mdc Diff against .cursor/rules/javascript-standards.mdc Diff against .cursor/rules/landmark-accessibility.mdc Diff against .cursor/rules/liquid.mdc Diff against .cursor/rules/locales.mdc Diff against .cursor/rules/localization.mdc
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack