-
Notifications
You must be signed in to change notification settings - Fork 901
ui(desktop): new button with shortcuts option #460
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d1c87a8
88a42c6
d40d9b0
60f538b
9a4fd5d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,4 +1,4 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Fragment, useEffect, useRef, useState } from "react"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Fragment, useCallback, useEffect, useRef, useState } from "react"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useHotkeys } from "react-hotkeys-hook"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { trpc } from "renderer/lib/trpc"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -16,7 +16,7 @@ import { WorkspaceGroup } from "./WorkspaceGroup"; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const MIN_WORKSPACE_WIDTH = 60; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const MAX_WORKSPACE_WIDTH = 160; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const ADD_BUTTON_WIDTH = 48; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const ADD_BUTTON_WIDTH = 40; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export function WorkspacesTabs() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { data: groups = [] } = trpc.workspaces.getAllGrouped.useQuery(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -74,7 +74,7 @@ export function WorkspacesTabs() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Only create one at a time | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, [groups, isCreating, createBranchWorkspace.mutate]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, [groups, isCreating, createBranchWorkspace]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Flatten workspaces for keyboard navigation | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const allWorkspaces = groups.flatMap((group) => group.workspaces); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -84,9 +84,9 @@ export function WorkspacesTabs() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { length: 9 }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (_, i) => `meta+${i + 1}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ).join(", "); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| useHotkeys( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| workspaceKeys, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (event) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const handleWorkspaceSwitch = useCallback( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (event: KeyboardEvent) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const num = Number(event.key); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (num >= 1 && num <= 9) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const workspace = allWorkspaces[num - 1]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -98,8 +98,7 @@ export function WorkspacesTabs() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [allWorkspaces, setActiveWorkspace], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Navigate to previous workspace (⌘+←) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| useHotkeys(HOTKEYS.PREV_WORKSPACE.keys, () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const handlePrevWorkspace = useCallback(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!activeWorkspaceId) return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const currentIndex = allWorkspaces.findIndex( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (w) => w.id === activeWorkspaceId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -109,8 +108,7 @@ export function WorkspacesTabs() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, [activeWorkspaceId, allWorkspaces, setActiveWorkspace]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Navigate to next workspace (⌘+→) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| useHotkeys(HOTKEYS.NEXT_WORKSPACE.keys, () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const handleNextWorkspace = useCallback(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!activeWorkspaceId) return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const currentIndex = allWorkspaces.findIndex( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (w) => w.id === activeWorkspaceId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -120,6 +118,10 @@ export function WorkspacesTabs() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, [activeWorkspaceId, allWorkspaces, setActiveWorkspace]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| useHotkeys(workspaceKeys, handleWorkspaceSwitch); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| useHotkeys(HOTKEYS.PREV_WORKSPACE.keys, handlePrevWorkspace); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| useHotkeys(HOTKEYS.NEXT_WORKSPACE.keys, handleNextWorkspace); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const checkScroll = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!scrollRef.current) return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -163,58 +165,59 @@ export function WorkspacesTabs() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div ref={containerRef} className="flex items-center h-full w-full"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="flex items-center h-full min-w-0"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="relative h-full overflow-hidden min-w-0"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ref={scrollRef} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className="flex h-full overflow-x-auto hide-scrollbar gap-4" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {groups.map((group, groupIndex) => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Fragment key={group.project.id}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <WorkspaceGroup | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| projectId={group.project.id} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| projectName={group.project.name} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| projectColor={group.project.color} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| projectIndex={groupIndex} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| workspaces={group.workspaces} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| activeWorkspaceId={ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isSettingsActive ? null : activeWorkspaceId | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| workspaceWidth={workspaceWidth} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hoveredWorkspaceId={hoveredWorkspaceId} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onWorkspaceHover={setHoveredWorkspaceId} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {groupIndex < groups.length - 1 && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="flex items-center h-full py-2"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="w-px h-full bg-border" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Fragment> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ))} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {isSettingsTabOpen && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {groups.length > 0 && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="flex items-center h-full py-2"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="w-px h-full bg-border" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <SettingsTab | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| width={workspaceWidth} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isActive={isSettingsActive} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {/* Fade effects for scroll indication */} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {showStartFade && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="pointer-events-none absolute left-0 top-0 h-full w-8 bg-linear-to-r from-background to-transparent" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="relative h-full overflow-hidden min-w-0 flex-1"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ref={scrollRef} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className="flex h-full overflow-x-auto hide-scrollbar gap-4 pr-10" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {groups.map((group, groupIndex) => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Fragment key={group.project.id}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <WorkspaceGroup | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| projectId={group.project.id} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| projectName={group.project.name} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| projectColor={group.project.color} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| projectIndex={groupIndex} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| workspaces={group.workspaces} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| activeWorkspaceId={isSettingsActive ? null : activeWorkspaceId} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| workspaceWidth={workspaceWidth} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hoveredWorkspaceId={hoveredWorkspaceId} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onWorkspaceHover={setHoveredWorkspaceId} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {groupIndex < groups.length - 1 && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="flex items-center h-full py-2"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="w-px h-full bg-border" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Fragment> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ))} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {isSettingsTabOpen && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {groups.length > 0 && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="flex items-center h-full py-2"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="w-px h-full bg-border" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <SettingsTab width={workspaceWidth} isActive={isSettingsActive} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {/* Left fade for scroll indication */} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {showStartFade && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="pointer-events-none absolute left-0 top-0 h-full w-8 bg-linear-to-r from-background to-transparent" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {/* Right side: gradient fade + button container */} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="absolute right-0 top-0 h-full flex items-center pointer-events-none"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {/* Gradient fade - only show when content overflows */} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {showEndFade && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="pointer-events-none absolute right-0 top-0 h-full w-8 bg-linear-to-l from-background to-transparent" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="h-full w-8 bg-linear-to-l from-background to-transparent" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {/* Button with solid background */} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="h-full flex items-center bg-background pl-1 pr-2 pointer-events-auto"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <CreateWorkspaceButton className="no-drag" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+206
to
220
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix invalid TailwindCSS gradient class names. Lines 207 and 214 use 🔎 Proposed fix for gradient class names {/* Left fade for scroll indication */}
{showStartFade && (
- <div className="pointer-events-none absolute left-0 top-0 h-full w-8 bg-linear-to-r from-background to-transparent" />
+ <div className="pointer-events-none absolute left-0 top-0 h-full w-8 bg-gradient-to-r from-background to-transparent" />
)}
{/* Right side: gradient fade + button container */}
<div className="absolute right-0 top-0 h-full flex items-center pointer-events-none">
{/* Gradient fade - only show when content overflows */}
{showEndFade && (
- <div className="h-full w-8 bg-linear-to-l from-background to-transparent" />
+ <div className="h-full w-8 bg-gradient-to-l from-background to-transparent" />
)}
{/* Button with solid background */}
<div className="h-full flex items-center bg-background pl-1 pr-2 pointer-events-auto">
<CreateWorkspaceButton className="no-drag" />
</div>
</div>📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <CreateWorkspaceButton className="no-drag" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use dynamic keyboard shortcuts for cross-platform support.
The dropdown menu hardcodes Mac-specific keyboard shortcut symbols (
⌘N,⌘⇧N,⌘⇧O). This won't adapt to Windows (Ctrl+N) or Linux (Super+N) conventions.🔎 Proposed fix using HOTKEYS.display
<DropdownMenuItem onClick={handleModalCreate} className="rounded-md text-[13px]" > <HiMiniPlus className="size-[14px] opacity-60" /> New Workspace - <DropdownMenuShortcut className="opacity-40">⌘N</DropdownMenuShortcut> + <DropdownMenuShortcut className="opacity-40"> + {HOTKEYS.NEW_WORKSPACE.display.join("")} + </DropdownMenuShortcut> </DropdownMenuItem> <DropdownMenuItem onClick={handleQuickCreate} disabled={isLoading} className="rounded-md text-[13px]" > <HiOutlineBolt className="size-[14px] opacity-60" /> Quick Create <DropdownMenuShortcut className="opacity-40"> - ⌘⇧N + {HOTKEYS.QUICK_CREATE_WORKSPACE.display.join("")} </DropdownMenuShortcut> </DropdownMenuItem> <DropdownMenuSeparator className="my-1 bg-border/40" /> <DropdownMenuItem onClick={handleOpenNewProject} disabled={isLoading} className="rounded-md text-[13px]" > <HiFolderOpen className="size-[14px] opacity-60" /> Open Project <DropdownMenuShortcut className="opacity-40"> - ⌘⇧O + {HOTKEYS.OPEN_PROJECT.display.join("")} </DropdownMenuShortcut> </DropdownMenuItem>🤖 Prompt for AI Agents