diff --git a/src/client/components/CommandPanel.tsx b/src/client/components/CommandPanel.tsx
new file mode 100644
index 0000000..0503693
--- /dev/null
+++ b/src/client/components/CommandPanel.tsx
@@ -0,0 +1,236 @@
+import React, { useEffect, useState } from 'react';
+import {
+ Command,
+ CommandDialog,
+ CommandEmpty,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+ CommandList,
+ CommandSeparator,
+} from '@/components/ui/command';
+import {
+ LuAreaChart,
+ LuBellDot,
+ LuFilePieChart,
+ LuMonitorDot,
+ LuSearch,
+ LuServer,
+ LuUserCircle2,
+ LuWifi,
+} from 'react-icons/lu';
+import { NavigateOptions, useNavigate } from '@tanstack/react-router';
+import { useEvent } from '@/hooks/useEvent';
+import { useCommandState } from 'cmdk';
+import { useTranslation } from '@i18next-toolkit/react';
+import { trpc } from '@/api/trpc';
+import { useCurrentWorkspaceId } from '@/store/user';
+import { Button } from './ui/button';
+
+export const CommandPanel: React.FC = React.memo(() => {
+ const [open, setOpen] = useState(false);
+ const navigate = useNavigate();
+ const { t } = useTranslation();
+
+ const handleJump = useEvent((options: NavigateOptions) => {
+ return () => {
+ setOpen(false);
+ navigate(options);
+ };
+ });
+
+ useEffect(() => {
+ const down = (e: KeyboardEvent) => {
+ if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {
+ e.preventDefault();
+ setOpen((open) => !open);
+ }
+ };
+
+ document.addEventListener('keydown', down);
+ return () => document.removeEventListener('keydown', down);
+ }, []);
+
+ return (
+ <>
+
+
+
+
+
+
+ {t('No results found.')}
+
+
+
+
+ {t('Website')}
+
+
+
+ {t('Monitor')}
+
+
+
+ {t('Servers')}
+
+
+
+ {t('Telemetry')}
+
+
+
+ {t('Pages')}
+
+
+
+
+
+
+ {t('Profile')}
+
+
+
+ {t('Notifications')}
+
+
+
+
+
+ >
+ );
+});
+CommandPanel.displayName = 'CommandPanel';
+
+interface CommandPanelSearchGroupProps {
+ handleJump: (options: NavigateOptions) => () => void;
+}
+export const CommandPanelSearchGroup: React.FC =
+ React.memo((props) => {
+ const handleJump = props.handleJump;
+ const search = useCommandState((state) => state.search);
+ const workspaceId = useCurrentWorkspaceId();
+ const { t } = useTranslation();
+ const { data: websites = [] } = trpc.website.all.useQuery({
+ workspaceId,
+ });
+ const { data: monitors = [] } = trpc.monitor.all.useQuery({
+ workspaceId,
+ });
+ const { data: telemetryList = [] } = trpc.telemetry.all.useQuery({
+ workspaceId,
+ });
+ const { data: pages = [] } = trpc.monitor.getAllPages.useQuery({
+ workspaceId,
+ });
+
+ if (!search) {
+ return null;
+ }
+
+ return (
+
+ {websites.map((w) => (
+
+
+ {w.name}
+
+ ))}
+ {monitors.map((m) => (
+
+
+ {m.name}
+
+ ))}
+ {telemetryList.map((t) => (
+
+
+ {t.name}
+
+ ))}
+ {pages.map((p) => (
+
+
+ {p.title}
+
+ ))}
+
+ );
+ });
+CommandPanelSearchGroup.displayName = 'CommandPanelSearchGroup';
diff --git a/src/client/components/ui/command.tsx b/src/client/components/ui/command.tsx
index 91b2295..b18e756 100644
--- a/src/client/components/ui/command.tsx
+++ b/src/client/components/ui/command.tsx
@@ -27,7 +27,7 @@ const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
return (