Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.

Commit bdede90

Browse files
authored
Merge pull request #500 from ckeditor/t/ckeditor5/1404
Fix: All editor toolbars should come with the `role` and `aria-label` attributes. Closes ckeditor/ckeditor5#1404. BREAKING CHANGE: The `ToolbarView` class requires the [editor locale](https://ckeditor.com/docs/ckeditor5/latest/api/module_utils_locale-Locale.html) to be passed into the constructor.
2 parents 3903679 + 9ce9e3c commit bdede90

File tree

7 files changed

+78
-10
lines changed

7 files changed

+78
-10
lines changed

lang/contexts.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,7 @@
44
"Edit block": "Label of the block toolbar icon (a block toolbar is displayed next to each paragraph, heading, list item, etc. and contains e.g. block formatting options)",
55
"Next": "Label for a button showing the next thing (tab, page, etc.).",
66
"Previous": "Label for a button showing the previous thing (tab, page, etc.).",
7-
"%0 of %1": "Label for a 'page X of Y' status of a typical next/previous page navigation."
7+
"%0 of %1": "Label for a 'page X of Y' status of a typical next/previous page navigation.",
8+
"Editor toolbar": "Label used by assistive technologies describing a generic editor toolbar.",
9+
"Dropdown toolbar": "Label used by assistive technologies describing a toolbar displayed inside a dropdown."
810
}

src/dropdown/utils.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,11 @@ export function createDropdown( locale, ButtonClass = DropdownButtonView ) {
129129
* @param {Iterable.<module:ui/button/buttonview~ButtonView>} buttons
130130
*/
131131
export function addToolbarToDropdown( dropdownView, buttons ) {
132-
const toolbarView = dropdownView.toolbarView = new ToolbarView();
132+
const locale = dropdownView.locale;
133+
const t = locale.t;
134+
const toolbarView = dropdownView.toolbarView = new ToolbarView( locale );
135+
136+
toolbarView.set( 'ariaLabel', t( 'Dropdown toolbar' ) );
133137

134138
dropdownView.extendTemplate( {
135139
attributes: {

src/toolbar/toolbarview.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,25 @@ import { attachLinkToDocumentation } from '@ckeditor/ckeditor5-utils/src/ckedito
2727
*/
2828
export default class ToolbarView extends View {
2929
/**
30-
* @inheritDoc
30+
* Creates an instance of the {@link module:ui/toolbar/toolbarview~ToolbarView} class.
31+
*
32+
* Also see {@link #render}.
33+
*
34+
* @param {module:utils/locale~Locale} locale The localization services instance.
3135
*/
3236
constructor( locale ) {
3337
super( locale );
3438

3539
const bind = this.bindTemplate;
40+
const t = this.t;
41+
42+
/**
43+
* Label used by assistive technologies to describe this toolbar element.
44+
*
45+
* @default 'Editor toolbar'
46+
* @member {String} #ariaLabel
47+
*/
48+
this.set( 'ariaLabel', t( 'Editor toolbar' ) );
3649

3750
/**
3851
* Collection of the toolbar items (like buttons).
@@ -102,7 +115,9 @@ export default class ToolbarView extends View {
102115
'ck-toolbar',
103116
bind.if( 'isVertical', 'ck-toolbar_vertical' ),
104117
bind.to( 'class' )
105-
]
118+
],
119+
role: 'toolbar',
120+
'aria-label': bind.to( 'ariaLabel' )
106121
},
107122

108123
children: this.items,

tests/dropdown/manual/dropdown.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ function testLongLabel() {
9393
}
9494

9595
function testToolbar() {
96-
const locale = {};
96+
const locale = { t: langString => langString };
9797

9898
const icons = { left: alignLeftIcon, right: alignRightIcon, center: alignCenterIcon };
9999

tests/dropdown/utils.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ describe( 'utils', () => {
2727
let locale, dropdownView;
2828

2929
beforeEach( () => {
30-
locale = { t() {} };
30+
locale = { t: langString => langString };
3131
} );
3232

3333
describe( 'createDropdown()', () => {
@@ -272,6 +272,10 @@ describe( 'utils', () => {
272272
expect( dropdownView.element.classList.contains( 'ck-toolbar-dropdown' ) ).to.be.true;
273273
} );
274274

275+
it( 'sets aria-label', () => {
276+
expect( dropdownView.toolbarView.element.getAttribute( 'aria-label' ) ).to.equal( 'Dropdown toolbar' );
277+
} );
278+
275279
describe( 'view#toolbarView', () => {
276280
it( 'is created', () => {
277281
const panelChildren = dropdownView.panelView.children;

tests/toolbar/enabletoolbarkeyboardfocus.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ describe( 'enableToolbarKeyboardFocus()', () => {
1919
origin = viewCreator();
2020
originFocusTracker = new FocusTracker();
2121
originKeystrokeHandler = new KeystrokeHandler();
22-
toolbar = new ToolbarView();
22+
toolbar = new ToolbarView( { t: langString => langString } );
2323

2424
toolbar.render();
2525

@@ -93,7 +93,7 @@ describe( 'enableToolbarKeyboardFocus()', () => {
9393
origin = viewCreator();
9494
originFocusTracker = new FocusTracker();
9595
originKeystrokeHandler = new KeystrokeHandler();
96-
toolbar = new ToolbarView();
96+
toolbar = new ToolbarView( { t: langString => langString } );
9797

9898
const toolbarFocusSpy = sinon.spy( toolbar, 'focus' );
9999
const originFocusSpy = origin.focus = sinon.spy();

tests/toolbar/toolbarview.js

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,30 @@ import FocusCycler from '../../src/focuscycler';
1414
import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';
1515
import ViewCollection from '../../src/viewcollection';
1616
import View from '../../src/view';
17+
import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
18+
import { add as addTranslations, _clear as clearTranslations } from '@ckeditor/ckeditor5-utils/src/translation-service';
19+
import Locale from '@ckeditor/ckeditor5-utils/src/locale';
1720

1821
describe( 'ToolbarView', () => {
1922
let locale, view;
2023

24+
testUtils.createSinonSandbox();
25+
26+
before( () => {
27+
addTranslations( 'pl', {
28+
'Editor toolbar': 'Pasek narzędzi edytora'
29+
} );
30+
addTranslations( 'en', {
31+
'Editor toolbar': 'Editor toolbar'
32+
} );
33+
} );
34+
35+
after( () => {
36+
clearTranslations();
37+
} );
38+
2139
beforeEach( () => {
22-
locale = {};
40+
locale = new Locale( 'en' );
2341
view = new ToolbarView( locale );
2442
view.render();
2543
} );
@@ -61,6 +79,31 @@ describe( 'ToolbarView', () => {
6179
expect( view.element.classList.contains( 'ck-toolbar' ) ).to.true;
6280
} );
6381

82+
describe( 'attributes', () => {
83+
it( 'should be defined', () => {
84+
expect( view.element.getAttribute( 'role' ) ).to.equal( 'toolbar' );
85+
expect( view.element.getAttribute( 'aria-label' ) ).to.equal( 'Editor toolbar' );
86+
} );
87+
88+
it( 'should allow a custom aria-label', () => {
89+
const view = new ToolbarView( locale );
90+
91+
view.ariaLabel = 'Custom label';
92+
93+
view.render();
94+
95+
expect( view.element.getAttribute( 'aria-label' ) ).to.equal( 'Custom label' );
96+
} );
97+
98+
it( 'should allow the aria-label to be translated', () => {
99+
const view = new ToolbarView( new Locale( 'pl' ) );
100+
101+
view.render();
102+
103+
expect( view.element.getAttribute( 'aria-label' ) ).to.equal( 'Pasek narzędzi edytora' );
104+
} );
105+
} );
106+
64107
describe( 'event listeners', () => {
65108
it( 'prevent default on #mousedown', () => {
66109
const evt = new Event( 'mousedown', { bubbles: true } );
@@ -116,7 +159,7 @@ describe( 'ToolbarView', () => {
116159
} );
117160

118161
it( 'starts listening for #keystrokes coming from #element', () => {
119-
const view = new ToolbarView();
162+
const view = new ToolbarView( new Locale( 'en' ) );
120163
const spy = sinon.spy( view.keystrokes, 'listenTo' );
121164

122165
view.render();

0 commit comments

Comments
 (0)