Ver código fonte

Accessibility: Allow inserting emoji via keyboard

Danilo Bargen 6 anos atrás
pai
commit
470e85567a

+ 13 - 6
src/directives/compose_area.ts

@@ -24,7 +24,7 @@ import {LogService} from '../services/log';
 import {ReceiverService} from '../services/receiver';
 import {StringService} from '../services/string';
 import {TimeoutService} from '../services/timeout';
-import {isEmojiInfo} from '../typeguards';
+import {isEmojiInfo, isKeyboardEvent} from '../typeguards';
 
 /**
  * The compose area where messages are written.
@@ -491,6 +491,7 @@ export default [
 
                         // Add event handlers
                         allEmoji.on('click', onEmojiChosen as any);
+                        allEmoji.on('keydown', onEmojiChosen as any);
                         allEmojiTabs.on('keydown', onEmojiTabSelected as any);
 
                         // Focus compose area again
@@ -514,6 +515,7 @@ export default [
 
                     // Remove event handlers
                     allEmoji.off('click', onEmojiChosen as any);
+                    allEmoji.off('keydown', onEmojiChosen as any);
                     allEmojiTabs.off('keydown', onEmojiTabSelected as any);
                 }
 
@@ -533,15 +535,20 @@ export default [
                 }
 
                 // Emoji is chosen
-                function onEmojiChosen(ev: MouseEvent): void {
-                    ev.stopPropagation();
-                    insertSingleEmojiString((ev.target as Element).textContent);
-                    updateView();
+                function onEmojiChosen(ev: MouseEvent | KeyboardEvent): void {
+                    if (ev.type === 'click' || (isKeyboardEvent(ev) && isActionTrigger(ev))) {
+                        ev.stopPropagation();
+                        if (isKeyboardEvent(ev)) {
+                            ev.preventDefault();
+                        }
+                        insertSingleEmojiString((ev.target as Element).textContent);
+                        updateView();
+                    }
                 }
 
                 // Emoji tab is selected
                 function onEmojiTabSelected(ev: KeyboardEvent): void {
-                    if (ev.key === ' ' || ev.key === 'Enter') {
+                    if (isActionTrigger(ev)) {
                         // Warning: Hacky
                         (ev.target as any).parentElement.previousElementSibling.checked = true;
                     }

Diferenças do arquivo suprimidas por serem muito extensas
+ 1130 - 1130
src/partials/emoji-picker.html


+ 7 - 0
src/typeguards.ts

@@ -112,3 +112,10 @@ export function controllerModelHasMembers<T extends threema.BaseReceiver>(
 ): cm is threema.ControllerModel<T> & threema.ControllerModelWithMembers {
     return cm.receiverType === 'group' || cm.receiverType === 'distributionList';
 }
+
+/**
+ * Return whether this event is a keyboard event.
+ */
+export function isKeyboardEvent(ev: Event): ev is KeyboardEvent {
+    return ev.type === 'keydown' || ev.type === 'keypress' || ev.type === 'keyup';
+}

+ 1 - 1
tools/twemoji/generate-emoji-picker.py

@@ -46,7 +46,7 @@ for i, category in enumerate(category_order):
             hex_codepoint = emoji['codepoint'].lower()
         else:
             hex_codepoint = emoji['codepoint_fully_qualified']
-        print('            <span class="em em-{3}-{0}" role="option" data-c="{0}" data-s="{1}" title="{2}">{4}</span>'.format(
+        print('            <span class="em em-{3}-{0}" role="option" tabindex="0" data-c="{0}" data-s="{1}" title="{2}">{4}</span>'.format(
             emoji['codepoint'].lower(),
             emoji['shortname'],
             emoji['name'],

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff