Skip to content

Commit 6e483d5

Browse files
authoredMar 22, 2025··
feat(vue-a11y): add vue accessibility plugin support (#686)
1 parent ea15e1d commit 6e483d5

File tree

7 files changed

+125
-2
lines changed

7 files changed

+125
-2
lines changed
 

‎README.md

+21
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,27 @@ export default antfu({
540540

541541
As it's in maintenance mode, we only accept bug fixes for Vue 2. It might also be removed in the future when `eslint-plugin-vue` drops support for Vue 2. We recommend upgrading to Vue 3 if possible.
542542

543+
#### Vue Accessibility
544+
545+
To enable Vue accessibility support, you need to explicitly turn it on:
546+
547+
```js
548+
// eslint.config.js
549+
import antfu from '@antfu/eslint-config'
550+
551+
export default antfu({
552+
vue: {
553+
a11y: true
554+
},
555+
})
556+
```
557+
558+
Running `npx eslint` should prompt you to install the required dependencies, otherwise, you can install them manually:
559+
560+
```bash
561+
npm i -D eslint-plugin-vuejs-accessibility
562+
```
563+
543564
### Optional Configs
544565

545566
We provide some optional configs for specific use cases, that we don't include their dependencies by default.

‎eslint.config.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import { antfu } from './src'
44

55
export default antfu(
66
{
7-
vue: true,
7+
vue: {
8+
a11y: true,
9+
},
810
react: true,
911
solid: true,
1012
svelte: true,

‎package.json

+5
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"eslint-plugin-react-refresh": "^0.4.4",
5555
"eslint-plugin-solid": "^0.14.3",
5656
"eslint-plugin-svelte": ">=2.35.1",
57+
"eslint-plugin-vuejs-accessibility": "^2.4.1",
5758
"prettier-plugin-astro": "^0.14.0",
5859
"prettier-plugin-slidev": "^1.0.5",
5960
"svelte-eslint-parser": ">=0.37.0"
@@ -89,6 +90,9 @@
8990
"eslint-plugin-svelte": {
9091
"optional": true
9192
},
93+
"eslint-plugin-vuejs-accessibility": {
94+
"optional": true
95+
},
9296
"prettier-plugin-astro": {
9397
"optional": true
9498
},
@@ -155,6 +159,7 @@
155159
"eslint-plugin-react-refresh": "catalog:peer",
156160
"eslint-plugin-solid": "catalog:peer",
157161
"eslint-plugin-svelte": "catalog:peer",
162+
"eslint-plugin-vuejs-accessibility": "catalog:peer",
158163
"eslint-typegen": "catalog:dev",
159164
"execa": "catalog:dev",
160165
"jiti": "catalog:dev",

‎pnpm-lock.yaml

+49
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎pnpm-workspace.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ catalogs:
3535
eslint-plugin-react-refresh: ^0.4.19
3636
eslint-plugin-solid: ^0.14.5
3737
eslint-plugin-svelte: ^3.3.3
38+
eslint-plugin-vuejs-accessibility: ^2.4.1
3839
prettier-plugin-astro: ^0.14.1
3940
prettier-plugin-slidev: ^1.0.5
4041
svelte: ^5.23.2

‎src/configs/vue.ts

+38-1
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ import type {
99

1010
import { mergeProcessors } from 'eslint-merge-processors'
1111
import { GLOB_VUE } from '../globs'
12-
import { interopDefault } from '../utils'
12+
import { ensurePackages, interopDefault } from '../utils'
1313

1414
export async function vue(
1515
options: OptionsVue & OptionsHasTypeScript & OptionsOverrides & OptionsStylistic & OptionsFiles = {},
1616
): Promise<TypedFlatConfigItem[]> {
1717
const {
18+
a11y = false,
1819
files = [GLOB_VUE],
1920
overrides = {},
2021
stylistic = true,
@@ -29,14 +30,22 @@ export async function vue(
2930
indent = 2,
3031
} = typeof stylistic === 'boolean' ? {} : stylistic
3132

33+
if (a11y) {
34+
await ensurePackages([
35+
'eslint-plugin-vuejs-accessibility',
36+
])
37+
}
38+
3239
const [
3340
pluginVue,
3441
parserVue,
3542
processorVueBlocks,
43+
pluginVueA11y,
3644
] = await Promise.all([
3745
interopDefault(import('eslint-plugin-vue')),
3846
interopDefault(import('vue-eslint-parser')),
3947
interopDefault(import('eslint-processor-vue-blocks')),
48+
...a11y ? [interopDefault(import('eslint-plugin-vuejs-accessibility'))] : [],
4049
] as const)
4150

4251
return [
@@ -64,6 +73,7 @@ export async function vue(
6473
name: 'antfu/vue/setup',
6574
plugins: {
6675
vue: pluginVue,
76+
...a11y ? { 'vue-a11y': pluginVueA11y } : {},
6777
},
6878
},
6979
{
@@ -192,6 +202,33 @@ export async function vue(
192202
}
193203
: {},
194204

205+
...a11y
206+
? {
207+
'vue-a11y/alt-text': 'error',
208+
'vue-a11y/anchor-has-content': 'error',
209+
'vue-a11y/aria-props': 'error',
210+
'vue-a11y/aria-role': 'error',
211+
'vue-a11y/aria-unsupported-elements': 'error',
212+
'vue-a11y/click-events-have-key-events': 'error',
213+
'vue-a11y/form-control-has-label': 'error',
214+
'vue-a11y/heading-has-content': 'error',
215+
'vue-a11y/iframe-has-title': 'error',
216+
'vue-a11y/interactive-supports-focus': 'error',
217+
'vue-a11y/label-has-for': 'error',
218+
'vue-a11y/media-has-caption': 'warn',
219+
'vue-a11y/mouse-events-have-key-events': 'error',
220+
'vue-a11y/no-access-key': 'error',
221+
'vue-a11y/no-aria-hidden-on-focusable': 'error',
222+
'vue-a11y/no-autofocus': 'warn',
223+
'vue-a11y/no-distracting-elements': 'error',
224+
'vue-a11y/no-redundant-roles': 'error',
225+
'vue-a11y/no-role-presentation-on-focusable': 'error',
226+
'vue-a11y/no-static-element-interactions': 'error',
227+
'vue-a11y/role-has-required-aria-props': 'error',
228+
'vue-a11y/tabindex-no-positive': 'warn',
229+
}
230+
: {},
231+
195232
...overrides,
196233
},
197234
},

‎src/types.ts

+8
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ export interface OptionsVue extends OptionsOverrides {
4444
* @default 3
4545
*/
4646
vueVersion?: 2 | 3
47+
48+
/**
49+
* Vue accessibility plugin. Help check a11y issue in `.vue` files upon enabled
50+
*
51+
* @see https://vue-a11y.github.io/eslint-plugin-vuejs-accessibility/
52+
* @default false
53+
*/
54+
a11y?: boolean
4755
}
4856

4957
export type OptionsTypescript =

0 commit comments

Comments
 (0)
Please sign in to comment.