chore: improve command bar (#641)

This commit is contained in:
Lucas Smith
2023-11-09 14:38:26 +11:00
committed by GitHub
parent 3490e2a3a8
commit 86160136aa
3 changed files with 78 additions and 10 deletions

View File

@ -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 (
<NextAuthProvider session={session}>
<LimitsProvider>
<CommandMenu />
<Header user={user} />
<main className="mt-8 pb-8 md:mt-12 md:pb-12">{children}</main>

View File

@ -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<string[]>([]);
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..."
/>
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
{!currentPage && (
@ -89,7 +131,7 @@ export function CommandMenu() {
<Commands push={push} pages={SETTINGS_PAGES} />
</CommandGroup>
<CommandGroup heading="Preferences">
<CommandItem onSelect={() => setPages([...pages, 'theme'])}>Change theme</CommandItem>
<CommandItem onSelect={() => addPage('theme')}>Change theme</CommandItem>
</CommandGroup>
</>
)}

View File

@ -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<HTMLDivElement>;
export const DesktopNav = ({ className, ...props }: DesktopNavProps) => {
// const pathname = usePathname();
const [open, setOpen] = useState(false);
return (
<div className={cn('ml-8 hidden flex-1 gap-x-6 md:flex', className)} {...props}>
<div
className={cn('ml-8 hidden flex-1 gap-x-6 md:flex md:justify-center', className)}
{...props}
>
<CommandMenu open={open} onOpenChange={setOpen} />
<Button
variant="outline"
className="text-muted-foreground flex w-96 items-center justify-between rounded-lg"
onClick={() => setOpen((open) => !open)}
>
<div className="flex items-center">
<Search className="mr-2 h-5 w-5" />
Search
</div>
<div>
<div className="text-muted-foreground bg-muted rounded-md px-1.5 py-0.5 font-mono text-xs">
Ctrl+K
</div>
</div>
</Button>
{/* We have no other subpaths rn */}
{/* <Link
href="/documents"