diff --git a/application/ui/src/features/dataset/media-preview/primary-toolbar/hotkeys/hotkeys-list.component.tsx b/application/ui/src/features/dataset/media-preview/primary-toolbar/hotkeys/hotkeys-list.component.tsx index 2add36a7a69..132538cf411 100644 --- a/application/ui/src/features/dataset/media-preview/primary-toolbar/hotkeys/hotkeys-list.component.tsx +++ b/application/ui/src/features/dataset/media-preview/primary-toolbar/hotkeys/hotkeys-list.component.tsx @@ -25,7 +25,13 @@ export const HotkeysList = () => { return ( - + + + + {availableTools.map((tool) => ( diff --git a/application/ui/src/features/dataset/media-preview/secondary-toolbar/secondary-toolbar.component.tsx b/application/ui/src/features/dataset/media-preview/secondary-toolbar/secondary-toolbar.component.tsx index e3b66c10643..0805c52d219 100644 --- a/application/ui/src/features/dataset/media-preview/secondary-toolbar/secondary-toolbar.component.tsx +++ b/application/ui/src/features/dataset/media-preview/secondary-toolbar/secondary-toolbar.component.tsx @@ -125,7 +125,7 @@ export const SecondaryToolbar = ({ const isSubmitDisabled = (!canSubmit && !hasSubsetChanged) || isSaving || isLoadingPredictions; useHotkeys( - HOTKEYS.submit, + `${HOTKEYS.submit}, ${HOTKEYS.submitAlternative}`, (event) => { event.preventDefault(); diff --git a/application/ui/src/features/dataset/media-preview/sidebar-items/use-keyboard-navigation.hook.test.tsx b/application/ui/src/features/dataset/media-preview/sidebar-items/use-keyboard-navigation.hook.test.tsx index b3b03ec2eff..934246fb5bc 100644 --- a/application/ui/src/features/dataset/media-preview/sidebar-items/use-keyboard-navigation.hook.test.tsx +++ b/application/ui/src/features/dataset/media-preview/sidebar-items/use-keyboard-navigation.hook.test.tsx @@ -21,12 +21,20 @@ describe('useKeyboardNavigation', () => { it('calls onSelectedMediaItem with previous item on ArrowUp', async () => { const mockedOnSelectedMediaItem = vi.fn(); - render(); + render(); fireEvent.keyDown(screen.getByTestId('target'), { key: 'ArrowUp' }); expect(mockedOnSelectedMediaItem).toHaveBeenCalledWith(items[0]); }); + it('calls onSelectedMediaItem with previous item on ArrowLeft', async () => { + const mockedOnSelectedMediaItem = vi.fn(); + render(); + + fireEvent.keyDown(screen.getByTestId('target'), { key: 'ArrowLeft' }); + expect(mockedOnSelectedMediaItem).toHaveBeenCalledWith(items[0]); + }); + it('calls onSelectedMediaItem with next item on ArrowDown', async () => { const mockedOnSelectedMediaItem = vi.fn(); render(); @@ -35,20 +43,34 @@ describe('useKeyboardNavigation', () => { expect(mockedOnSelectedMediaItem).toHaveBeenCalledWith(items[2]); }); - it('does not go below index 0 on ArrowUp', async () => { + it('calls onSelectedMediaItem with next item on ArrowRight', async () => { + const mockedOnSelectedMediaItem = vi.fn(); + render(); + + fireEvent.keyDown(screen.getByTestId('target'), { key: 'ArrowRight' }); + expect(mockedOnSelectedMediaItem).toHaveBeenCalledWith(items[2]); + }); + + it('does not go below index 0 on ArrowUp or ArrowLeft', async () => { const mockedOnSelectedMediaItem = vi.fn(); render(); fireEvent.keyDown(screen.getByTestId('target'), { key: 'ArrowUp' }); expect(mockedOnSelectedMediaItem).toHaveBeenCalledWith(items[0]); + + fireEvent.keyDown(screen.getByTestId('target'), { key: 'ArrowLeft' }); + expect(mockedOnSelectedMediaItem).toHaveBeenCalledWith(items[0]); }); - it('does not go above last index on ArrowDown', async () => { + it('does not go above last index on ArrowDown or ArrowRight', async () => { const mockedOnSelectedMediaItem = vi.fn(); render(); fireEvent.keyDown(screen.getByTestId('target'), { key: 'ArrowDown' }); expect(mockedOnSelectedMediaItem).toHaveBeenCalledWith(items[2]); + + fireEvent.keyDown(screen.getByTestId('target'), { key: 'ArrowRight' }); + expect(mockedOnSelectedMediaItem).toHaveBeenCalledWith(items[2]); }); it('does not call onSelectedMediaItem for other keys', async () => { diff --git a/application/ui/src/features/dataset/media-preview/sidebar-items/use-keyboard-navigation.hook.tsx b/application/ui/src/features/dataset/media-preview/sidebar-items/use-keyboard-navigation.hook.tsx index ae4a7ba0ecc..f7943a0db75 100644 --- a/application/ui/src/features/dataset/media-preview/sidebar-items/use-keyboard-navigation.hook.tsx +++ b/application/ui/src/features/dataset/media-preview/sidebar-items/use-keyboard-navigation.hook.tsx @@ -20,12 +20,12 @@ export const useKeyboardNavigation = ({ selectedIndex, onSelectedMediaItem, }: UseKeyboardNavigationProps) => { - const getNewIndex = (key: 'ArrowUp' | 'ArrowDown') => { - if (key === 'ArrowUp') { + const getNewIndex = (key: 'ArrowUp' | 'ArrowDown' | 'ArrowLeft' | 'ArrowRight') => { + if (key === 'ArrowUp' || key === 'ArrowLeft') { return Math.max(0, selectedIndex - 1); } - if (key === 'ArrowDown') { + if (key === 'ArrowDown' || key === 'ArrowRight') { return Math.min(items.length - 1, selectedIndex + 1); } @@ -35,7 +35,12 @@ export const useKeyboardNavigation = ({ useEventListener( 'keydown', (event) => { - if (event.key === 'ArrowUp' || event.key === 'ArrowDown') { + if ( + event.key === 'ArrowUp' || + event.key === 'ArrowDown' || + event.key === 'ArrowLeft' || + event.key === 'ArrowRight' + ) { const newIndex = getNewIndex(event.key); items[newIndex] && onSelectedMediaItem(items[newIndex]); diff --git a/application/ui/src/shared/hotkeys-definition.ts b/application/ui/src/shared/hotkeys-definition.ts index a56d07c66f0..3688167dec7 100644 --- a/application/ui/src/shared/hotkeys-definition.ts +++ b/application/ui/src/shared/hotkeys-definition.ts @@ -25,6 +25,7 @@ export const HOTKEYS = { selectAllAnnotations: `${CTRL_OR_COMMAND_KEY}+a`, deselectAllAnnotations: `${CTRL_OR_COMMAND_KEY}+d`, submit: `${CTRL_OR_COMMAND_KEY}+s`, + submitAlternative: 'enter', } as const; const COMMON_HOTKEYS = {