Skip to content

Commit 8b1cd2c

Browse files
authored
Merge pull request #103 from moda20/Improvement/UI-UX-improvements
[MAIN-IMP] UI/UX improvements: Keyboard shortcuts and navigation enhancements
2 parents 2e10445 + 69515f6 commit 8b1cd2c

17 files changed

Lines changed: 311 additions & 106 deletions

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"@radix-ui/react-tooltip": "^1.1.3",
4444
"@reduxjs/toolkit": "^2.0.1",
4545
"@shadcn/ui": "^0.0.4",
46+
"@tanstack/react-hotkeys": "^0.10.0",
4647
"@tanstack/react-query": "^5.90.21",
4748
"@tanstack/react-table": "^8.20.5",
4849
"@tanstack/react-virtual": "^3.13.18",
@@ -54,6 +55,7 @@
5455
"cronstrue": "^2.50.0",
5556
"date-fns": "^4.1.0",
5657
"framer-motion": "^12.16.0",
58+
"fuse.js": "^7.4.0",
5759
"history": "^5.3.0",
5860
"js-cookie": "^3.0.5",
5961
"lucide": "^0.474.0",
@@ -64,7 +66,7 @@
6466
"react-day-picker": "^9.14.0",
6567
"react-dom": "^19.2.4",
6668
"react-hook-form": "^7.53.1",
67-
"react-hotkeys-hook": "^4.6.1",
69+
"react-hotkeys-hook": "^5.3.2",
6870
"react-js-cron": "^5.0.1",
6971
"react-redux": "^9.1.0",
7072
"react-router": "^7.13.1",
@@ -76,6 +78,7 @@
7678
},
7779
"devDependencies": {
7880
"@tanstack/eslint-plugin-query": "^5.91.4",
81+
"@tanstack/react-hotkeys-devtools": "^0.7.0",
7982
"@testing-library/dom": "^10.4.1",
8083
"@testing-library/jest-dom": "^6.9.1",
8184
"@testing-library/react": "^16.3.2",

src/app/dashboard/mainPage.tsx

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,9 @@ import {
2121
routes,
2222
currentRoute,
2323
RouteObject,
24-
config,
25-
setConfigItem,
2624
} from "@/app/reducers/uiReducer"
27-
import { useEffect, useRef, useState } from "react"
28-
import SheetActionDialog from "@/components/sheet-action-dialog"
29-
import { Button } from "@/components/ui/button"
30-
import { CogIcon, DeleteIcon, SaveIcon } from "lucide-react"
31-
import { Label } from "@/components/ui/label"
32-
import { Input } from "@/components/ui/input"
33-
import { PlayIcon } from "@radix-ui/react-icons"
34-
import { toast } from "@/hooks/use-toast"
25+
import { useEffect } from "react"
26+
3527
import DrawerMenuConfigurator from "@/components/custom/DrawerMenuConfigurator"
3628
import SearchBar from "@/components/custom/SearchBar"
3729
import JobsStatusCount from "@/components/custom/dashboard/JobsStatusCount"

src/app/reducers/uiReducer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export interface RouteObject {
1515
url: string
1616
active?: boolean
1717
items?: Array<RouteObject>
18+
parent?: RouteObject
1819
}
1920
export interface UISliceState {
2021
toasts: Array<ToastObject>

src/components/confirmationDialogAction.tsx

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type * as React from "react"
1414
import type { VariantProps } from "class-variance-authority"
1515
import useDialogueManager from "@/hooks/useDialogManager"
1616
import { isValidElement, useCallback, useRef } from "react"
17+
import { useHotkeys } from "react-hotkeys-hook"
1718

1819
export enum ConfirmationDialogActionType {
1920
CONFIRM,
@@ -41,6 +42,19 @@ export default function ConfirmationDialogAction(
4142
const { isDialogOpen, setDialogState } = useDialogueManager()
4243
const cancelButtonRef = useRef<HTMLButtonElement>(null)
4344

45+
useHotkeys("meta+enter", () => {
46+
if (!props.disableConfirm && isDialogOpen) {
47+
handleConfirm()
48+
}
49+
})
50+
51+
const handleConfirm = useCallback(() => {
52+
return props.takeAction(
53+
ConfirmationDialogActionType.CONFIRM,
54+
...(props?.extraTakeActionArgs ?? []),
55+
)
56+
}, [props])
57+
4458
const setDialogStateWithFocus = useCallback(
4559
(open: boolean, onOpenChange?: (open: boolean) => void) => {
4660
setDialogState(open, onOpenChange)
@@ -68,7 +82,7 @@ export default function ConfirmationDialogAction(
6882
e.preventDefault()
6983
setDialogState(false, props.onOpenChange)
7084
}}
71-
className={"text-foreground bg-background"}
85+
className={"text-foreground bg-background border-border border-2"}
7286
>
7387
<AlertDialogHeader>
7488
<AlertDialogTitle>{props.title}</AlertDialogTitle>
@@ -97,18 +111,13 @@ export default function ConfirmationDialogAction(
97111
<AlertDialogAction
98112
ref={cancelButtonRef}
99113
title={props.confirmText ?? "Confirm"}
100-
onClick={() =>
101-
props.takeAction(
102-
ConfirmationDialogActionType.CONFIRM,
103-
...(props?.extraTakeActionArgs ?? []),
104-
)
105-
}
114+
onClick={handleConfirm}
106115
variant={props.confirmVariant}
107116
disabled={props.disableConfirm}
108117
autoFocus={true}
109118
tabIndex={0}
110119
>
111-
{props.confirmText ?? "Confirm"}
120+
{props.confirmText ?? "Confirm"} (⌘↩)
112121
</AlertDialogAction>
113122
</AlertDialogFooter>
114123
</AlertDialogContent>

src/components/custom/DrawerMenuConfigurator.tsx

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,13 @@ import SheetActionDialog from "@/components/sheet-action-dialog"
77
import { config, setConfigItem } from "@/app/reducers/uiReducer"
88
import { toast } from "@/hooks/use-toast"
99
import { useAppDispatch, useAppSelector } from "@/app/hooks"
10-
import { useEffect, useRef, useState } from "react"
10+
import { useCallback, useEffect, useRef, useState } from "react"
1111
import ConfirmationDialogAction, {
1212
ConfirmationDialogActionType,
1313
} from "@/components/confirmationDialogAction"
14-
import { DropdownMenuItem } from "@/components/ui/dropdown-menu"
15-
import { jobActions } from "@/features/jobsTable/interfaces"
1614
import { useHotkeys } from "react-hotkeys-hook"
17-
import HotKeyButton from "@/components/custom/HotKeyButton"
1815
import { verifyUserConnection } from "@/utils/authUtils"
16+
import { ButtonWithTooltip } from "@/components/custom/general/ButtonWithTooltip"
1917

2018
export default function DrawerMenuConfigurator() {
2119
useHotkeys(
@@ -63,6 +61,27 @@ export default function DrawerMenuConfigurator() {
6361
})
6462
sideBarTriggerRef.current.click()
6563
}
64+
const hotKLeySaveTargetRef = useHotkeys<HTMLInputElement>(
65+
["meta+enter"],
66+
() => {
67+
return updateSavedTargets(targetServer)
68+
},
69+
{
70+
enableOnFormTags: true,
71+
enableOnContentEditable: true,
72+
},
73+
)
74+
75+
const handleTargetServerRemoval = useCallback(
76+
(action: ConfirmationDialogActionType, target) => {
77+
if (action === ConfirmationDialogActionType.CANCEL) {
78+
return
79+
}
80+
81+
return removeSavedTarget(target)
82+
},
83+
[savedConfig],
84+
)
6685

6786
return (
6887
<SheetActionDialog
@@ -90,6 +109,7 @@ export default function DrawerMenuConfigurator() {
90109
Current
91110
</Label>
92111
<Input
112+
ref={hotKLeySaveTargetRef}
93113
name={"target"}
94114
placeholder="..."
95115
className="w-6/12"
@@ -121,7 +141,7 @@ export default function DrawerMenuConfigurator() {
121141
savedConfig.savedTargets.map((e, i) => (
122142
<div
123143
className="flex items-center gap-4 justify-between w-full min-w-0 flex-1 overflow-hidden"
124-
key={i}
144+
key={e + i}
125145
>
126146
<div
127147
className={
@@ -146,26 +166,27 @@ export default function DrawerMenuConfigurator() {
146166
}}
147167
title={`Delete Target server : ${e}`}
148168
description={
149-
"This action will delete the target server from your local browser storage. You can add it back again anytime"
169+
"This action will delete the target server from your local browser storage"
150170
}
151-
takeAction={action => {
152-
if (action === ConfirmationDialogActionType.CANCEL) return
153-
removeSavedTarget(e)
154-
}}
171+
extraTakeActionArgs={[e]}
172+
takeAction={handleTargetServerRemoval}
155173
confirmVariant="destructive"
174+
autoFocus={true}
156175
>
157176
<Button variant={"destructive"} size={"icon"}>
158177
<DeleteIcon />
159178
</Button>
160179
</ConfirmationDialogAction>
161-
<HotKeyButton
162-
hotKey={["ctrl+alt+" + (i + 1), "meta+alt+" + (i + 1)]}
180+
<ButtonWithTooltip
181+
tooltipContent={`(⌘⌥${i + 1})`}
182+
keyBinding={["ctrl+alt+" + (i + 1), "meta+alt+" + (i + 1)]}
183+
hideKeyboardShortcut={true}
163184
variant={"default"}
164185
size={"icon"}
165186
onClick={() => setNewTargetServer(e)}
166187
>
167188
<PlayIcon />
168-
</HotKeyButton>
189+
</ButtonWithTooltip>
169190
</div>
170191
</div>
171192
))}

0 commit comments

Comments
 (0)