diff --git a/tdrive/frontend/src/app/atoms/button/button.tsx b/tdrive/frontend/src/app/atoms/button/button.tsx index e789e865d..9a20c5cbb 100644 --- a/tdrive/frontend/src/app/atoms/button/button.tsx +++ b/tdrive/frontend/src/app/atoms/button/button.tsx @@ -1,8 +1,17 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import React from 'react'; +import React, { useEffect } from 'react'; import _ from 'lodash'; - -export type ButtonTheme = 'primary' | 'secondary' | 'danger' | 'default' | 'outline' | 'dark' | 'white' | 'green'; +import { addShortcut, removeShortcut } from 'app/features/global/services/shortcut-service'; + +export type ButtonTheme = + | 'primary' + | 'secondary' + | 'danger' + | 'default' + | 'outline' + | 'dark' + | 'white' + | 'green'; interface ButtonProps extends React.ButtonHTMLAttributes { theme?: ButtonTheme; @@ -12,6 +21,7 @@ interface ButtonProps extends React.ButtonHTMLAttributes { loading?: boolean; disabled?: boolean; children?: React.ReactNode; + shortcut?: string; testClassId?: string; } @@ -43,9 +53,7 @@ export const Button = (props: ButtonProps) => { className = 'text-zinc-300 border-0 bg-zinc-900 hover:bg-zinc-800 hover:text-white active:bg-zinc-900'; - if (props.theme === 'green') - className = - 'text-zinc-300 border-0 bg-green-700'; + if (props.theme === 'green') className = 'text-zinc-300 border-0 bg-green-700'; if (disabled) className += ' opacity-50 pointer-events-none'; @@ -59,10 +67,31 @@ export const Button = (props: ButtonProps) => { else className = className + ' w-9 !p-0 justify-center'; } + useEffect(() => { + const handler = (event?: KeyboardEvent) => { + // Disable default behavior for the shortcut + if (event) { + event.preventDefault(); + event.stopPropagation(); + } + props.onClick && props.onClick({} as any); + }; + + const shortcut = props.shortcut || ''; + + // Add shortcut with default behavior prevention + addShortcut({ + shortcut, + handler: event => { + handler(event as KeyboardEvent); + }, + }); + }, [props.onClick, props.shortcut]); const testId = props.testClassId ? `testid:${props.testClassId}` : ''; return ( ); }; diff --git a/tdrive/frontend/src/app/atoms/modal/index.tsx b/tdrive/frontend/src/app/atoms/modal/index.tsx index 331a27b49..3f7637c5b 100644 --- a/tdrive/frontend/src/app/atoms/modal/index.tsx +++ b/tdrive/frontend/src/app/atoms/modal/index.tsx @@ -4,6 +4,7 @@ import { Fragment, ReactNode, useCallback, useEffect, useState } from 'react'; import { atom, useRecoilState } from 'recoil'; import { DismissIcon } from '../icons-colored'; import { Title } from '../text'; +import { Button } from '@atoms/button/button'; const ModalsCountState = atom({ key: 'ModalsState', @@ -126,13 +127,15 @@ export const Modal = (props: { > {props.closable !== false && (
- +
)} {didOpenOnce && props.children} @@ -177,7 +180,7 @@ export const ModalContent = (props: { } > {props.title} -
+

{props.text || ''}

diff --git a/tdrive/frontend/src/app/features/global/services/shortcut-service.ts b/tdrive/frontend/src/app/features/global/services/shortcut-service.ts index 02811f45d..551acdf65 100644 --- a/tdrive/frontend/src/app/features/global/services/shortcut-service.ts +++ b/tdrive/frontend/src/app/features/global/services/shortcut-service.ts @@ -15,7 +15,26 @@ export const defaultShortcutsMap = { }; export const addShortcut = (shortcut: ShortcutType | ShortcutType[]) => { - return shortcuts.add(shortcut); + return shortcuts.add({ + ...shortcut, + handler: (event: any) => { + const target = event.target as HTMLElement; + if ( + ['input', 'textarea'].includes(target.tagName.toLowerCase()) || + target.isContentEditable + ) { + return; + } else { + if (shortcut instanceof Array) { + shortcut.forEach(s => { + s.handler && s.handler(event); + }); + } else { + shortcut.handler && shortcut.handler(event); + } + } + }, + }); }; export const removeShortcut = (shortcut: ShortcutType | ShortcutType[]) => { diff --git a/tdrive/frontend/src/app/views/client/body/drive/modals/create/index.tsx b/tdrive/frontend/src/app/views/client/body/drive/modals/create/index.tsx index 8a0ba8a1f..e815d712e 100644 --- a/tdrive/frontend/src/app/views/client/body/drive/modals/create/index.tsx +++ b/tdrive/frontend/src/app/views/client/body/drive/modals/create/index.tsx @@ -171,12 +171,21 @@ export const CreateModal = ({ }; const CreateModalOption = (props: { testClassId?: string; icon: ReactNode; text: string; onClick: () => void }) => { + // on press enter + const handleKeyPress = (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + props.onClick(); + } + }; + const testId = props.testClassId ? `testid:${props.testClassId}` : ''; return (
{props.icon}
diff --git a/tdrive/frontend/src/app/views/client/body/drive/modals/upload/index.tsx b/tdrive/frontend/src/app/views/client/body/drive/modals/upload/index.tsx index fec229a9e..88a109261 100644 --- a/tdrive/frontend/src/app/views/client/body/drive/modals/upload/index.tsx +++ b/tdrive/frontend/src/app/views/client/body/drive/modals/upload/index.tsx @@ -90,11 +90,25 @@ export const UploadModal = ({ ); }; -const CreateModalOption = (props: { icon: ReactNode; text: string; onClick: () => void; testClassId?: string; }) => { +const CreateModalOption = (props: { + icon: ReactNode; + text: string; + onClick: () => void; + testClassId?: string; +}) => { + // on press enter + const handleKeyPress = (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + props.onClick(); + } + }; + return (
{props.icon}
diff --git a/tdrive/frontend/src/app/views/client/side-bar/actions.tsx b/tdrive/frontend/src/app/views/client/side-bar/actions.tsx index 3fe3e4605..13649b40c 100644 --- a/tdrive/frontend/src/app/views/client/side-bar/actions.tsx +++ b/tdrive/frontend/src/app/views/client/side-bar/actions.tsx @@ -166,6 +166,7 @@ export default () => {