From 7950ac72af2d304de2039d64c3c3403040a4b7fa Mon Sep 17 00:00:00 2001 From: Naiyuan Qing <145280634+NevilleQingNY@users.noreply.github.com> Date: Thu, 9 Apr 2026 18:35:22 +0800 Subject: [PATCH] feat(web): add search button to sidebar header + restore turbo globalEnv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a visible search trigger button next to the create-issue button in the sidebar header, improving search discoverability (previously only accessible via ⌘K). Search dialog open state is shared via a Zustand store so both the button and keyboard shortcut work. Also restores turbo.json globalEnv config (FRONTEND_PORT, etc.) that was accidentally dropped during the monorepo extraction, fixing worktree port conflicts. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../(dashboard)/_components/app-sidebar.tsx | 33 +++++++++++++------ .../search/components/search-command.tsx | 11 ++++--- apps/web/features/search/index.ts | 1 + .../features/search/stores/search-store.ts | 15 +++++++++ turbo.json | 12 +++++++ 5 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 apps/web/features/search/stores/search-store.ts diff --git a/apps/web/app/(dashboard)/_components/app-sidebar.tsx b/apps/web/app/(dashboard)/_components/app-sidebar.tsx index 619908aa8..5ace39932 100644 --- a/apps/web/app/(dashboard)/_components/app-sidebar.tsx +++ b/apps/web/app/(dashboard)/_components/app-sidebar.tsx @@ -17,6 +17,7 @@ import { SquarePen, CircleUser, FolderKanban, + Search, } from "lucide-react"; import { WorkspaceAvatar } from "@multica/views/workspace/workspace-avatar"; import { useIssueDraftStore } from "@multica/core/issues/stores/draft-store"; @@ -49,6 +50,7 @@ import { inboxKeys, deduplicateInboxItems } from "@multica/core/inbox/queries"; import { api } from "@/platform/api"; import { useModalStore } from "@multica/core/modals"; import { useMyRuntimesNeedUpdate } from "@multica/core/runtimes/hooks"; +import { useSearchStore } from "@/features/search"; const primaryNav = [ { href: "/inbox", label: "Inbox", icon: Inbox }, @@ -172,16 +174,27 @@ export function AppSidebar() { - - useModalStore.getState().open("create-issue")} - > - - - - New issue - +
+ + useSearchStore.getState().setOpen(true)} + > + + + Search workspace (⌘K) + + + useModalStore.getState().open("create-issue")} + > + + + + New issue + +
diff --git a/apps/web/features/search/components/search-command.tsx b/apps/web/features/search/components/search-command.tsx index 581839b4e..c55647e7a 100644 --- a/apps/web/features/search/components/search-command.tsx +++ b/apps/web/features/search/components/search-command.tsx @@ -15,10 +15,12 @@ import { DialogTitle, DialogDescription, } from "@multica/ui/components/ui/dialog"; +import { useSearchStore } from "../stores/search-store"; export function SearchCommand() { const router = useRouter(); - const [open, setOpen] = useState(false); + const open = useSearchStore((s) => s.open); + const setOpen = useSearchStore((s) => s.setOpen); const [query, setQuery] = useState(""); const [results, setResults] = useState([]); const [isLoading, setIsLoading] = useState(false); @@ -30,7 +32,7 @@ export function SearchCommand() { const handleKeyDown = (e: KeyboardEvent) => { if (e.key === "k" && (e.metaKey || e.ctrlKey)) { e.preventDefault(); - setOpen((prev) => !prev); + useSearchStore.getState().toggle(); } }; document.addEventListener("keydown", handleKeyDown); @@ -186,8 +188,9 @@ export function SearchCommand() { )} {!isLoading && !query.trim() && ( -
- Type to search issues... +
+ Type to search issues... + Press ⌘K to open this anytime
)} diff --git a/apps/web/features/search/index.ts b/apps/web/features/search/index.ts index 6e3baea48..b6f719b68 100644 --- a/apps/web/features/search/index.ts +++ b/apps/web/features/search/index.ts @@ -1 +1,2 @@ export { SearchCommand } from "./components/search-command"; +export { useSearchStore } from "./stores/search-store"; diff --git a/apps/web/features/search/stores/search-store.ts b/apps/web/features/search/stores/search-store.ts new file mode 100644 index 000000000..341fe01d7 --- /dev/null +++ b/apps/web/features/search/stores/search-store.ts @@ -0,0 +1,15 @@ +"use client"; + +import { create } from "zustand"; + +interface SearchStore { + open: boolean; + setOpen: (open: boolean) => void; + toggle: () => void; +} + +export const useSearchStore = create((set) => ({ + open: false, + setOpen: (open) => set({ open }), + toggle: () => set((s) => ({ open: !s.open })), +})); diff --git a/turbo.json b/turbo.json index 694658b87..7a74c0b70 100644 --- a/turbo.json +++ b/turbo.json @@ -1,5 +1,17 @@ { "$schema": "https://turbo.build/schema.json", + "globalEnv": [ + "DATABASE_URL", + "PORT", + "FRONTEND_PORT", + "FRONTEND_ORIGIN", + "NEXT_PUBLIC_API_URL", + "NEXT_PUBLIC_WS_URL", + "MULTICA_SERVER_URL", + "COMPOSE_PROJECT_NAME", + "POSTGRES_DB", + "POSTGRES_PORT" + ], "tasks": { "build": { "dependsOn": ["^build"],