---
name: angular-accessibility
description: Enforce and improve accessibility (a11y) in Angular applications following WCAG 2.2 AA, ARIA best practices, semantic HTML, and Angular-specific patterns.
---

# Angular Accessibility Skill

## Purpose

This skill helps build and review Angular applications that are accessible by default. It prioritizes semantic HTML, keyboard navigation, screen reader compatibility, color contrast, focus management, and Angular CDK accessibility utilities.

Target standard: **WCAG 2.2 Level AA**

## When to Use

Activate this skill whenever the task involves:

- Creating Angular components
- Reviewing templates for accessibility
- Refactoring UI components
- Building forms
- Navigation menus
- Dialogs and modals
- Tables
- Custom controls
- Angular Material components
- Accessibility audits
- Fixing Lighthouse or axe-core accessibility issues

---

# Accessibility Principles

Always follow this priority order:

1. Semantic HTML
2. Native browser behavior
3. Angular accessibility utilities
4. ARIA only when necessary

**Rule:** Never use ARIA to replace native HTML functionality.

Example:

Good:

```html
<button type="button">Save</button>
```

Avoid:

```html
<div role="button">Save</div>
```

---

# Angular Template Rules

## Buttons

Always:

- use `<button>`
- specify `type`
- provide accessible text

Good:

```html
<button type="submit">Submit</button>
```

Icon button:

```html
<button type="button" aria-label="Close dialog">
  <mat-icon>close</mat-icon>
</button>
```

---

## Links

Use `<a>` only for navigation.

Good:

```html
<a routerLink="/dashboard">Dashboard</a>
```

Avoid:

```html
<a (click)="save()">Save</a>
```

Use a button instead.

---

## Images

Decorative:

```html
<img src="divider.svg" alt="">
```

Informative:

```html
<img src="profile.jpg" alt="Jane Doe smiling">
```

Avoid generic alt text like "image" or "photo."

---

# Forms

## Labels

Every input needs a label.

Good:

```html
<label for="email">Email</label>
<input id="email" type="email">
```

Angular Material:

```html
<mat-form-field>
  <mat-label>Email</mat-label>
  <input matInput type="email">
</mat-form-field>
```

---

## Error Messages

Requirements:

- visible
- descriptive
- associated with the input

Example:

```html
<input
  id="email"
  aria-describedby="email-error">

<div id="email-error">
  Enter a valid email address.
</div>
```

Avoid relying on color alone.

---

## Required Fields

Use both:

```html
<input required aria-required="true">
```

---

# Keyboard Accessibility

Every interactive element must be usable with:

- Tab
- Shift+Tab
- Enter
- Space
- Escape (when applicable)
- Arrow keys (where expected)

Never trap keyboard focus.

---

# Focus Management

Use Angular CDK when possible.

Example:

```typescript
constructor(private focusMonitor: FocusMonitor) {}
```

For dialogs:

- move focus into dialog
- trap focus
- restore focus on close

Angular Material already provides this behavior.

---

# Angular CDK Accessibility

Prefer Angular CDK utilities.

Useful services:

- FocusMonitor
- LiveAnnouncer
- InteractivityChecker
- FocusTrapFactory

Example:

```typescript
this.liveAnnouncer.announce('Settings saved');
```

Use for:

- success messages
- validation updates
- dynamic content

---

# ARIA Usage

Use ARIA only when native HTML cannot express the behavior.

Common attributes:

| Attribute | Use |
|-----------|-----|
| aria-label | Icon buttons |
| aria-labelledby | Existing visible label |
| aria-describedby | Helper/error text |
| aria-expanded | Expandable controls |
| aria-controls | Controlled region |
| aria-live | Dynamic announcements |
| aria-current | Current navigation item |

Avoid redundant ARIA.

Bad:

```html
<button role="button">
```

---

# Navigation

Provide a skip link.

Example:

```html
<a href="#main" class="skip-link">
  Skip to main content
</a>
```

Use landmarks:

```html
<header>
<nav>
<main id="main">
<footer>
```

---

# Tables

Use proper table structure.

Good:

```html
<table>
  <thead>
    <tr>
      <th scope="col">Name</th>
      <th scope="col">Role</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Alice</td>
      <td>Admin</td>
    </tr>
  </tbody>
</table>
```

Avoid tables for layout.

---

# Dialogs

Requirements:

- focus trap
- Escape closes dialog
- initial focus
- restore focus afterward

Angular Material Dialog already supports most of these.

Add:

```html
<h2 mat-dialog-title>
```

for proper dialog labeling.

---

# Custom Components

When creating custom controls:

Implement:

- keyboard interaction
- focus visibility
- accessible name
- appropriate ARIA state

Example checklist:

- [ ] Tab reachable
- [ ] Enter works
- [ ] Space works
- [ ] Focus visible
- [ ] Screen reader announces purpose

---

# Color and Contrast

Minimum ratios:

| Text | Ratio |
|------|-------|
| Normal | 4.5:1 |
| Large | 3:1 |

Never communicate information using color alone.

Instead of:

- Red = error

Use:

- icon
- text
- color

---

# Focus Indicators

Never remove focus outlines unless replacing them.

Good:

```css
:focus-visible {
  outline: 2px solid #005fcc;
  outline-offset: 2px;
}
```

Avoid:

```css
outline: none;
```

---

# Motion

Respect reduced motion.

Example:

```css
@media (prefers-reduced-motion: reduce) {
  * {
    animation: none;
    transition: none;
  }
}
```

---

# Angular Material Guidance

Prefer built-in accessible components.

Good choices:

- MatButton
- MatDialog
- MatMenu
- MatCheckbox
- MatRadio
- MatSelect
- MatSnackBar
- MatTabs

Verify:

- labels
- keyboard support
- announcements

---

# Testing Checklist

Before completing any accessibility task:

## Keyboard

- [ ] Everything reachable with Tab
- [ ] No keyboard traps
- [ ] Enter works
- [ ] Space works
- [ ] Escape works where appropriate

## Screen Reader

- [ ] Controls have accessible names
- [ ] Form fields have labels
- [ ] Errors are announced
- [ ] Dynamic updates are announced

## Visual

- [ ] Contrast passes WCAG
- [ ] Focus visible
- [ ] No color-only communication
- [ ] Text scales properly

---

# Automated Testing

Recommend these tools:

## Angular ESLint

Enable accessibility rules.

## axe-core

Use for automated audits.

Example:

- axe DevTools
- Cypress + axe
- Playwright + axe

## Lighthouse

Run accessibility audits regularly.

Treat Lighthouse as a guide rather than the only authority.

---

# Code Review Rules

Whenever reviewing Angular code:

1. Replace non-semantic elements with semantic HTML.
2. Add missing labels.
3. Improve keyboard support.
4. Remove unnecessary ARIA.
5. Fix focus management.
6. Ensure dynamic updates are announced.
7. Verify Angular Material accessibility.
8. Confirm WCAG 2.2 AA compliance.

Always explain:

- why the issue affects accessibility
- the WCAG principle involved
- the preferred Angular solution
- the corrected code