Developing Accessible Vue Applications

Best practices for ensuring Vue applications are accessible to users with disabilities, adhering to WCAG guidelines.

0 likes
10 views

Rule Content

title: Developing Accessible Vue Applications
description: Best practices for ensuring Vue applications are accessible to users with disabilities, adhering to WCAG guidelines.
category: Vue Cursor Rules
rules:
  - id: vue-accessibility-semantic-html
    description: Ensure the use of semantic HTML elements to improve accessibility and assistive technology support.
    severity: error
    pattern: |
      <div\s+.*?\brole\s*=\s*["'](button|link|heading|navigation|main|article|section|footer|header)["'].*?>
    replacement: |
      <\1>
    message: "Replace <div> with the appropriate semantic HTML element: <button>, <a>, <h1>-<h6>, <nav>, <main>, <article>, <section>, <footer>, or <header>."
    example: |
      <div role="button" @click="handleClick">Click Me</div>
    correction: |
      <button @click="handleClick">Click Me</button>

  - id: vue-accessibility-aria-attributes
    description: Ensure appropriate use of ARIA attributes to enhance accessibility.
    severity: warning
    pattern: |
      <(button|a|input|select|textarea)\s+.*?\baria-(label|describedby|hidden|role)\s*=\s*["'].*?["'].*?>
    message: "Verify that ARIA attributes are used correctly and enhance accessibility without redundancy."
    example: |
      <button aria-label="Submit" @click="submitForm">Submit</button>
    correction: |
      <button @click="submitForm">Submit</button>

  - id: vue-accessibility-keyboard-navigation
    description: Ensure all interactive elements are keyboard accessible.
    severity: error
    pattern: |
      <div\s+.*?\btabindex\s*=\s*["']0["'].*?>
    replacement: |
      <button>
    message: "Replace <div> with a semantic <button> element to ensure keyboard accessibility."
    example: |
      <div tabindex="0" @click="toggleModal">Open Modal</div>
    correction: |
      <button @click="toggleModal">Open Modal</button>

  - id: vue-accessibility-color-contrast
    description: Ensure sufficient color contrast between text and background.
    severity: warning
    pattern: |
      color:\s*#([0-9a-fA-F]{6}|[0-9a-fA-F]{3});
      background-color:\s*#([0-9a-fA-F]{6}|[0-9a-fA-F]{3});
    message: "Check that the color contrast ratio between text and background meets WCAG guidelines (minimum 4.5:1 for normal text)."
    example: |
      color: #666;
      background-color: #fff;
    correction: |
      color: #000;
      background-color: #fff;

  - id: vue-accessibility-alt-text
    description: Ensure all images have descriptive alt text.
    severity: error
    pattern: |
      <img\s+.*?\bsrc\s*=\s*["'].*?["'].*?>
    replacement: |
      <img src="..." alt="...">
    message: "Add a descriptive alt attribute to the <img> tag to improve accessibility."
    example: |
      <img src="logo.png">
    correction: |
      <img src="logo.png" alt="Company Logo">

  - id: vue-accessibility-form-labels
    description: Ensure all form inputs have associated labels.
    severity: error
    pattern: |
      <input\s+.*?\btype\s*=\s*["'](text|email|password|number|tel|url)["'].*?>
    replacement: |
      <label for="...">...</label>
      <input id="..." type="...">
    message: "Add a <label> element associated with the <input> to improve accessibility."
    example: |
      <input type="text" id="username">
    correction: |
      <label for="username">Username</label>
      <input type="text" id="username">

  - id: vue-accessibility-focus-management
    description: Ensure proper focus management for dynamic content.
    severity: warning
    pattern: |
      this\.\$refs\.\w+\.focus\(\);
    message: "Verify that focus is managed appropriately when dynamic content is displayed to assist keyboard and screen reader users."
    example: |
      this.$refs.modal.focus();
    correction: |
      this.$nextTick(() => {
        this.$refs.modal.focus();
      });

  - id: vue-accessibility-skip-links
    description: Provide skip links to allow users to bypass repetitive content.
    severity: warning
    pattern: |
      <a\s+.*?\bhref\s*=\s*["']#main-content["'].*?>
    message: "Ensure a skip link is present to allow users to bypass repetitive navigation and go directly to the main content."
    example: |
      <a href="#main-content" class="skip-link">Skip to main content</a>
    correction: |
      <a href="#main-content" class="skip-link">Skip to main content</a>
      <style>
        .skip-link {
          position: absolute;
          top: -40px;
          left: 0;
          background: #000;
          color: #fff;
          padding: 8px;
          z-index: 100;
        }
        .skip-link:focus {
          top: 0;
        }
      </style>

  - id: vue-accessibility-live-regions
    description: Use ARIA live regions to announce dynamic content updates.
    severity: warning
    pattern: |
      <div\s+.*?\brole\s*=\s*["']alert["'].*?>
    message: "Ensure that ARIA live regions are used appropriately to announce dynamic content updates to assistive technologies."
    example: |
      <div role="alert">{{ notification }}</div>
    correction: |
      <div role="alert" aria-live="assertive">{{ notification }}</div>

  - id: vue-accessibility-media-captions
    description: Provide captions for all media content.
    severity: error
    pattern: |
      <video\s+.*?>
    replacement: |
      <video>
        <track kind="captions" src="..." srclang="en" label="English">
      </video>
    message: "Add a <track> element with kind='captions' to provide captions for media content."
    example: |
      <video controls>
        <source src="video.mp4" type="video/mp4">
      </video>
    correction: |
      <video controls>
        <source src="video.mp4" type="video/mp4">
        <track kind="captions" src="captions.vtt" srclang="en" label="English">
      </video>