Vize

Accessibility integrity

Use these rules when a template's roles, focus order, labels, or element relationships disagree. They help review the consistency of markup after adding ARIA roles or changing an interactive component.

For example, role-has-required-aria-props shows which change to make when an assigned role is missing a required property. Compare the examples, use that rule's configuration, then run vp run lint. The complete accessibility guide links the other checks.

Every rule on this page includes its purpose, prerequisites, configuration, and complete Bad/Good examples. Highlighted lines show the changes; copied code keeps the complete source. Each packet states its current support limits.

Rule Examples Purpose
a11y/no-role-presentation-on-focusable Bad · Good Disallow role="presentation" or role="none" on focusable elements
a11y/no-static-element-interactions Bad · Good Disallow event handlers on static elements
a11y/placeholder-label-option Bad · Good Require disabled or hidden on select placeholder option
a11y/role-has-required-aria-props Bad · Good Require ARIA roles to have required properties
a11y/tabindex-no-positive Bad · Good Disallow positive tabindex values
a11y/use-list Bad · Good Suggest using list elements for bullet-like text
vue/use-unique-element-ids Bad · Good Enforce unique element IDs using useId() instead of static literals

All rules · Rule Options · ESLint migration map · Project checks · Attributes across components

a11y/no-role-presentation-on-focusable

Disallow role="presentation" or role="none" on focusable elements

Bad · Good

Default severity: error
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.

Configuration (Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  lint: {
    vize: {
      "preset": "incremental",
      "rules": {
        "a11y/no-role-presentation-on-focusable": "error"
      }
    },
  },
});
vp run lint

Bad

The focusable billing link requests role=presentation, which conflicts with its interactive link role; browsers must ignore that presentation request.

<template>
  <a href="/billing" role="presentation">Billing</a>
</template>

Good

Remove the conflicting presentation request and rely on the native link role and billing destination.

<template>
  <a href="/billing">Billing</a>
</template>

Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.

Implementation · All rules

a11y/no-static-element-interactions

Disallow event handlers on static elements

Bad · Good

Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.

Configuration (Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  lint: {
    vize: {
      "preset": "incremental",
      "rules": {
        "a11y/no-static-element-interactions": "warn"
      }
    },
  },
});
vp run lint

Bad

A static section receives an Enter-key action without an interactive role.

<template>
  <section @keydown.enter="select">Select</section>
</template>

Good

A native button carries the same action with an appropriate interactive element.

<template>
  <button type="button" @keydown.enter="select">Select</button>
</template>

Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.

Implementation · All rules

a11y/placeholder-label-option

Require disabled or hidden on select placeholder option

Bad · Good

Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.

Configuration (Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  lint: {
    vize: {
      "preset": "incremental",
      "rules": {
        "a11y/placeholder-label-option": "warn"
      }
    },
  },
});
vp run lint

Bad

The empty-value prompt remains selectable as if it were a country value.

<template>
  <select v-model="country">
    <option value="">Choose a country</option>
    <option value="jp">Japan</option>
  </select>
</template>

Good

Adding disabled distinguishes the prompt from the selectable Japan option.

<template>
  <select v-model="country">
    <option value="" disabled>Choose a country</option>
    <option value="jp">Japan</option>
  </select>
</template>

Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.

Implementation · All rules

a11y/role-has-required-aria-props

Require ARIA roles to have required properties

Bad · Good

Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.

Configuration (Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  lint: {
    vize: {
      "preset": "incremental",
      "rules": {
        "a11y/role-has-required-aria-props": "warn"
      }
    },
  },
});
vp run lint

Bad

The checkbox role omits aria-checked, which conveys the checkbox state.

<template>
  <span role="checkbox">Receive updates</span>
</template>

Good

aria-checked="false" supplies the state required by the checkbox role.

<template>
  <span role="checkbox" aria-checked="false">Receive updates</span>
</template>

Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.

Implementation · All rules

a11y/tabindex-no-positive

Disallow positive tabindex values

Bad · Good

Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.

Configuration (Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  lint: {
    vize: {
      "preset": "incremental",
      "rules": {
        "a11y/tabindex-no-positive": "warn"
      }
    },
  },
});
vp run lint

Bad

A positive tabindex of 3 creates a custom focus order ahead of ordinary controls.

<template>
  <button tabindex="3">Save</button>
</template>

Good

The button uses its native focus order without a positive tabindex.

<template>
  <button>Save</button>
</template>

Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.

Implementation · All rules

a11y/use-list

Suggest using list elements for bullet-like text

Bad · Good

Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.

Configuration (Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  lint: {
    vize: {
      "preset": "incremental",
      "rules": {
        "a11y/use-list": "warn"
      }
    },
  },
});
vp run lint

Bad

The task items are separate paragraphs with typed dash markers rather than list elements.

<template>
  <p>- First task</p>
  <p>- Second task</p>
</template>

Good

An unordered list and list items express the same tasks with list semantics.

<template>
  <ul>
    <li>First task</li>
    <li>Second task</li>
  </ul>
</template>

Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.

Implementation · All rules

vue/use-unique-element-ids

Enforce unique element IDs using useId() instead of static literals

Bad · Good

Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.

Configuration (Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  lint: {
    vize: {
      "preset": "incremental",
      "rules": {
        "vue/use-unique-element-ids": "warn"
      }
    },
  },
});
vp run lint

Bad

The literal email ID is reused by every instance of this component, which can misdirect its label when several instances are rendered.

<template>
  <label for="email">Email</label>
  <input id="email" />
</template>

Good

useId() produces the instance's emailId; bind the same value to the label's for and the input's id.

<script setup>
import { useId } from "vue";

const emailId = useId();
</script>

<template>
  <label :for="emailId">Email</label>
  <input :id="emailId" />
</template>

Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.

Implementation · All rules