feat(core): add eslint-plugin-jsx-a11y and fix accessibility violations#930
feat(core): add eslint-plugin-jsx-a11y and fix accessibility violations#930
Conversation
| ref={el => (this.trigger = el)} | ||
| id={this.id} | ||
| role="combobox" | ||
| tabIndex={0} |
There was a problem hiding this comment.
I see that tabIndex is assigned programmatically in onClick and in onKeyDown, I'm not sure if this don't break the current implementation, if you are not sure - easier to add eslint-disable
There was a problem hiding this comment.
Done - removed tabIndex={0} and added ESLint disable comment instead.
aa7dc1a to
a1cd508
Compare
- Add eslint-plugin-jsx-a11y with recommended rules to ESLint config - Fix cat-select: add tabIndex, aria-expanded, aria-controls, role="option", keyboard handlers - Fix cat-tag: add aria-expanded and aria-controls to combobox input - Fix cat-radio: remove incorrect role="radio" from label element - Fix cat-date-inline: remove redundant onClick from label (htmlFor handles focus) - Fix cat-input: add role="presentation" to wrapper div - Fix cat-i18n-registry: remove unused variable in catch block This enables static a11y linting as part of the standard lint workflow.
- Add axe-core dependency for runtime a11y checks
- Create reusable checkA11y() helper that injects axe-core into Stencil E2E pages
- Add formatViolations() helper for readable test output
- Disable document-level rules by default (title, lang, landmarks) for component testing
- Add a11y test examples to cat-button component
Usage:
import { checkA11y, formatViolations } from '../../utils/a11y-test';
const violations = await checkA11y(page);
expect(violations).toEqual([]);
- cat-input: replace role="presentation" with ESLint disable comment - cat-select: remove redundant tabIndex, onKeyDown handlers, and duplicate ARIA attributes - cat-select: use i18n for 'Options' fallback instead of hardcoded string - cat-tag: remove incorrect combobox role and associated ARIA attributes
- cat-menu: Change <nav role="menu"> to <div role="menu"> (nav is non-interactive landmark, menu is interactive role) - cat-select: Add tabIndex back to combobox for focusability - cat-select: Add eslint disable for option click handler
- cat-menu.spec: Update selectors from nav to div for role="menu" - cat-tag.spec: Remove role="combobox" and aria-controls from expected HTML
04eb042 to
e19b2e8
Compare
| @@ -109,55 +109,16 @@ importers: | |||
| version: 5.9.3 | |||
| vitest: | |||
| specifier: ^4.0.16 | |||
| version: 4.0.18(@types/node@12.20.55)(@vitest/browser-playwright@4.0.18)(@vitest/ui@4.0.16)(jiti@2.6.1)(jsdom@27.4.0)(less@4.6.2)(sass-embedded@1.98.0)(sass@1.97.1) | |||
|
|
|||
| angular/dist/catalyst: | |||
There was a problem hiding this comment.
angular/dist/catalyst should not be deleted
core/package.json
Outdated
| "babel-loader": "9.2.1", | ||
| "eslint": "9.39.2", | ||
| "eslint-config-prettier": "9.1.2", | ||
| "eslint-plugin-jsx-a11y": "^6.10.0", |
There was a problem hiding this comment.
we agreed to fix versions for security reasons (same for axe-core)
| <div class={{ 'label-container': true, 'label-hidden': this.labelHidden }}> | ||
| {(this.hasSlottedLabel || this.label) && ( | ||
| <label id={`${this.id}-label`} htmlFor={this.id} part="label" onClick={() => this.doFocus()}> | ||
| <label id={`${this.id}-label`} htmlFor={this.id} part="label"> |
There was a problem hiding this comment.
I thought we don't have a real case for cat-date-inline with shown label, but we do, in search-ui, and by clicking on label the today day receives focus. That changes were intentional and we should not remove focus on click. Let's just disable the eslint rule
| </div> | ||
| <div class={{ 'input-color': this.type === 'color', 'input-container': true }}> | ||
| <div class="input-outer-wrapper"> | ||
| {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions -- click focuses the input, keyboard users can focus it directly */} |
There was a problem hiding this comment.
I have a warning
379:14 warning Unused eslint-disable directive (no problems were reported from 'jsx-a11y/click-events-have-key-events' or 'jsx-a11y/no-static-element-interactions')
| ref={el => (this.trigger = el)} | ||
| id={this.id} | ||
| role="combobox" | ||
| tabIndex={0} |
- Pin exact versions for axe-core and eslint-plugin-jsx-a11y - Restore onClick handler on cat-date-inline label with ESLint disable - Update ESLint disable comment in cat-input for clarity - Regenerate pnpm-lock.yaml
This enables static a11y linting as part of the standard lint workflow.