EmojiPicker: Enter adds emoji in keyboard mode, otherwise dismisses
This commit is contained in:
parent
28eaf1689f
commit
9533796c81
9 changed files with 72 additions and 15 deletions
|
@ -33,16 +33,28 @@ export type EmojiPickDataType = {
|
|||
|
||||
export type OwnProps = {
|
||||
readonly i18n: LocalizerType;
|
||||
readonly onPickEmoji: (o: EmojiPickDataType) => unknown;
|
||||
readonly skinTone?: number;
|
||||
readonly onSetSkinTone?: (tone: number) => unknown;
|
||||
readonly recentEmojis?: ReadonlyArray<string>;
|
||||
readonly skinTone?: number;
|
||||
readonly onClickSettings?: () => unknown;
|
||||
readonly onClose?: () => unknown;
|
||||
readonly onPickEmoji: (o: EmojiPickDataType) => unknown;
|
||||
readonly onSetSkinTone?: (tone: number) => unknown;
|
||||
readonly wasInvokedFromKeyboard: boolean;
|
||||
};
|
||||
|
||||
export type Props = OwnProps & Pick<React.HTMLProps<HTMLDivElement>, 'style'>;
|
||||
|
||||
function isEventFromMouse(
|
||||
event:
|
||||
| React.MouseEvent<HTMLButtonElement>
|
||||
| React.KeyboardEvent<HTMLButtonElement>
|
||||
): boolean {
|
||||
return (
|
||||
('clientX' in event && event.clientX !== 0) ||
|
||||
('clientY' in event && event.clientY !== 0)
|
||||
);
|
||||
}
|
||||
|
||||
function focusOnRender(el: HTMLElement | null) {
|
||||
if (el) {
|
||||
el.focus();
|
||||
|
@ -77,11 +89,16 @@ export const EmojiPicker = React.memo(
|
|||
style,
|
||||
onClickSettings,
|
||||
onClose,
|
||||
wasInvokedFromKeyboard,
|
||||
}: Props,
|
||||
ref
|
||||
) => {
|
||||
const isRTL = i18n.getLocaleDirection() === 'rtl';
|
||||
|
||||
const [isUsingKeyboard, setIsUsingKeyboard] = React.useState(
|
||||
wasInvokedFromKeyboard
|
||||
);
|
||||
|
||||
const [firstRecent] = React.useState(recentEmojis);
|
||||
const [selectedCategory, setSelectedCategory] = React.useState<Category>(
|
||||
categories[0]
|
||||
|
@ -97,6 +114,9 @@ export const EmojiPicker = React.memo(
|
|||
| React.MouseEvent<HTMLButtonElement>
|
||||
| React.KeyboardEvent<HTMLButtonElement>
|
||||
) => {
|
||||
if (isEventFromMouse(e)) {
|
||||
setIsUsingKeyboard(false);
|
||||
}
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
|
@ -129,6 +149,9 @@ export const EmojiPicker = React.memo(
|
|||
| React.MouseEvent<HTMLButtonElement>
|
||||
| React.KeyboardEvent<HTMLButtonElement>
|
||||
) => {
|
||||
if (isEventFromMouse(e)) {
|
||||
setIsUsingKeyboard(false);
|
||||
}
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
|
@ -151,24 +174,42 @@ export const EmojiPicker = React.memo(
|
|||
const { shortName } = e.currentTarget.dataset;
|
||||
if ('key' in e) {
|
||||
if (e.key === 'Enter') {
|
||||
if (shortName) {
|
||||
if (shortName && isUsingKeyboard) {
|
||||
onPickEmoji({ skinTone: selectedTone, shortName });
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
} else if (onClose) {
|
||||
onClose();
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
} else if (shortName) {
|
||||
if (isEventFromMouse(e)) {
|
||||
setIsUsingKeyboard(false);
|
||||
}
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
onPickEmoji({ skinTone: selectedTone, shortName });
|
||||
}
|
||||
},
|
||||
[onPickEmoji, selectedTone]
|
||||
[
|
||||
onClose,
|
||||
onPickEmoji,
|
||||
isUsingKeyboard,
|
||||
selectedTone,
|
||||
setIsUsingKeyboard,
|
||||
]
|
||||
);
|
||||
|
||||
// Handle key presses, particularly Escape
|
||||
React.useEffect(() => {
|
||||
const handler = (event: KeyboardEvent) => {
|
||||
if (event.key === 'Tab') {
|
||||
// We do NOT prevent default here to allow Tab to be used normally
|
||||
setIsUsingKeyboard(true);
|
||||
return;
|
||||
}
|
||||
if (event.key === 'Escape') {
|
||||
if (searchMode) {
|
||||
event.preventDefault();
|
||||
|
@ -190,7 +231,6 @@ export const EmojiPicker = React.memo(
|
|||
'ArrowRight',
|
||||
'Enter',
|
||||
'Shift',
|
||||
'Tab',
|
||||
' ', // Space
|
||||
].includes(event.key)
|
||||
) {
|
||||
|
@ -215,7 +255,7 @@ export const EmojiPicker = React.memo(
|
|||
return () => {
|
||||
document.removeEventListener('keydown', handler);
|
||||
};
|
||||
}, [onClose, searchMode, setSearchMode]);
|
||||
}, [onClose, setIsUsingKeyboard, searchMode, setSearchMode]);
|
||||
|
||||
const [, ...renderableCategories] = categories;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue