Skip to content

Commit 91a4772

Browse files
committed
feat: refactor CommandBar to separate backdrop and enhance navigation with keyboard shortcuts
1 parent 69d74b4 commit 91a4772

File tree

6 files changed

+343
-144
lines changed

6 files changed

+343
-144
lines changed

src/Pages/Shared/CommandBar/CommandBar.component.tsx

Lines changed: 7 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,22 @@
1-
import { useEffect, useRef, useState } from 'react'
1+
import { useEffect, useState } from 'react'
22

3-
import {
4-
API_STATUS_CODES,
5-
Backdrop,
6-
getUserPreferences,
7-
KeyboardShortcut,
8-
ResponseType,
9-
SearchBar,
10-
stopPropagation,
11-
useQuery,
12-
useRegisterShortcut,
13-
UseRegisterShortcutProvider,
14-
} from '@devtron-labs/devtron-fe-common-lib'
3+
import { useRegisterShortcut, UseRegisterShortcutProvider } from '@devtron-labs/devtron-fe-common-lib'
154

16-
import CommandGroup from './CommandGroup'
17-
import { NAVIGATION_GROUPS, RECENT_ACTIONS_GROUP, SHORT_CUTS } from './constants'
18-
import { CommandBarGroupType } from './types'
5+
import CommandBarBackdrop from './CommandBarBackdrop'
6+
import { SHORT_CUTS } from './constants'
197

208
import './CommandBar.scss'
219

2210
const CommandBar = () => {
2311
const [showCommandBar, setShowCommandBar] = useState(false)
24-
const [searchText, setSearchText] = useState('')
25-
26-
const { data: recentActionsGroup, isLoading } = useQuery({
27-
queryFn: ({ signal }) =>
28-
getUserPreferences(signal).then((response) => {
29-
const responseData: ResponseType<typeof response> = {
30-
code: API_STATUS_CODES.OK,
31-
status: 'OK',
32-
result: response,
33-
}
34-
return responseData
35-
}),
36-
queryKey: [showCommandBar, 'recentNavigationActions'],
37-
enabled: showCommandBar,
38-
select: ({ result }) =>
39-
result.commandBar.recentNavigationActions.reduce<CommandBarGroupType>((acc, action) => {
40-
const requiredGroup = NAVIGATION_GROUPS.find((group) =>
41-
group.items.some((item) => item.id === action.id),
42-
)
43-
44-
if (requiredGroup) {
45-
const requiredItem = requiredGroup.items.find((item) => item.id === action.id)
46-
if (requiredItem) {
47-
acc.items.push(structuredClone(requiredItem))
48-
}
49-
}
50-
return acc
51-
}, structuredClone(RECENT_ACTIONS_GROUP)),
52-
})
53-
54-
const searchBarRef = useRef<HTMLInputElement>(null)
55-
5612
const { registerShortcut, unregisterShortcut } = useRegisterShortcut()
5713

58-
const handleSearchChange = (value: string) => {
59-
setSearchText(value)
60-
}
61-
62-
const handleClose = () => {
63-
setSearchText('')
64-
setShowCommandBar(false)
65-
}
66-
67-
const handleEscape = () => {
68-
if (searchText) {
69-
handleSearchChange('')
70-
return
71-
}
72-
73-
handleClose()
74-
}
75-
7614
const handleOpen = () => {
7715
setShowCommandBar(true)
7816
}
7917

80-
const focusSearchBar = () => {
81-
if (searchBarRef.current) {
82-
searchBarRef.current.focus()
83-
}
18+
const handleClose = () => {
19+
setShowCommandBar(false)
8420
}
8521

8622
useEffect(() => {
@@ -90,15 +26,8 @@ const CommandBar = () => {
9026
callback: handleOpen,
9127
})
9228

93-
registerShortcut({
94-
keys: SHORT_CUTS.FOCUS_SEARCH_BAR.keys,
95-
description: SHORT_CUTS.FOCUS_SEARCH_BAR.description,
96-
callback: focusSearchBar,
97-
})
98-
9929
return () => {
10030
unregisterShortcut(SHORT_CUTS.OPEN_COMMAND_BAR.keys)
101-
unregisterShortcut(SHORT_CUTS.FOCUS_SEARCH_BAR.keys)
10231
}
10332
}, [])
10433

@@ -108,65 +37,7 @@ const CommandBar = () => {
10837

10938
return (
11039
<UseRegisterShortcutProvider ignoreTags={[]}>
111-
<Backdrop onEscape={handleEscape} onClick={handleClose} deactivateFocusOnEscape={!!searchText}>
112-
<div
113-
onClick={stopPropagation}
114-
className="dc__mxw-800 mxh-450 flexbox-col dc__overflow-auto dc__content-space br-12 bg__modal--primary command-bar__container w-100 h-100"
115-
>
116-
<div className="flexbox-col dc__overflow-auto">
117-
<div className="px-20 py-8">
118-
<SearchBar
119-
inputProps={{
120-
autoFocus: true,
121-
placeholder: 'Search or jump to…',
122-
ref: searchBarRef,
123-
}}
124-
initialSearchText={searchText}
125-
handleSearchChange={handleSearchChange}
126-
noBackgroundAndBorder
127-
/>
128-
</div>
129-
130-
<div
131-
className="flexbox-col dc__overflow-auto border__primary--top pt-8"
132-
role="listbox"
133-
aria-label="Command Menu"
134-
// TODO: aria-activedescendant for the currently focused item
135-
>
136-
<CommandGroup isLoading={isLoading} {...(recentActionsGroup || RECENT_ACTIONS_GROUP)} />
137-
138-
{NAVIGATION_GROUPS.map((group) => (
139-
<CommandGroup key={group.id} {...group} />
140-
))}
141-
</div>
142-
</div>
143-
144-
<div className="flexbox dc__content-space dc__align-items-center px-20 py-12 border__primary--top bg__secondary">
145-
<div className="flexbox dc__gap-20 dc__align-items-center">
146-
<div className="flexbox dc__gap-8 dc__align-items-center">
147-
<KeyboardShortcut keyboardKey="ArrowUp" />
148-
<KeyboardShortcut keyboardKey="ArrowDown" />
149-
<span className="cn-9 fs-12 fw-4 lh-20">to navigate</span>
150-
</div>
151-
152-
<div className="flexbox dc__gap-8 dc__align-items-center">
153-
<KeyboardShortcut keyboardKey="Enter" />
154-
<span className="cn-9 fs-12 fw-4 lh-20">to select</span>
155-
</div>
156-
157-
<div className="flexbox dc__gap-8 dc__align-items-center">
158-
<KeyboardShortcut keyboardKey="Escape" />
159-
<span className="cn-9 fs-12 fw-4 lh-20">to close</span>
160-
</div>
161-
</div>
162-
163-
<div className="flexbox dc__gap-8 dc__align-items-center">
164-
<KeyboardShortcut keyboardKey=">" />
165-
<span className="cn-9 fs-12 fw-4 lh-20">to search actions</span>
166-
</div>
167-
</div>
168-
</div>
169-
</Backdrop>
40+
<CommandBarBackdrop handleClose={handleClose} />
17041
</UseRegisterShortcutProvider>
17142
)
17243
}

src/Pages/Shared/CommandBar/CommandBar.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
&__container {
33
box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.04), 0 2px 8px 0 rgba(0, 0, 0, 0.04), 0 3px 17px 0 rgba(0, 0, 0, 0.04), 0 4px 30px 0 rgba(0, 0, 0, 0.13), 0 8px 48px 0 rgba(0, 0, 0, 0.15);
44

5+
&--selected-item {
6+
background: var(--bg-hover);
7+
}
8+
59
.search-bar {
610
&:focus-within {
711
border: none !important;

0 commit comments

Comments
 (0)