Cursor rule
.cursor/rules/tab-accessibility.mdcTab component accessibility compliance pattern
Cursor rules
Quality
40/100
Scores the file, not the repository.Length
567 words
1 headings · 2 code blocksRepository
428
— · pushed 17 days agoLast changed
3 days ago
First indexed 3 days ago.123456# Tab Component Accessibility Standards78Ensures tab components follow WCAG compliance and WAI-ARIA Tab Pattern specifications.910<rule>11name: tab_accessibility_standards12description: Enforce tab component accessibility standards and WAI-ARIA Tab Pattern compliance13filters:14 - type: file_extension15 pattern: "\\.(vue|jsx|tsx|html|liquid|php|js|ts)$"1617actions:18 - type: enforce19 conditions:20 # Tablist role requirement21 - pattern: "(?i)<(div|nav|section)[^>]*(?:tab.*list|list.*tab)[^>]*>"22 pattern_negate: "role=\"tablist\""23 message: "Tab list container must have role='tablist' attribute."2425 # Tab role requirement26 - pattern: "(?i)<(button|a|div)[^>]*(?:tab)[^>]*>"27 pattern_negate: "role=\"tab\""28 message: "Tab elements must have role='tab' attribute."2930 # Tabpanel role requirement31 - pattern: "(?i)<(div|section)[^>]*(?:tab.*panel|panel.*tab)[^>]*>"32 pattern_negate: "role=\"tabpanel\""33 message: "Tab panel elements must have role='tabpanel' attribute."3435 # Missing aria-selected state36 - pattern: "(?i)<[^>]*role=\"tab\"[^>]*>"37 pattern_negate: "aria-selected=\"(true|false)\""38 message: "Tab elements must have aria-selected attribute set to 'true' or 'false'."3940 # Missing aria-controls41 - pattern: "(?i)<[^>]*role=\"tab\"[^>]*>"42 pattern_negate: "aria-controls=\"[^\"]+\""43 message: "Tab elements must have aria-controls attribute referencing their associated panel."4445 # Missing aria-labelledby on tabpanel46 - pattern: "(?i)<[^>]*role=\"tabpanel\"[^>]*>"47 pattern_negate: "aria-labelledby=\"[^\"]+\""48 message: "Tab panel elements must have aria-labelledby referencing their associated tab."4950 # Missing keyboard event handlers51 - pattern: "(?i)<[^>]*role=\"tab\"[^>]*>"52 pattern_negate: "(onKeyDown|onkeydown|@keydown|v-on:keydown)"53 message: "Tab elements should handle keyboard events (Arrow keys, Space, Enter, Home, End)."5455 # Missing tablist label56 - pattern: "(?i)<[^>]*role=\"tablist\"[^>]*>"57 pattern_negate: "(aria-labelledby|aria-label)"58 message: "Tab list must have either aria-labelledby or aria-label for accessibility."5960 # Empty aria-label check61 - pattern: "(?i)<[^>]*role=\"tablist\"[^>]*aria-label=\"\"[^>]*>"62 message: "Tab list aria-label should not be empty; provide a meaningful description."6364 - type: suggest65 message: |66 **Tab Component Accessibility Best Practices:**6768 **Required ARIA Attributes:**69 - **role='tablist':** Set on the container of tab elements70 - **role='tab':** Set on each tab element71 - **role='tabpanel':** Set on each panel element72 - **aria-selected:** 'true' for active tab, 'false' for inactive tabs73 - **aria-controls:** On tab elements, referencing their panel74 - **aria-labelledby:** On tab panels, referencing their tab75 - **aria-labelledby/aria-label:** On tablist for accessibility7677 **Optional ARIA Attributes:**78 - **aria-orientation:** 'vertical' if tabs are vertically oriented79 - **aria-haspopup:** Set on tabs with popup menus80 - **aria-disabled:** 'true' if tab cannot be activated8182 **Keyboard Interaction Requirements:**83 - **Tab:** Move focus into/out of tab list84 - **Left/Right Arrow:** Move between tabs (horizontal)85 - **Up/Down Arrow:** Move between tabs (vertical)86 - **Space/Enter:** Activate focused tab87 - **Home:** Move to first tab88 - **End:** Move to last tab89 - **Shift + F10:** Open popup menu if available90 - **Delete:** (Optional) Remove tab9192 **Structure Requirements:**93 - Tab list must contain all tab elements94 - Each tab must be associated with exactly one panel95 - Active tab must be visually distinct96 - Tab panels must be properly labeled97 - Consider using native button elements for tabs9899 **Implementation Patterns:**100101 **Basic Tab Structure:**102```html103 <div role="tablist" aria-label="Settings">104 <button role="tab"105 aria-selected="true"106 aria-controls="panel-1"107 id="tab-1">108 Account109 </button>110 <button role="tab"111 aria-selected="false"112 aria-controls="panel-2"113 id="tab-2">114 Security115 </button>116 </div>117118 <div role="tabpanel"119 id="panel-1"120 aria-labelledby="tab-1">121 Account settings content...122 </div>123 <div role="tabpanel"124 id="panel-2"125 aria-labelledby="tab-2"126 hidden>127 Security settings content...128 </div>129```130131 **Vertical Tab List:**132```html133 <div role="tablist"134 aria-label="Settings"135 aria-orientation="vertical">136 <button role="tab"137 aria-selected="true"138 aria-controls="panel-1"139 id="tab-1">140 Account141 </button>142 <button role="tab"143 aria-selected="false"144 aria-controls="panel-2"145 id="tab-2">146 Security147 </button>148 </div>149```150151 **JavaScript Considerations:**152 - Implement keyboard navigation between tabs153 - Handle tab activation on Space/Enter154 - Update aria-selected states155 - Manage focus when switching tabs156 - Handle optional features (Home/End, Delete)157 - Consider implementing automatic activation158 - Ensure proper focus management159160 **Accessibility Notes:**161 - Choose between automatic and manual activation162 - Ensure visual focus indicators are clear163 - Test with screen readers for proper announcement164 - Consider implementing skip links for long tab lists165 - Maintain proper heading structure within panels166 - Ensure sufficient color contrast for active/inactive states167168metadata:169 priority: high170 version: 1.0171</rule>172
Also in Shopify/horizon
Diff this repo’s formatsOne 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?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| Shopify/horizon.cursor/rules/accordion-accessibility.mdc · 428 | Cursor rules | ui | 40/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/animation-accessibility.mdc · 428 | Cursor rules | ui | 40/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/blocks.mdc · 428 | Cursor rules | stylearchtypesdatabase+2 | 62/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/breadcrumb-accessibility.mdc · 428 | Cursor rules | ui | 36/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/carousel-accessibility.mdc · 428 | Cursor rules | ui | 32/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/cart-drawer-accessibility.mdc · 428 | Cursor rules | ui | 40/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/chat-window-accessibility.mdc · 428 | Cursor rules | styleui | 24/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/color-contrast-accessibility.mdc · 428 | Cursor rules | lint-formatui | 44/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/color-swatch-accessibility.mdc · 428 | Cursor rules | ui | 40/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/commit-messages.mdc · 428 | Cursor rules | setuplint-formattypesgit | 62/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/css-standards.mdc · 428 | Cursor rules | stylearchuiperformance+3 | 49/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/disclosure-accessibility.mdc · 428 | Cursor rules | ui | 40/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/dropdown-navigation-accessibility.mdc · 428 | Cursor rules | styleui | 36/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/flip-card-accessibility.mdc · 428 | Cursor rules | styleui | 36/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/form-accessibility.mdc · 428 | Cursor rules | ui | 32/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/javascript-standards.mdc · 428 | Cursor rules | stylearchtypesui+2 | 54/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/landmark-accessibility.mdc · 428 | Cursor rules | ui | 40/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/liquid.mdc · 428 | Cursor rules | buildstyletypesdatabase+2 | 77/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/locales.mdc · 428 | Cursor rules | arch | 49/100 | 3 days ago | |
| Shopify/horizon.cursor/rules/localization.mdc · 428 | Cursor rules | style | 54/100 | 3 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
