Files
marco/.agents/skills/ember-best-practices/rules/a11y-route-announcements.md

3.9 KiB

title, impact, impactDescription, tags
title impact impactDescription tags
Announce Route Transitions to Screen Readers HIGH Critical for screen reader navigation accessibility, a11y, routing, screen-readers

Announce Route Transitions to Screen Readers

Announce page title changes and route transitions to screen readers so users know when navigation has occurred.

Incorrect (no announcements):

// app/router.js
export default class Router extends EmberRouter {
  location = config.locationType;
  rootURL = config.rootURL;
}

Correct (using a11y-announcer library - recommended):

Use the a11y-announcer library for robust route announcements:

ember install @ember-a11y/a11y-announcer
// app/router.js
import EmberRouter from '@ember/routing/router';
import config from './config/environment';

export default class Router extends EmberRouter {
  location = config.locationType;
  rootURL = config.rootURL;
}

Router.map(function () {
  this.route('about');
  this.route('dashboard');
  this.route('posts', function () {
    this.route('post', { path: '/:post_id' });
  });
});

The a11y-announcer library automatically handles route announcements. For custom announcements in your routes:

// app/routes/dashboard.js
import Route from '@ember/routing/route';
import { service } from '@ember/service';

export default class DashboardRoute extends Route {
  @service announcer;

  afterModel() {
    this.announcer.announce('Loaded dashboard with latest data');
  }
}

Alternative: DIY approach with ARIA live regions:

If you prefer not to use a library, you can implement route announcements yourself:

// app/router.js
import EmberRouter from '@ember/routing/router';
import config from './config/environment';

export default class Router extends EmberRouter {
  location = config.locationType;
  rootURL = config.rootURL;
}

Router.map(function () {
  this.route('about');
  this.route('dashboard');
  this.route('posts', function () {
    this.route('post', { path: '/:post_id' });
  });
});
// app/routes/application.js
import Route from '@ember/routing/route';
import { service } from '@ember/service';

export default class ApplicationRoute extends Route {
  @service router;

  constructor() {
    super(...arguments);

    this.router.on('routeDidChange', (transition) => {
      // Update document title
      const title = this.getPageTitle(transition.to);
      document.title = title;

      // Announce to screen readers
      this.announceRouteChange(title);
    });
  }

  getPageTitle(route) {
    // Get title from route metadata or generate it
    return route.metadata?.title || route.name;
  }

  announceRouteChange(title) {
    const announcement = document.getElementById('route-announcement');
    if (announcement) {
      announcement.textContent = `Navigated to ${title}`;
    }
  }
}
// app/routes/application.gjs
<template>
  <div
    id="route-announcement"
    role="status"
    aria-live="polite"
    aria-atomic="true"
    class="sr-only"
  ></div>

  {{outlet}}
</template>
/* app/styles/app.css */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

Alternative: Use ember-page-title with announcements:

ember install ember-page-title
// app/routes/dashboard.gjs
import { pageTitle } from 'ember-page-title';

<template>
  {{pageTitle "Dashboard"}}

  <div class="dashboard">
    {{outlet}}
  </div>
</template>

Route announcements ensure screen reader users know when navigation occurs, improving the overall accessibility experience.

Reference: Ember Accessibility - Page Titles