feat(core): added code to handle keyboard inputs (#4006)

Co-authored-by: Alex Yang <himself65@outlook.com>
This commit is contained in:
Priyansh Gupta
2023-08-31 23:45:55 +05:30
committed by GitHub
parent 6be176b4e3
commit 18d5a99af5
4 changed files with 111 additions and 21 deletions

View File

@@ -5,11 +5,10 @@ import {
MenuTrigger,
styled,
} from '@affine/component';
import { LOCALES } from '@affine/i18n';
import { useI18N } from '@affine/i18n';
import { LOCALES, useI18N } from '@affine/i18n';
import { assertExists } from '@blocksuite/global/utils';
import type { ButtonProps } from '@toeverything/components/button';
import type { ReactElement } from 'react';
import { useCallback } from 'react';
import { useCallback, useEffect, useState } from 'react';
export const StyledListItem = styled(MenuItem)(() => ({
height: '38px',
@@ -17,30 +16,78 @@ export const StyledListItem = styled(MenuItem)(() => ({
}));
interface LanguageMenuContentProps {
currentLanguage?: string;
currentLanguage: string;
currentLanguageIndex: number;
}
const LanguageMenuContent = ({ currentLanguage }: LanguageMenuContentProps) => {
const LanguageMenuContent = ({
currentLanguage,
currentLanguageIndex,
}: LanguageMenuContentProps) => {
const i18n = useI18N();
const changeLanguage = useCallback(
(event: string) => {
return i18n.changeLanguage(event);
(targetLanguage: string) => {
console.assert(
LOCALES.some(item => item.tag === targetLanguage),
'targetLanguage should be one of the LOCALES'
);
i18n.changeLanguage(targetLanguage).catch(err => {
console.error('Failed to change language', err);
});
},
[i18n]
);
const [focusedOptionIndex, setFocusedOptionIndex] = useState(
currentLanguageIndex ?? 0
);
const handleKeyDown = useCallback(
(event: KeyboardEvent) => {
switch (event.key) {
case 'ArrowUp':
event.preventDefault();
setFocusedOptionIndex(prevIndex =>
prevIndex > 0 ? prevIndex - 1 : 0
);
break;
case 'ArrowDown':
event.preventDefault();
setFocusedOptionIndex(prevIndex =>
prevIndex < LOCALES.length - 1 ? prevIndex + 1 : LOCALES.length
);
break;
case 'Enter':
if (focusedOptionIndex !== -1) {
const selectedOption = LOCALES[focusedOptionIndex];
changeLanguage(selectedOption.tag);
}
break;
default:
break;
}
},
[changeLanguage, focusedOptionIndex]
);
useEffect(() => {
document.addEventListener('keydown', handleKeyDown);
return () => {
document.removeEventListener('keydown', handleKeyDown);
};
}, [handleKeyDown]);
return (
<>
{LOCALES.map(option => {
{LOCALES.map((option, optionIndex) => {
return (
<StyledListItem
key={option.name}
active={currentLanguage === option.originalName}
active={option.tag === currentLanguage}
userFocused={optionIndex == focusedOptionIndex}
title={option.name}
onClick={() => {
changeLanguage(option.tag).catch(err => {
throw new Error('Failed to change language', err);
});
changeLanguage(option.tag);
}}
>
{option.originalName}
@@ -61,16 +108,19 @@ export const LanguageMenu = ({
}: LanguageMenuProps) => {
const i18n = useI18N();
const currentLanguage = LOCALES.find(item => item.tag === i18n.language);
const currentLanguageIndex = LOCALES.findIndex(
item => item.tag === i18n.language
);
const currentLanguage = LOCALES[currentLanguageIndex];
assertExists(currentLanguage, 'currentLanguage should exist');
return (
<Menu
content={
(
<LanguageMenuContent
currentLanguage={currentLanguage?.originalName}
/>
) as ReactElement
<LanguageMenuContent
currentLanguage={currentLanguage.tag}
currentLanguageIndex={currentLanguageIndex}
/>
}
placement="bottom-end"
trigger="click"
@@ -82,7 +132,7 @@ export const LanguageMenu = ({
style={{ textTransform: 'capitalize' }}
{...triggerProps}
>
{currentLanguage?.originalName}
{currentLanguage.originalName}
</MenuTrigger>
</Menu>
);