Announce Route Transitions to Screen Readers
Incorrect (no announcements):
// app/router.js
export default class Router extends EmberRouter {
location = config.locationType;
rootURL = config.rootURL;
}
পুরো rule · Correct আর ব্যাখ্যা — আগে নিজে লিখুন, তারপর খুলুন
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 ember-a11y-refocus library - recommended):
Use the ember-a11y-refocus library for robust route announcements, route transition focus management, and a bypass block (aka skip link).
pnpm add ember-a11y-refocus
Or with npm:
npm install ember-a11y-refocus
Use the addon by rendering NavigationNarrator in your application layout and ensuring your primary content has id="main".
{{! app/templates/application.hbs }}
<header>
<NavigationNarrator />
{{! other header content }}
</header>
<main id='main'>
{{outlet}}
</main>
If you are using GJS or GTS, import the component directly:
import { NavigationNarrator } from 'ember-a11y-refocus';
<template>
<header>
<NavigationNarrator />
</header>
<main id="main">
{{outlet}}
</main>
</template>
The addon ships minimal styles for the skip link and navigation message:
// app/app.js or app/app.ts
import 'ember-a11y-refocus/styles/navigation-narrator.css';
If you need to customize which transitions count as a route change, pass a validator function to NavigationNarrator:
// app/controllers/application.js
import Controller from '@ember/controller';
import { defaultValidator } from 'ember-a11y-refocus';
export default class ApplicationController extends Controller {
myCustomValidator(transition) {
if (transition.from?.name === 'special') {
return false;
}
return defaultValidator(transition);
}
}
{{! app/templates/application.hbs }}
<header>
<NavigationNarrator @routeChangeValidator={{this.myCustomValidator}} />
</header>
<main id='main'>
{{outlet}}
</main>
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;
}
Route announcements ensure screen reader users know when navigation occurs, improving the overall accessibility experience.
Reference: Ember Accessibility - Page Titles