diff --git a/apps/web/src/app/(dashboard)/layout.tsx b/apps/web/src/app/(dashboard)/layout.tsx index 2bbdfcc36..efd3aa2ea 100644 --- a/apps/web/src/app/(dashboard)/layout.tsx +++ b/apps/web/src/app/(dashboard)/layout.tsx @@ -8,7 +8,6 @@ import { LimitsProvider } from '@documenso/ee/server-only/limits/provider/server import { NEXT_AUTH_OPTIONS } from '@documenso/lib/next-auth/auth-options'; import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get-server-session'; -import { CommandMenu } from '~/components/(dashboard)/common/command-menu'; import { Header } from '~/components/(dashboard)/layout/header'; import { RefreshOnFocus } from '~/components/(dashboard)/refresh-on-focus/refresh-on-focus'; import { NextAuthProvider } from '~/providers/next-auth'; @@ -31,7 +30,6 @@ export default async function AuthenticatedDashboardLayout({ return ( -
{children}
diff --git a/apps/web/src/components/(dashboard)/common/command-menu.tsx b/apps/web/src/components/(dashboard)/common/command-menu.tsx index cc597cfeb..8d21f8d6a 100644 --- a/apps/web/src/components/(dashboard)/common/command-menu.tsx +++ b/apps/web/src/components/(dashboard)/common/command-menu.tsx @@ -40,22 +40,61 @@ const SETTINGS_PAGES = [ { label: 'Password', path: '/settings/password' }, ]; -export function CommandMenu() { +export type CommandMenuProps = { + open?: boolean; + onOpenChange?: (_open: boolean) => void; +}; + +export function CommandMenu({ open, onOpenChange }: CommandMenuProps) { const { setTheme } = useTheme(); - const { push } = useRouter(); - const [open, setOpen] = useState(false); + const router = useRouter(); + + const [isOpen, setIsOpen] = useState(() => open ?? false); const [search, setSearch] = useState(''); const [pages, setPages] = useState([]); + const currentPage = pages[pages.length - 1]; const toggleOpen = () => { - setOpen((open) => !open); + setIsOpen((isOpen) => !isOpen); + onOpenChange?.(!isOpen); + + if (isOpen) { + setPages([]); + setSearch(''); + } + }; + + const setOpen = useCallback( + (open: boolean) => { + setIsOpen(open); + onOpenChange?.(open); + + if (!open) { + setPages([]); + setSearch(''); + } + }, + [onOpenChange], + ); + + const push = useCallback( + (path: string) => { + router.push(path); + setOpen(false); + }, + [router, setOpen], + ); + + const addPage = (page: string) => { + setPages((pages) => [...pages, page]); + setSearch(''); }; const goToSettings = useCallback(() => push(SETTINGS_PAGES[0].path), [push]); const goToDocuments = useCallback(() => push(DOCUMENTS_PAGES[0].path), [push]); - useHotkeys('ctrl+k', toggleOpen); + useHotkeys(['ctrl+k', 'meta+k'], toggleOpen); useHotkeys(SETTINGS_PAGE_SHORTCUT, goToSettings); useHotkeys(DOCUMENTS_PAGE_SHORTCUT, goToDocuments); @@ -64,9 +103,11 @@ export function CommandMenu() { // Backspace goes to previous page when search is empty if (e.key === 'Escape' || (e.key === 'Backspace' && !search)) { e.preventDefault(); + if (currentPage === undefined) { setOpen(false); } + setPages((pages) => pages.slice(0, -1)); } }; @@ -78,6 +119,7 @@ export function CommandMenu() { onValueChange={setSearch} placeholder="Type a command or search..." /> + No results found. {!currentPage && ( @@ -89,7 +131,7 @@ export function CommandMenu() { - setPages([...pages, 'theme'])}>Change theme + addPage('theme')}>Change theme )} diff --git a/apps/web/src/components/(dashboard)/layout/desktop-nav.tsx b/apps/web/src/components/(dashboard)/layout/desktop-nav.tsx index 2c6165a05..a32d1b82a 100644 --- a/apps/web/src/components/(dashboard)/layout/desktop-nav.tsx +++ b/apps/web/src/components/(dashboard)/layout/desktop-nav.tsx @@ -1,16 +1,44 @@ 'use client'; -import { HTMLAttributes } from 'react'; +import { HTMLAttributes, useState } from 'react'; + +import { Search } from 'lucide-react'; import { cn } from '@documenso/ui/lib/utils'; +import { Button } from '@documenso/ui/primitives/button'; + +import { CommandMenu } from '../common/command-menu'; export type DesktopNavProps = HTMLAttributes; export const DesktopNav = ({ className, ...props }: DesktopNavProps) => { // const pathname = usePathname(); + const [open, setOpen] = useState(false); return ( -