@ckeditor/ckeditor5-ui 34.1.0 → 35.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/CHANGELOG.md +542 -0
  2. package/LICENSE.md +4 -0
  3. package/lang/contexts.json +1 -1
  4. package/lang/translations/ar.po +24 -24
  5. package/lang/translations/ast.po +4 -4
  6. package/lang/translations/az.po +4 -4
  7. package/lang/translations/bg.po +105 -0
  8. package/lang/translations/bn.po +105 -0
  9. package/lang/translations/ca.po +105 -0
  10. package/lang/translations/cs.po +4 -4
  11. package/lang/translations/da.po +4 -4
  12. package/lang/translations/de-ch.po +4 -4
  13. package/lang/translations/de.po +4 -4
  14. package/lang/translations/el.po +4 -4
  15. package/lang/translations/en-au.po +4 -4
  16. package/lang/translations/en-gb.po +4 -4
  17. package/lang/translations/en.po +4 -4
  18. package/lang/translations/eo.po +4 -4
  19. package/lang/translations/es.po +5 -5
  20. package/lang/translations/et.po +4 -4
  21. package/lang/translations/eu.po +4 -4
  22. package/lang/translations/fa.po +4 -4
  23. package/lang/translations/fi.po +6 -6
  24. package/lang/translations/fr.po +5 -5
  25. package/lang/translations/gl.po +4 -4
  26. package/lang/translations/he.po +19 -19
  27. package/lang/translations/hi.po +4 -4
  28. package/lang/translations/hr.po +4 -4
  29. package/lang/translations/hu.po +4 -4
  30. package/lang/translations/id.po +4 -4
  31. package/lang/translations/it.po +5 -5
  32. package/lang/translations/ja.po +9 -9
  33. package/lang/translations/km.po +4 -4
  34. package/lang/translations/kn.po +4 -4
  35. package/lang/translations/ko.po +4 -4
  36. package/lang/translations/ku.po +4 -4
  37. package/lang/translations/lt.po +8 -8
  38. package/lang/translations/lv.po +4 -4
  39. package/lang/translations/ms.po +105 -0
  40. package/lang/translations/nb.po +4 -4
  41. package/lang/translations/ne.po +4 -4
  42. package/lang/translations/nl.po +4 -4
  43. package/lang/translations/no.po +4 -4
  44. package/lang/translations/pl.po +4 -4
  45. package/lang/translations/pt-br.po +5 -5
  46. package/lang/translations/pt.po +25 -25
  47. package/lang/translations/ro.po +4 -4
  48. package/lang/translations/ru.po +4 -4
  49. package/lang/translations/sk.po +4 -4
  50. package/lang/translations/sl.po +3 -3
  51. package/lang/translations/sq.po +4 -4
  52. package/lang/translations/sr-latn.po +4 -4
  53. package/lang/translations/sr.po +4 -4
  54. package/lang/translations/sv.po +24 -24
  55. package/lang/translations/th.po +10 -10
  56. package/lang/translations/tk.po +4 -4
  57. package/lang/translations/tr.po +4 -4
  58. package/lang/translations/ug.po +4 -4
  59. package/lang/translations/uk.po +4 -4
  60. package/lang/translations/ur.po +22 -22
  61. package/lang/translations/uz.po +4 -4
  62. package/lang/translations/vi.po +4 -4
  63. package/lang/translations/zh-cn.po +4 -4
  64. package/lang/translations/zh.po +4 -4
  65. package/package.json +21 -20
  66. package/src/button/buttonview.js +15 -7
  67. package/src/dropdown/button/splitbuttonview.js +2 -0
  68. package/src/dropdown/dropdownpanelview.js +22 -2
  69. package/src/dropdown/dropdownview.js +10 -1
  70. package/src/dropdown/utils.js +71 -1
  71. package/src/editableui/inline/inlineeditableuiview.js +18 -3
  72. package/src/panel/balloon/balloonpanelview.js +4 -4
@@ -16,17 +16,17 @@ msgstr ""
16
16
  "Language: ur\n"
17
17
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
18
18
 
19
- msgctxt "Title of the CKEditor5 editor."
20
- msgid "Rich Text Editor, %0"
21
- msgstr ""
22
-
23
19
  msgctxt "Title of the CKEditor5 editor."
24
20
  msgid "Rich Text Editor"
25
- msgstr ""
21
+ msgstr "خانۂ ترمیم"
22
+
23
+ msgctxt "Accessible label of the specific editing area belonging to a container with an ARIA application role."
24
+ msgid "Editor editing area: %0"
25
+ msgstr "رقبہ خانۂ ترمیم: 0%"
26
26
 
27
27
  msgctxt "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)"
28
28
  msgid "Edit block"
29
- msgstr ""
29
+ msgstr "خانہ کی تدوین"
30
30
 
31
31
  msgctxt "Label for a button showing the next thing (tab, page, etc.)."
32
32
  msgid "Next"
@@ -38,7 +38,7 @@ msgstr "پچھلا"
38
38
 
39
39
  msgctxt "Label used by assistive technologies describing a generic editor toolbar."
40
40
  msgid "Editor toolbar"
41
- msgstr ""
41
+ msgstr "ایڈیٹر آلہ جات"
42
42
 
43
43
  msgctxt "Label used by assistive technologies describing a toolbar displayed inside a dropdown."
44
44
  msgid "Dropdown toolbar"
@@ -46,60 +46,60 @@ msgstr "آلہ جات برائے فہرست "
46
46
 
47
47
  msgctxt "Label of a button that applies a black color in color pickers."
48
48
  msgid "Black"
49
- msgstr ""
49
+ msgstr "سیاہ"
50
50
 
51
51
  msgctxt "Label of a button that applies a dim grey color in color pickers."
52
52
  msgid "Dim grey"
53
- msgstr ""
53
+ msgstr "پھیکا سرمئی"
54
54
 
55
55
  msgctxt "Label of a button that applies a grey color in color pickers."
56
56
  msgid "Grey"
57
- msgstr ""
57
+ msgstr "سرمئی"
58
58
 
59
59
  msgctxt "Label of a button that applies a light grey color in color pickers."
60
60
  msgid "Light grey"
61
- msgstr ""
61
+ msgstr "ہلکا سرمئی"
62
62
 
63
63
  msgctxt "Label of a button that applies a white color in color pickers."
64
64
  msgid "White"
65
- msgstr ""
65
+ msgstr "سفید"
66
66
 
67
67
  msgctxt "Label of a button that applies a red color in color pickers."
68
68
  msgid "Red"
69
- msgstr ""
69
+ msgstr "سرخ"
70
70
 
71
71
  msgctxt "Label of a button that applies a orange color in color pickers."
72
72
  msgid "Orange"
73
- msgstr ""
73
+ msgstr "نارنجی"
74
74
 
75
75
  msgctxt "Label of a button that applies a yellow color in color pickers."
76
76
  msgid "Yellow"
77
- msgstr ""
77
+ msgstr "پیلا"
78
78
 
79
79
  msgctxt "Label of a button that applies a light green color in color pickers."
80
80
  msgid "Light green"
81
- msgstr ""
81
+ msgstr "ہلکا سبز"
82
82
 
83
83
  msgctxt "Label of a button that applies a green color in color pickers."
84
84
  msgid "Green"
85
- msgstr ""
85
+ msgstr "سبز"
86
86
 
87
87
  msgctxt "Label of a button that applies a aquamarine color in color pickers."
88
88
  msgid "Aquamarine"
89
- msgstr ""
89
+ msgstr "نیلگوں بلور"
90
90
 
91
91
  msgctxt "Label of a button that applies a turquoise color in color pickers."
92
92
  msgid "Turquoise"
93
- msgstr ""
93
+ msgstr "فیروزی"
94
94
 
95
95
  msgctxt "Label of a button that applies a light blue color in color pickers."
96
96
  msgid "Light blue"
97
- msgstr ""
97
+ msgstr "ہلکا نیلا"
98
98
 
99
99
  msgctxt "Label of a button that applies a blue color in color pickers."
100
100
  msgid "Blue"
101
- msgstr ""
101
+ msgstr "نیلا"
102
102
 
103
103
  msgctxt "Label of a button that applies a purple color in color pickers."
104
104
  msgid "Purple"
105
- msgstr ""
105
+ msgstr "ارغوانی"
@@ -16,14 +16,14 @@ msgstr ""
16
16
  "Language: uz\n"
17
17
  "Plural-Forms: nplurals=1; plural=0;\n"
18
18
 
19
- msgctxt "Title of the CKEditor5 editor."
20
- msgid "Rich Text Editor, %0"
21
- msgstr "Tahrirlovchi, %0"
22
-
23
19
  msgctxt "Title of the CKEditor5 editor."
24
20
  msgid "Rich Text Editor"
25
21
  msgstr "Tahrirlovchi"
26
22
 
23
+ msgctxt "Accessible label of the specific editing area belonging to a container with an ARIA application role."
24
+ msgid "Editor editing area: %0"
25
+ msgstr ""
26
+
27
27
  msgctxt "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)"
28
28
  msgid "Edit block"
29
29
  msgstr "Blokni tahrirlash"
@@ -16,14 +16,14 @@ msgstr ""
16
16
  "Language: vi\n"
17
17
  "Plural-Forms: nplurals=1; plural=0;\n"
18
18
 
19
- msgctxt "Title of the CKEditor5 editor."
20
- msgid "Rich Text Editor, %0"
21
- msgstr "Trình soạn thảo văn bản, %0"
22
-
23
19
  msgctxt "Title of the CKEditor5 editor."
24
20
  msgid "Rich Text Editor"
25
21
  msgstr "Trình soạn thảo văn bản"
26
22
 
23
+ msgctxt "Accessible label of the specific editing area belonging to a container with an ARIA application role."
24
+ msgid "Editor editing area: %0"
25
+ msgstr "Vùng chỉnh sửa của trình chỉnh sửa: %0"
26
+
27
27
  msgctxt "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)"
28
28
  msgid "Edit block"
29
29
  msgstr "Chỉnh sửa đoạn"
@@ -16,14 +16,14 @@ msgstr ""
16
16
  "Language: zh_CN\n"
17
17
  "Plural-Forms: nplurals=1; plural=0;\n"
18
18
 
19
- msgctxt "Title of the CKEditor5 editor."
20
- msgid "Rich Text Editor, %0"
21
- msgstr "富文本编辑器, %0"
22
-
23
19
  msgctxt "Title of the CKEditor5 editor."
24
20
  msgid "Rich Text Editor"
25
21
  msgstr "富文本编辑器"
26
22
 
23
+ msgctxt "Accessible label of the specific editing area belonging to a container with an ARIA application role."
24
+ msgid "Editor editing area: %0"
25
+ msgstr "编辑器编辑区域:%0"
26
+
27
27
  msgctxt "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)"
28
28
  msgid "Edit block"
29
29
  msgstr "编辑框"
@@ -16,14 +16,14 @@ msgstr ""
16
16
  "Language: zh_TW\n"
17
17
  "Plural-Forms: nplurals=1; plural=0;\n"
18
18
 
19
- msgctxt "Title of the CKEditor5 editor."
20
- msgid "Rich Text Editor, %0"
21
- msgstr "豐富文字編輯器,%0"
22
-
23
19
  msgctxt "Title of the CKEditor5 editor."
24
20
  msgid "Rich Text Editor"
25
21
  msgstr "豐富文字編輯器"
26
22
 
23
+ msgctxt "Accessible label of the specific editing area belonging to a container with an ARIA application role."
24
+ msgid "Editor editing area: %0"
25
+ msgstr "編輯器編輯區:%0"
26
+
27
27
  msgctxt "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)"
28
28
  msgid "Edit block"
29
29
  msgstr "編輯區塊"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-ui",
3
- "version": "34.1.0",
3
+ "version": "35.0.1",
4
4
  "description": "The UI framework and standard UI library of CKEditor 5.",
5
5
  "keywords": [
6
6
  "ckeditor",
@@ -11,27 +11,27 @@
11
11
  ],
12
12
  "main": "src/index.js",
13
13
  "dependencies": {
14
- "@ckeditor/ckeditor5-utils": "^34.1.0",
15
- "@ckeditor/ckeditor5-core": "^34.1.0",
14
+ "@ckeditor/ckeditor5-utils": "^35.0.1",
15
+ "@ckeditor/ckeditor5-core": "^35.0.1",
16
16
  "lodash-es": "^4.17.15"
17
17
  },
18
18
  "devDependencies": {
19
- "@ckeditor/ckeditor5-basic-styles": "^34.1.0",
20
- "@ckeditor/ckeditor5-block-quote": "^34.1.0",
21
- "@ckeditor/ckeditor5-editor-balloon": "^34.1.0",
22
- "@ckeditor/ckeditor5-editor-classic": "^34.1.0",
23
- "@ckeditor/ckeditor5-engine": "^34.1.0",
24
- "@ckeditor/ckeditor5-enter": "^34.1.0",
25
- "@ckeditor/ckeditor5-essentials": "^34.1.0",
26
- "@ckeditor/ckeditor5-heading": "^34.1.0",
27
- "@ckeditor/ckeditor5-image": "^34.1.0",
28
- "@ckeditor/ckeditor5-link": "^34.1.0",
29
- "@ckeditor/ckeditor5-list": "^34.1.0",
30
- "@ckeditor/ckeditor5-mention": "^34.1.0",
31
- "@ckeditor/ckeditor5-paragraph": "^34.1.0",
32
- "@ckeditor/ckeditor5-horizontal-line": "^34.1.0",
33
- "@ckeditor/ckeditor5-table": "^34.1.0",
34
- "@ckeditor/ckeditor5-typing": "^34.1.0"
19
+ "@ckeditor/ckeditor5-basic-styles": "^35.0.1",
20
+ "@ckeditor/ckeditor5-block-quote": "^35.0.1",
21
+ "@ckeditor/ckeditor5-editor-balloon": "^35.0.1",
22
+ "@ckeditor/ckeditor5-editor-classic": "^35.0.1",
23
+ "@ckeditor/ckeditor5-engine": "^35.0.1",
24
+ "@ckeditor/ckeditor5-enter": "^35.0.1",
25
+ "@ckeditor/ckeditor5-essentials": "^35.0.1",
26
+ "@ckeditor/ckeditor5-heading": "^35.0.1",
27
+ "@ckeditor/ckeditor5-image": "^35.0.1",
28
+ "@ckeditor/ckeditor5-link": "^35.0.1",
29
+ "@ckeditor/ckeditor5-list": "^35.0.1",
30
+ "@ckeditor/ckeditor5-mention": "^35.0.1",
31
+ "@ckeditor/ckeditor5-paragraph": "^35.0.1",
32
+ "@ckeditor/ckeditor5-horizontal-line": "^35.0.1",
33
+ "@ckeditor/ckeditor5-table": "^35.0.1",
34
+ "@ckeditor/ckeditor5-typing": "^35.0.1"
35
35
  },
36
36
  "engines": {
37
37
  "node": ">=14.0.0",
@@ -50,6 +50,7 @@
50
50
  "lang",
51
51
  "src",
52
52
  "theme",
53
- "ckeditor5-metadata.json"
53
+ "ckeditor5-metadata.json",
54
+ "CHANGELOG.md"
54
55
  ]
55
56
  }
@@ -13,6 +13,7 @@ import TooltipView from '../tooltip/tooltipview';
13
13
 
14
14
  import uid from '@ckeditor/ckeditor5-utils/src/uid';
15
15
  import { getEnvKeystrokeText } from '@ckeditor/ckeditor5-utils/src/keyboard';
16
+ import env from '@ckeditor/ckeditor5-utils/src/env';
16
17
 
17
18
  import '../../theme/components/button/button.css';
18
19
 
@@ -127,7 +128,7 @@ export default class ButtonView extends View {
127
128
  this._getTooltipString.bind( this )
128
129
  );
129
130
 
130
- this.setTemplate( {
131
+ const template = {
131
132
  tag: 'button',
132
133
 
133
134
  attributes: {
@@ -145,16 +146,12 @@ export default class ButtonView extends View {
145
146
  tabindex: bind.to( 'tabindex' ),
146
147
  'aria-labelledby': `ck-editor__aria-label_${ ariaLabelUid }`,
147
148
  'aria-disabled': bind.if( 'isEnabled', true, value => !value ),
148
- 'aria-pressed': bind.to( 'isOn', value => this.isToggleable ? String( value ) : false )
149
+ 'aria-pressed': bind.to( 'isOn', value => this.isToggleable ? String( !!value ) : false )
149
150
  },
150
151
 
151
152
  children: this.children,
152
153
 
153
154
  on: {
154
- mousedown: bind.to( evt => {
155
- evt.preventDefault();
156
- } ),
157
-
158
155
  click: bind.to( evt => {
159
156
  // We can't make the button disabled using the disabled attribute, because it won't be focusable.
160
157
  // Though, shouldn't this condition be moved to the button controller?
@@ -167,7 +164,18 @@ export default class ButtonView extends View {
167
164
  }
168
165
  } )
169
166
  }
170
- } );
167
+ };
168
+
169
+ // On Safari we have to force the focus on a button on click as it's the only browser
170
+ // that doesn't do that automatically. See #12115.
171
+ if ( env.isSafari ) {
172
+ template.on.mousedown = bind.to( evt => {
173
+ this.focus();
174
+ evt.preventDefault();
175
+ } );
176
+ }
177
+
178
+ this.setTemplate( template );
171
179
  }
172
180
 
173
181
  /**
@@ -229,6 +229,8 @@ export default class SplitButtonView extends View {
229
229
  } );
230
230
 
231
231
  arrowView.bind( 'isEnabled' ).to( this );
232
+ arrowView.bind( 'label' ).to( this );
233
+ arrowView.bind( 'tooltip' ).to( this );
232
234
 
233
235
  arrowView.delegate( 'execute' ).to( this, 'open' );
234
236
 
@@ -8,6 +8,7 @@
8
8
  */
9
9
 
10
10
  import View from '../view';
11
+ import { logWarning } from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
11
12
 
12
13
  /**
13
14
  * The dropdown panel view class.
@@ -81,13 +82,32 @@ export default class DropdownPanelView extends View {
81
82
  }
82
83
 
83
84
  /**
84
- * Focuses the view element or first item in view collection on opening dropdown's panel.
85
+ * Focuses the first view in the {@link #children} collection.
85
86
  *
86
87
  * See also {@link module:ui/dropdown/dropdownpanelfocusable~DropdownPanelFocusable}.
87
88
  */
88
89
  focus() {
89
90
  if ( this.children.length ) {
90
- this.children.first.focus();
91
+ if ( typeof this.children.first.focus === 'function' ) {
92
+ this.children.first.focus();
93
+ } else {
94
+ /**
95
+ * The child view of a dropdown could not be focused because it is missing the `focus()` method.
96
+ *
97
+ * This warning appears when a dropdown {@link module:ui/dropdown/dropdownview~DropdownView#isOpen gets open} and it
98
+ * attempts to focus the {@link module:ui/dropdown/dropdownpanelview~DropdownPanelView#children first child} of its panel
99
+ * but the child does not implement the
100
+ * {@link module:ui/dropdown/dropdownpanelfocusable~DropdownPanelFocusable focusable interface}.
101
+ *
102
+ * Focusing the content of a dropdown on open greatly improves the accessibility. Please make sure the view instance
103
+ * provides the `focus()` method for the best user experience.
104
+ *
105
+ * @error ui-dropdown-panel-focus-child-missing-focus
106
+ * @param {module:ui/view~View} childView
107
+ * @param {module:ui/dropdown/dropdownpanelview~DropdownPanelView} dropdownPanel
108
+ */
109
+ logWarning( 'ui-dropdown-panel-focus-child-missing-focus', { childView: this.children.first, dropdownPanel: this } );
110
+ }
91
111
  }
92
112
  }
93
113
 
@@ -106,6 +106,10 @@ export default class DropdownView extends View {
106
106
  /**
107
107
  * Controls whether the dropdown view is open, i.e. shows or hides the {@link #panelView panel}.
108
108
  *
109
+ * **Note**: When the dropdown gets open, it will attempt to call `focus()` on the first child of its {@link #panelView}.
110
+ * See {@link module:ui/dropdown/utils~addToolbarToDropdown}, {@link module:ui/dropdown/utils~addListToDropdown}, and
111
+ * {@link module:ui/dropdown/utils~focusChildOnDropdownOpen} to learn more about focus management in dropdowns.
112
+ *
109
113
  * @observable
110
114
  * @member {Boolean} #isOpen
111
115
  */
@@ -248,6 +252,9 @@ export default class DropdownView extends View {
248
252
  // be updated every time the dropdown is open.
249
253
  this.on( 'change:isOpen', () => {
250
254
  if ( !this.isOpen ) {
255
+ // If the dropdown was closed, move the focus back to the button (#12125).
256
+ this.focus();
257
+
251
258
  return;
252
259
  }
253
260
 
@@ -263,6 +270,9 @@ export default class DropdownView extends View {
263
270
  } else {
264
271
  this.panelView.position = this.panelPosition;
265
272
  }
273
+
274
+ // Focus the first item in the dropdown when the dropdown opened
275
+ this.panelView.focus();
266
276
  } );
267
277
 
268
278
  // Listen for keystrokes coming from within #element.
@@ -270,7 +280,6 @@ export default class DropdownView extends View {
270
280
 
271
281
  const closeDropdown = ( data, cancel ) => {
272
282
  if ( this.isOpen ) {
273
- this.buttonView.focus();
274
283
  this.isOpen = false;
275
284
  cancel();
276
285
  }
@@ -19,6 +19,8 @@ import SwitchButtonView from '../button/switchbuttonview';
19
19
 
20
20
  import clickOutsideHandler from '../bindings/clickoutsidehandler';
21
21
 
22
+ import { logWarning } from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
23
+
22
24
  import '../../theme/components/dropdown/toolbardropdown.css';
23
25
  import '../../theme/components/dropdown/listdropdown.css';
24
26
 
@@ -123,12 +125,22 @@ export function createDropdown( locale, ButtonClass = DropdownButtonView ) {
123
125
  * dropdown.render()
124
126
  * document.body.appendChild( dropdown.element );
125
127
  *
128
+ * **Note:** To improve the accessibility, you can tell the dropdown to focus the first active button of the toolbar when the dropdown
129
+ * {@link module:ui/dropdown/dropdownview~DropdownView#isOpen gets open}. See the documentation of `options` to learn more.
130
+ *
126
131
  * See {@link module:ui/dropdown/utils~createDropdown} and {@link module:ui/toolbar/toolbarview~ToolbarView}.
127
132
  *
128
133
  * @param {module:ui/dropdown/dropdownview~DropdownView} dropdownView A dropdown instance to which `ToolbarView` will be added.
129
134
  * @param {Iterable.<module:ui/button/buttonview~ButtonView>} buttons
135
+ * @param {Object} [options]
136
+ * @param {Boolean} [options.enableActiveItemFocusOnDropdownOpen=false] When set `true`, the focus will automatically move to the first
137
+ * active {@link module:ui/toolbar/toolbarview~ToolbarView#items item} of the toolbar upon
138
+ * {@link module:ui/dropdown/dropdownview~DropdownView#isOpen opening} the dropdown. Active items are those with the `isOn` property set
139
+ * `true` (for instance {@link module:ui/button/buttonview~ButtonView buttons}). If no active items is found, the toolbar will be focused
140
+ * as a whole resulting in the focus moving to its first focusable item (default behavior of
141
+ * {@link module:ui/dropdown/dropdownview~DropdownView}).
130
142
  */
131
- export function addToolbarToDropdown( dropdownView, buttons ) {
143
+ export function addToolbarToDropdown( dropdownView, buttons, options = {} ) {
132
144
  const locale = dropdownView.locale;
133
145
  const t = locale.t;
134
146
  const toolbarView = dropdownView.toolbarView = new ToolbarView( locale );
@@ -143,6 +155,11 @@ export function addToolbarToDropdown( dropdownView, buttons ) {
143
155
 
144
156
  buttons.map( view => toolbarView.items.add( view ) );
145
157
 
158
+ if ( options.enableActiveItemFocusOnDropdownOpen ) {
159
+ // Accessibility: Focus the first active button in the toolbar when the dropdown gets open.
160
+ focusChildOnDropdownOpen( dropdownView, () => toolbarView.items.find( item => item.isOn ) );
161
+ }
162
+
146
163
  dropdownView.panelView.children.add( toolbarView );
147
164
  toolbarView.items.delegate( 'execute' ).to( dropdownView );
148
165
  }
@@ -182,6 +199,9 @@ export function addToolbarToDropdown( dropdownView, buttons ) {
182
199
  * The `items` collection passed to this methods controls the presence and attributes of respective
183
200
  * {@link module:ui/list/listitemview~ListItemView list items}.
184
201
  *
202
+ * **Note:** To improve the accessibility, when a list is added to the dropdown using this helper the dropdown will automatically attempt
203
+ * to focus the first active item (a host to a {@link module:ui/button/buttonview~ButtonView} with
204
+ * {@link module:ui/button/buttonview~ButtonView#isOn} set `true`) or the very first item when none are active.
185
205
  *
186
206
  * See {@link module:ui/dropdown/utils~createDropdown} and {@link module:list/list~List}.
187
207
  *
@@ -219,6 +239,56 @@ export function addListToDropdown( dropdownView, items ) {
219
239
  dropdownView.panelView.children.add( listView );
220
240
 
221
241
  listView.items.delegate( 'execute' ).to( dropdownView );
242
+
243
+ // Accessibility: Focus the first active button in the list when the dropdown gets open.
244
+ focusChildOnDropdownOpen( dropdownView, () => listView.items.find( item => {
245
+ if ( item instanceof ListItemView ) {
246
+ return item.children.first.isOn;
247
+ }
248
+
249
+ return false;
250
+ } ) );
251
+ }
252
+
253
+ /**
254
+ * A helper to be used on an existing {@link module:ui/dropdown/dropdownview~DropdownView} that focuses
255
+ * a specific child in DOM when the dropdown {@link module:ui/dropdown/dropdownview~DropdownView#isOpen gets open}.
256
+ *
257
+ * @param {module:ui/dropdown/dropdownview~DropdownView} dropdownView A dropdown instance to which the focus behavior will be added.
258
+ * @param {Function} childSelectorCallback A callback executed when the dropdown gets open. It should return a {@link module:ui/view~View}
259
+ * instance (child of {@link module:ui/dropdown/dropdownview~DropdownView#panelView}) that will get focused or a falsy value.
260
+ * If falsy value is returned, a default behavior of the dropdown will engage focusing the first focusable child in
261
+ * the {@link module:ui/dropdown/dropdownview~DropdownView#panelView}.
262
+ */
263
+ export function focusChildOnDropdownOpen( dropdownView, childSelectorCallback ) {
264
+ dropdownView.on( 'change:isOpen', () => {
265
+ if ( !dropdownView.isOpen ) {
266
+ return;
267
+ }
268
+
269
+ const childToFocus = childSelectorCallback();
270
+
271
+ if ( !childToFocus ) {
272
+ return;
273
+ }
274
+
275
+ if ( typeof childToFocus.focus === 'function' ) {
276
+ childToFocus.focus();
277
+ } else {
278
+ /**
279
+ * The child view of a {@link module:ui/dropdown/dropdownview~DropdownView dropdown} is missing the `focus()` method
280
+ * and could not be focused when the dropdown got {@link module:ui/dropdown/dropdownview~DropdownView#isOpen open}.
281
+ *
282
+ * Making the content of a dropdown focusable in this case greatly improves the accessibility. Please make the view instance
283
+ * implements the {@link module:ui/dropdown/dropdownpanelfocusable~DropdownPanelFocusable focusable interface} for the best user
284
+ * experience.
285
+ *
286
+ * @error ui-dropdown-focus-child-on-open-child-missing-focus
287
+ * @param {module:ui/view~View} view
288
+ */
289
+ logWarning( 'ui-dropdown-focus-child-on-open-child-missing-focus', { view: childToFocus } );
290
+ }
291
+ }, { priority: 'low' } );
222
292
  }
223
293
 
224
294
  // Add a set of default behaviors to dropdown view.
@@ -23,16 +23,32 @@ export default class InlineEditableUIView extends EditableUIView {
23
23
  * @param {HTMLElement} [editableElement] The editable element. If not specified, the
24
24
  * {@link module:ui/editableui/editableuiview~EditableUIView}
25
25
  * will create it. Otherwise, the existing element will be used.
26
+ * @param {Object} [options] Additional configuration of the view.
27
+ * @param {Function} [options.label] A function that gets called with the instance of this view as an argument
28
+ * and should return a string that represents the label of the editable for assistive technologies. If not provided,
29
+ * a default label generator is used.
26
30
  */
27
- constructor( locale, editingView, editableElement ) {
31
+ constructor( locale, editingView, editableElement, options = {} ) {
28
32
  super( locale, editingView, editableElement );
29
33
 
34
+ const t = locale.t;
35
+
30
36
  this.extendTemplate( {
31
37
  attributes: {
32
38
  role: 'textbox',
33
39
  class: 'ck-editor__editable_inline'
34
40
  }
35
41
  } );
42
+
43
+ /**
44
+ * A function that gets called with the instance of this view as an argument and should return a string that
45
+ * represents the label of the editable for assistive technologies.
46
+ *
47
+ * @private
48
+ * @readonly
49
+ * @param {Function}
50
+ */
51
+ this._generateLabel = options.label || ( () => t( 'Editor editing area: %0', this.name ) );
36
52
  }
37
53
 
38
54
  /**
@@ -42,12 +58,11 @@ export default class InlineEditableUIView extends EditableUIView {
42
58
  super.render();
43
59
 
44
60
  const editingView = this._editingView;
45
- const t = this.t;
46
61
 
47
62
  editingView.change( writer => {
48
63
  const viewRoot = editingView.document.getRoot( this.name );
49
64
 
50
- writer.setAttribute( 'aria-label', t( 'Rich Text Editor, %0', this.name ), viewRoot );
65
+ writer.setAttribute( 'aria-label', this._generateLabel( this ), viewRoot );
51
66
  } );
52
67
  }
53
68
  }
@@ -756,14 +756,14 @@ BalloonPanelView._getOptimalPosition = getOptimalPosition;
756
756
  * The name that the position function returns will be reflected in the balloon panel's class that
757
757
  * controls the placement of the "arrow". See {@link #position} to learn more.
758
758
  *
759
- * @member {Object.<String,module:utils/dom/position~positioningFunction>}
759
+ * @member {Object.<String,module:utils/dom/position~PositioningFunction>}
760
760
  * module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions
761
761
  */
762
762
  BalloonPanelView.defaultPositions = generatePositions();
763
763
 
764
764
  /**
765
765
  * Returns available {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView}
766
- * {@link module:utils/dom/position~positioningFunction positioning functions} adjusted by the specific offsets.
766
+ * {@link module:utils/dom/position~PositioningFunction positioning functions} adjusted by the specific offsets.
767
767
  *
768
768
  * @protected
769
769
  * @param {Object} [options] Options to generate positions. If not specified, this helper will simply return
@@ -779,8 +779,8 @@ BalloonPanelView.defaultPositions = generatePositions();
779
779
  * will be used.
780
780
  * @param {Object} [options.config] Additional configuration of the balloon balloon panel view.
781
781
  * Currently only {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView#withArrow} is supported. Learn more
782
- * about {@link module:utils/dom/position~positioningFunction positioning functions}.
783
- * @returns {Object.<String,module:utils/dom/position~positioningFunction>}
782
+ * about {@link module:utils/dom/position~PositioningFunction positioning functions}.
783
+ * @returns {Object.<String,module:utils/dom/position~PositioningFunction>}
784
784
  */
785
785
  export function generatePositions( {
786
786
  horizontalOffset = BalloonPanelView.arrowHorizontalOffset,