Browse Source

Improve usability of toggled button labels (#12426)

* feat(a11y) buttons can now have toggled-aware a11y labels
factor2
Emmanuel Pelletier 2 years ago
parent
commit
45b7f53294
No account linked to committer's email address

+ 30
- 11
lang/main.json View File

@@ -1098,11 +1098,20 @@
1098 1098
             "cc": "Toggle subtitles",
1099 1099
             "chat": "Open / Close chat",
1100 1100
             "clap": "Clap",
1101
+            "closeChat": "Close chat",
1102
+            "closeMoreActions": "Close more actions menu",
1103
+            "closeParticipantsPane": "Close participants pane",
1101 1104
             "collapse": "Collapse",
1102 1105
             "document": "Toggle shared document",
1106
+            "documentClose": "Close shared document",
1107
+            "documentOpen": "Open shared document",
1103 1108
             "download": "Download our apps",
1104 1109
             "embedMeeting": "Embed meeting",
1105 1110
             "endConference": "End meeting for all",
1111
+            "enterFullScreen": "View full screen",
1112
+            "enterTileView": "Enter tile view",
1113
+            "exitFullScreen": "Exit full screen",
1114
+            "exitTileView": "Exit tile view",
1106 1115
             "expand": "Expand",
1107 1116
             "feedback": "Leave feedback",
1108 1117
             "fullScreen": "Toggle full screen",
@@ -1111,6 +1120,7 @@
1111 1120
             "hangup": "Leave the meeting",
1112 1121
             "heading": "Toolbar",
1113 1122
             "help": "Help",
1123
+            "hideWhiteboard": "Hide whiteboard",
1114 1124
             "invite": "Invite people",
1115 1125
             "kick": "Kick participant",
1116 1126
             "laugh": "Laugh",
@@ -1120,21 +1130,23 @@
1120 1130
             "lobbyButton": "Enable/disable lobby mode",
1121 1131
             "localRecording": "Toggle local recording controls",
1122 1132
             "lockRoom": "Toggle meeting password",
1133
+            "lowerHand": "Lower your hand",
1123 1134
             "moreActions": "More actions",
1124 1135
             "moreActionsMenu": "More actions menu",
1125 1136
             "moreOptions": "Show more options",
1126
-            "mute": "Mute / Unmute",
1137
+            "mute": "Mute",
1127 1138
             "muteEveryone": "Mute everyone",
1128 1139
             "muteEveryoneElse": "Mute everyone else",
1129 1140
             "muteEveryoneElsesVideoStream": "Stop everyone else's video",
1130 1141
             "muteEveryonesVideoStream": "Stop everyone's video",
1131 1142
             "noiseSuppression": "Noise suppression",
1132
-            "participants": "Participants",
1143
+            "openChat": "Open chat",
1144
+            "participants": "Open participants pane",
1133 1145
             "pip": "Toggle Picture-in-Picture mode",
1134 1146
             "privateMessage": "Send private message",
1135 1147
             "profile": "Edit your profile",
1136
-            "raiseHand": "Raise / Lower your hand",
1137
-            "reactionsMenu": "Open / Close reactions menu",
1148
+            "raiseHand": "Raise your hand",
1149
+            "reactionsMenu": "Reactions menu",
1138 1150
             "recording": "Toggle recording",
1139 1151
             "remoteMute": "Mute participant",
1140 1152
             "remoteVideoMute": "Disable camera of participant",
@@ -1142,20 +1154,24 @@
1142 1154
             "selectBackground": "Select Background",
1143 1155
             "selfView": "Toggle self view",
1144 1156
             "shareRoom": "Invite someone",
1145
-            "shareYourScreen": "Start / Stop sharing your screen",
1157
+            "shareYourScreen": "Start sharing your screen",
1146 1158
             "shareaudio": "Share audio",
1147
-            "sharedvideo": "Toggle video sharing",
1159
+            "sharedvideo": "Share video",
1148 1160
             "shortcuts": "Toggle shortcuts",
1149 1161
             "show": "Show on stage",
1162
+            "showWhiteboard": "Show whiteboard",
1150 1163
             "silence": "Silence",
1151 1164
             "speakerStats": "Toggle participants statistics",
1165
+            "stopScreenSharing": "Stop sharing your screen",
1166
+            "stopSharedVideo": "Stop video",
1152 1167
             "surprised": "Surprised",
1153 1168
             "tileView": "Toggle tile view",
1154 1169
             "toggleCamera": "Toggle camera",
1155 1170
             "toggleFilmstrip": "Toggle filmstrip",
1171
+            "unmute": "Unmute",
1156 1172
             "videoblur": "Toggle video blur",
1157
-            "videomute": "Start / Stop camera",
1158
-            "whiteboard": "Show / Hide whiteboard"
1173
+            "videomute": "Stop camera",
1174
+            "videounmute": "Start camera"
1159 1175
         },
1160 1176
         "addPeople": "Add people to your call",
1161 1177
         "audioOnlyOff": "Disable low bandwidth mode",
@@ -1168,6 +1184,7 @@
1168 1184
         "chat": "Open / Close chat",
1169 1185
         "clap": "Clap",
1170 1186
         "closeChat": "Close chat",
1187
+        "closeParticipantsPane": "Close participants pane",
1171 1188
         "closeReactionsMenu": "Close reactions menu",
1172 1189
         "disableNoiseSuppression": "Disable noise suppression",
1173 1190
         "disableReactionSounds": "You can disable reaction sounds for this meeting",
@@ -1201,7 +1218,7 @@
1201 1218
         "lowerYourHand": "Lower your hand",
1202 1219
         "moreActions": "More actions",
1203 1220
         "moreOptions": "More options",
1204
-        "mute": "Mute / Unmute",
1221
+        "mute": "Mute",
1205 1222
         "muteEveryone": "Mute everyone",
1206 1223
         "muteEveryonesVideo": "Disable everyone's camera",
1207 1224
         "noAudioSignalDesc": "If you did not purposely mute it from system settings or hardware, consider switching the device.",
@@ -1218,7 +1235,7 @@
1218 1235
         "pip": "Enter Picture-in-Picture mode",
1219 1236
         "privateMessage": "Send private message",
1220 1237
         "profile": "Edit your profile",
1221
-        "raiseHand": "Raise / Lower your hand",
1238
+        "raiseHand": "Raise your hand",
1222 1239
         "raiseYourHand": "Raise your hand",
1223 1240
         "reactionBoo": "Send boo reaction",
1224 1241
         "reactionClap": "Send clap reaction",
@@ -1245,8 +1262,10 @@
1245 1262
         "talkWhileMutedPopup": "Trying to speak? You are muted.",
1246 1263
         "tileViewToggle": "Toggle tile view",
1247 1264
         "toggleCamera": "Toggle camera",
1265
+        "unmute": "Unmute",
1248 1266
         "videoSettings": "Video settings",
1249
-        "videomute": "Start / Stop camera"
1267
+        "videomute": "Stop camera",
1268
+        "videounmute": "Start camera"
1250 1269
     },
1251 1270
     "transcribing": {
1252 1271
         "ccButtonTooltip": "Start / Stop subtitles",

+ 45
- 2
react/features/base/toolbox/components/AbstractButton.js View File

@@ -108,10 +108,21 @@ export default class AbstractButton<P: Props, S: *> extends Component<P, S> {
108 108
      * A succinct description of what the button does. Used by accessibility
109 109
      * tools and torture tests.
110 110
      *
111
+     * If `toggledAccessibilityLabel` is defined, this is used only when the
112
+     * button is not toggled on.
113
+     *
111 114
      * @abstract
112 115
      */
113 116
     accessibilityLabel: string;
114 117
 
118
+    /**
119
+     * This is the same as `accessibilityLabel`, replacing it when the button
120
+     * is toggled on.
121
+     *
122
+     * @abstract
123
+     */
124
+    toggledAccessibilityLabel: string;
125
+
115 126
     labelProps: Object;
116 127
 
117 128
     /**
@@ -144,10 +155,22 @@ export default class AbstractButton<P: Props, S: *> extends Component<P, S> {
144 155
     /**
145 156
      * The text to display in the tooltip. Used only on web.
146 157
      *
158
+     * If `toggleTooltip` is defined, this is used only when the button is not
159
+     * toggled on.
160
+     *
147 161
      * @abstract
148 162
      */
149 163
     tooltip: ?string;
150 164
 
165
+    /**
166
+     * The text to display in the tooltip when the button is toggled on.
167
+     *
168
+     * Used only on web.
169
+     *
170
+     * @abstract
171
+     */
172
+    toggledTooltip: ?string;
173
+
151 174
     /**
152 175
      * Initializes a new {@code AbstractButton} instance.
153 176
      *
@@ -221,6 +244,24 @@ export default class AbstractButton<P: Props, S: *> extends Component<P, S> {
221 244
             || this.label;
222 245
     }
223 246
 
247
+    /**
248
+     * Gets the current accessibility label, taking the toggled state into
249
+     * account. If no toggled label is provided, the regular accessibility label
250
+     * will also be used in the toggled state.
251
+     *
252
+     * The accessibility label is not visible in the UI, it is meant to be
253
+     * used by assistive technologies, mainly screen readers.
254
+     *
255
+     * @private
256
+     * @returns {string}
257
+     */
258
+    _getAccessibilityLabel() {
259
+        return (this._isToggled()
260
+            ? this.toggledAccessibilityLabel
261
+            : this.accessibilityLabel
262
+        ) || this.accessibilityLabel;
263
+    }
264
+
224 265
     /**
225 266
      * Gets the current styles, taking the toggled state into account. If no
226 267
      * toggled styles are provided, the regular styles will also be used in the
@@ -257,7 +298,9 @@ export default class AbstractButton<P: Props, S: *> extends Component<P, S> {
257 298
      * @returns {string}
258 299
      */
259 300
     _getTooltip() {
260
-        return this.tooltip || '';
301
+        return (this._isToggled() ? this.toggledTooltip : this.tooltip)
302
+            || this.tooltip
303
+            || '';
261 304
     }
262 305
 
263 306
     /**
@@ -324,7 +367,7 @@ export default class AbstractButton<P: Props, S: *> extends Component<P, S> {
324 367
     render(): React$Node {
325 368
         const props = {
326 369
             ...this.props,
327
-            accessibilityLabel: this.accessibilityLabel,
370
+            accessibilityLabel: this._getAccessibilityLabel(),
328 371
             elementAfter: this._getElementAfter(),
329 372
             icon: this._getIcon(),
330 373
             label: this._getLabel(),

+ 4
- 21
react/features/chat/components/web/ChatButton.js View File

@@ -24,30 +24,13 @@ type Props = AbstractButtonProps & {
24 24
  * Implementation of a button for accessing chat pane.
25 25
  */
26 26
 class ChatButton extends AbstractButton<Props, *> {
27
-    accessibilityLabel = 'toolbar.accessibilityLabel.chat';
27
+    accessibilityLabel = 'toolbar.accessibilityLabel.openChat';
28
+    toggledAccessibilityLabel = 'toolbar.accessibilityLabel.closeChat';
28 29
     icon = IconMessage;
29 30
     label = 'toolbar.openChat';
30 31
     toggledLabel = 'toolbar.closeChat';
31
-
32
-    /**
33
-     * Retrieves tooltip dynamically.
34
-     */
35
-    get tooltip() {
36
-        if (this._isToggled()) {
37
-            return 'toolbar.closeChat';
38
-        }
39
-
40
-        return 'toolbar.openChat';
41
-    }
42
-
43
-    /**
44
-     * Required by linter due to AbstractButton overwritten prop being writable.
45
-     *
46
-     * @param {string} _value - The value.
47
-     */
48
-    set tooltip(_value) {
49
-        // Unused.
50
-    }
32
+    tooltip = 'toolbar.openChat';
33
+    toggledTooltip = 'toolbar.closeChat';
51 34
 
52 35
     /**
53 36
      * Indicates whether this button is in toggled state or not.

+ 4
- 21
react/features/etherpad/components/SharedDocumentButton.web.js View File

@@ -27,30 +27,13 @@ type Props = AbstractButtonProps & {
27 27
  * Implements an {@link AbstractButton} to open the chat screen on mobile.
28 28
  */
29 29
 class SharedDocumentButton extends AbstractButton<Props, *> {
30
-    accessibilityLabel = 'toolbar.accessibilityLabel.document';
30
+    accessibilityLabel = 'toolbar.accessibilityLabel.documentOpen';
31
+    toggledAccessibilityLabel = 'toolbar.accessibilityLabel.documentClose';
31 32
     icon = IconShareDoc;
32 33
     label = 'toolbar.documentOpen';
33 34
     toggledLabel = 'toolbar.documentClose';
34
-
35
-    /**
36
-     * Dynamically retrieves tooltip based on sharing state.
37
-     */
38
-    get tooltip() {
39
-        if (this._isToggled()) {
40
-            return 'toolbar.documentClose';
41
-        }
42
-
43
-        return 'toolbar.documentOpen';
44
-    }
45
-
46
-    /**
47
-     * Required by linter due to AbstractButton overwritten prop being writable.
48
-     *
49
-     * @param {string} _value - The value.
50
-     */
51
-    set tooltip(_value) {
52
-        // Unused.
53
-    }
35
+    tooltip = 'toolbar.documentOpen';
36
+    toggledTooltip = 'toolbar.documentClose';
54 37
 
55 38
     /**
56 39
      * Handles clicking / pressing the button, and opens / closes the appropriate dialog.

+ 2
- 0
react/features/participants-pane/components/web/ParticipantsPaneButton.js View File

@@ -24,9 +24,11 @@ type Props = AbstractButtonProps & {
24 24
  */
25 25
 class ParticipantsPaneButton extends AbstractButton<Props, *> {
26 26
     accessibilityLabel = 'toolbar.accessibilityLabel.participants';
27
+    toggledAccessibilityLabel = 'toolbar.accessibilityLabel.closeParticipantsPane';
27 28
     icon = IconUsers;
28 29
     label = 'toolbar.participants';
29 30
     tooltip = 'toolbar.participants';
31
+    toggledTooltip = 'toolbar.closeParticipantsPane';
30 32
 
31 33
     /**
32 34
      * Indicates whether this button is in toggled state or not.

+ 4
- 17
react/features/reactions/components/web/RaiseHandButton.js View File

@@ -21,25 +21,12 @@ type Props = AbstractButtonProps & {
21 21
  */
22 22
 class RaiseHandButton extends AbstractButton<Props, *> {
23 23
     accessibilityLabel = 'toolbar.accessibilityLabel.raiseHand';
24
+    toggledAccessibilityLabel = 'toolbar.accessibilityLabel.lowerHand';
24 25
     icon = IconRaiseHand;
25 26
     label = 'toolbar.raiseHand';
26
-    toggledLabel = 'toolbar.raiseHand';
27
-
28
-    /**
29
-     * Retrieves tooltip dynamically.
30
-     */
31
-    get tooltip() {
32
-        return 'toolbar.raiseHand';
33
-    }
34
-
35
-    /**
36
-     * Required by linter due to AbstractButton overwritten prop being writable.
37
-     *
38
-     * @param {string} _value - The value.
39
-     */
40
-    set tooltip(_value) {
41
-        // Unused.
42
-    }
27
+    toggledLabel = 'toolbar.lowerYourHand';
28
+    tooltip = 'toolbar.raiseHand';
29
+    toggledTooltip = 'toolbar.lowerYourHand';
43 30
 
44 31
     /**
45 32
      * Indicates whether this button is in toggled state or not.

+ 3
- 20
react/features/shared-video/components/web/SharedVideoButton.js View File

@@ -35,29 +35,12 @@ type Props = AbstractButtonProps & {
35 35
  */
36 36
 class SharedVideoButton extends AbstractButton<Props, *> {
37 37
     accessibilityLabel = 'toolbar.accessibilityLabel.sharedvideo';
38
+    toggledAccessibilityLabel = 'toolbar.accessibilityLabel.stopSharedVideo';
38 39
     icon = IconPlay;
39 40
     label = 'toolbar.sharedvideo';
40 41
     toggledLabel = 'toolbar.stopSharedVideo';
41
-
42
-    /**
43
-     * Dynamically retrieves tooltip based on sharing state.
44
-     */
45
-    get tooltip() {
46
-        if (this._isToggled()) {
47
-            return 'toolbar.stopSharedVideo';
48
-        }
49
-
50
-        return 'toolbar.sharedvideo';
51
-    }
52
-
53
-    /**
54
-     * Required by linter due to AbstractButton overwritten prop being writable.
55
-     *
56
-     * @param {string} _value - The icon value.
57
-     */
58
-    set tooltip(_value) {
59
-        // Unused.
60
-    }
42
+    tooltip = 'toolbar.sharedvideo';
43
+    toggledTooltip = 'toolbar.stopSharedVideo';
61 44
 
62 45
     /**
63 46
      * Handles clicking / pressing the button, and opens a new dialog.

+ 2
- 0
react/features/toolbox/components/AudioMuteButton.js View File

@@ -46,8 +46,10 @@ type Props = AbstractButtonProps & {
46 46
  */
47 47
 class AudioMuteButton extends AbstractAudioMuteButton<Props, *> {
48 48
     accessibilityLabel = 'toolbar.accessibilityLabel.mute';
49
+    toggledAccessibilityLabel = 'toolbar.accessibilityLabel.unmute';
49 50
     label = 'toolbar.mute';
50 51
     tooltip = 'toolbar.mute';
52
+    toggledTooltip = 'toolbar.unmute';
51 53
 
52 54
     /**
53 55
      * Initializes a new {@code AudioMuteButton} instance.

+ 2
- 0
react/features/toolbox/components/VideoMuteButton.js View File

@@ -47,8 +47,10 @@ type Props = AbstractButtonProps & {
47 47
  */
48 48
 class VideoMuteButton extends AbstractVideoMuteButton<Props, *> {
49 49
     accessibilityLabel = 'toolbar.accessibilityLabel.videomute';
50
+    toggledAccessibilityLabel = 'toolbar.accessibilityLabel.videounmute';
50 51
     label = 'toolbar.videomute';
51 52
     tooltip = 'toolbar.videomute';
53
+    toggledTooltip = 'toolbar.videounmute';
52 54
 
53 55
     /**
54 56
      * Initializes a new {@code VideoMuteButton} instance.

+ 4
- 21
react/features/toolbox/components/web/FullscreenButton.js View File

@@ -17,9 +17,12 @@ type Props = AbstractButtonProps & {
17 17
  * Implementation of a button for toggling fullscreen state.
18 18
  */
19 19
 class FullscreenButton extends AbstractButton<Props, *> {
20
-    accessibilityLabel = 'toolbar.accessibilityLabel.fullScreen';
20
+    accessibilityLabel = 'toolbar.accessibilityLabel.enterFullScreen';
21
+    toggledAccessibilityLabel = 'toolbar.accessibilityLabel.exitFullScreen';
21 22
     label = 'toolbar.enterFullScreen';
22 23
     toggledLabel = 'toolbar.exitFullScreen';
24
+    tooltip = 'toolbar.enterFullScreen';
25
+    toggledTooltip = 'toolbar.exitFullScreen';
23 26
 
24 27
     /**
25 28
      * Retrieves icon dynamically.
@@ -41,26 +44,6 @@ class FullscreenButton extends AbstractButton<Props, *> {
41 44
         // Unused.
42 45
     }
43 46
 
44
-    /**
45
-     * Retrieves icon dynamically.
46
-     */
47
-    get tooltip() {
48
-        if (this._isToggled()) {
49
-            return 'toolbar.exitFullScreen';
50
-        }
51
-
52
-        return 'toolbar.enterFullScreen';
53
-    }
54
-
55
-    /**
56
-     * Required by linter due to AbstractButton overwritten prop being writable.
57
-     *
58
-     * @param {string} _value - The value.
59
-     */
60
-    set tooltip(_value) {
61
-        // Unused.
62
-    }
63
-
64 47
     /**
65 48
      * Indicates whether this button is in toggled state or not.
66 49
      *

+ 1
- 16
react/features/toolbox/components/web/HangupToggleButton.tsx View File

@@ -30,24 +30,9 @@ class HangupToggleButton extends AbstractButton<Props, any, any> {
30 30
     label = 'toolbar.hangup';
31 31
     toggledIcon = IconCloseLarge;
32 32
     toggledLabel = 'toolbar.hangup';
33
+    tooltip = 'toolbar.hangup';
33 34
     props: Props;
34 35
 
35
-    /**
36
-     * Retrieves tooltip dynamically.
37
-     */
38
-    get tooltip() {
39
-        return 'toolbar.hangup';
40
-    }
41
-
42
-    /**
43
-     * Required by linter due to AbstractButton overwritten prop being writable.
44
-     *
45
-     * @param {string} _value - The value.
46
-     */
47
-    set tooltip(_value) {
48
-        // Unused.
49
-    }
50
-
51 36
     /**
52 37
      * Indicates whether this button is in toggled state or not.
53 38
      *

+ 2
- 16
react/features/toolbox/components/web/OverflowToggleButton.js View File

@@ -26,25 +26,11 @@ type Props = AbstractButtonProps & {
26 26
  */
27 27
 class OverflowToggleButton extends AbstractButton<Props, *> {
28 28
     accessibilityLabel = 'toolbar.accessibilityLabel.moreActions';
29
+    toggledAccessibilityLabel = 'toolbar.accessibilityLabel.closeMoreActions';
29 30
     icon = IconDotsHorizontal;
30 31
     label = 'toolbar.moreActions';
31 32
     toggledLabel = 'toolbar.moreActions';
32
-
33
-    /**
34
-     * Retrieves tooltip dynamically.
35
-     */
36
-    get tooltip() {
37
-        return 'toolbar.moreActions';
38
-    }
39
-
40
-    /**
41
-     * Required by linter due to AbstractButton overwritten prop being writable.
42
-     *
43
-     * @param {string} _value - The value.
44
-     */
45
-    set tooltip(_value) {
46
-        // Unused.
47
-    }
33
+    tooltip = 'toolbar.moreActions';
48 34
 
49 35
     /**
50 36
      * Indicates whether this button is in toggled state or not.

+ 1
- 1
react/features/toolbox/components/web/ShareDesktopButton.js View File

@@ -31,11 +31,11 @@ type Props = AbstractButtonProps & {
31 31
  */
32 32
 class ShareDesktopButton extends AbstractButton<Props, *> {
33 33
     accessibilityLabel = 'toolbar.accessibilityLabel.shareYourScreen';
34
+    toggledAccessibilityLabel = 'toolbar.accessibilityLabel.stopScreenSharing';
34 35
     label = 'toolbar.startScreenSharing';
35 36
     icon = IconScreenshare;
36 37
     toggledIcon = IconStopScreenshare;
37 38
     toggledLabel = 'toolbar.stopScreenSharing';
38
-    tooltip = 'toolbar.accessibilityLabel.shareYourScreen';
39 39
 
40 40
     /**
41 41
      * Retrieves tooltip dynamically.

+ 2
- 1
react/features/video-layout/components/TileViewButton.js View File

@@ -38,7 +38,8 @@ type Props = AbstractButtonProps & {
38 38
  * @augments AbstractButton
39 39
  */
40 40
 class TileViewButton<P: Props> extends AbstractButton<P, *> {
41
-    accessibilityLabel = 'toolbar.accessibilityLabel.tileView';
41
+    accessibilityLabel = 'toolbar.accessibilityLabel.enterTileView';
42
+    toggledAccessibilityLabel = 'toolbar.accessibilityLabel.exitTileView';
42 43
     icon = IconTileView;
43 44
     label = 'toolbar.enterTileView';
44 45
     toggledLabel = 'toolbar.exitTileView';

+ 2
- 1
react/features/whiteboard/components/web/WhiteboardButton.tsx View File

@@ -27,7 +27,8 @@ type Props = AbstractButtonProps & {
27 27
  * Component that renders a toolbar button for the whiteboard.
28 28
  */
29 29
 class WhiteboardButton extends AbstractButton<Props, any, any> {
30
-    accessibilityLabel = 'toolbar.accessibilityLabel.whiteboard';
30
+    accessibilityLabel = 'toolbar.accessibilityLabel.showWhiteboard';
31
+    toggledAccessibilityLabel = 'toolbar.accessibilityLabel.hideWhiteboard';
31 32
     icon = IconWhiteboard;
32 33
     label = 'toolbar.showWhiteboard';
33 34
     toggledIcon = IconWhiteboardHide;

Loading…
Cancel
Save