axonhub / frontend /src /components /command-menu.tsx
llzai's picture
Upload 1793 files
9853396 verified
import React from 'react';
import { useNavigate, useRouter } from '@tanstack/react-router';
import { IconArrowRightDashed, IconChevronRight, IconDeviceLaptop, IconMoon, IconSun } from '@tabler/icons-react';
import { useTranslation } from 'react-i18next';
import { useSearch } from '@/context/search-context';
import { useTheme } from '@/context/theme-context';
import {
CommandDialog,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
} from '@/components/ui/command';
import { useSidebarData } from '../sidebar';
import { ScrollArea } from './ui/scroll-area';
export function CommandMenu() {
const router = useRouter();
const { setTheme } = useTheme();
const { open, setOpen } = useSearch();
const sidebarData = useSidebarData();
const { t } = useTranslation();
// Don't render if router is not available
if (!router) {
return null;
}
const navigate = useNavigate();
const runCommand = React.useCallback(
(command: () => unknown) => {
setOpen(false);
command();
},
[setOpen]
);
return (
<CommandDialog modal open={open} onOpenChange={setOpen}>
<CommandInput placeholder={t('command.placeholder')} />
<CommandList>
<ScrollArea type='hover' className='h-72 pr-1'>
<CommandEmpty>{t('command.noResults')}</CommandEmpty>
{sidebarData.navGroups.map((group) => (
<CommandGroup key={group.title} heading={group.title}>
{group.items.map((navItem, i) => {
if (navItem.url)
return (
<CommandItem
key={`${navItem.url}-${i}`}
value={navItem.title}
onSelect={() => {
runCommand(() => navigate({ to: navItem.url }));
}}
>
<div className='mr-2 flex h-4 w-4 items-center justify-center'>
<IconArrowRightDashed className='text-muted-foreground/80 size-2' />
</div>
{navItem.title}
</CommandItem>
);
return navItem.items?.map((subItem, i) => (
<CommandItem
key={`${navItem.title}-${subItem.url}-${i}`}
value={`${navItem.title}-${subItem.url}`}
onSelect={() => {
runCommand(() => navigate({ to: subItem.url }));
}}
>
<div className='mr-2 flex h-4 w-4 items-center justify-center'>
<IconArrowRightDashed className='text-muted-foreground/80 size-2' />
</div>
{navItem.title} <IconChevronRight /> {subItem.title}
</CommandItem>
));
})}
</CommandGroup>
))}
<CommandSeparator />
<CommandGroup heading={t('command.theme')}>
<CommandItem onSelect={() => runCommand(() => setTheme('light'))}>
<IconSun /> <span>{t('theme.light')}</span>
</CommandItem>
<CommandItem onSelect={() => runCommand(() => setTheme('dark'))}>
<IconMoon className='scale-90' />
<span>{t('theme.dark')}</span>
</CommandItem>
<CommandItem onSelect={() => runCommand(() => setTheme('system'))}>
<IconDeviceLaptop />
<span>{t('theme.system')}</span>
</CommandItem>
</CommandGroup>
</ScrollArea>
</CommandList>
</CommandDialog>
);
}