@@ -2,7 +2,7 @@ import { Link, Outlet, useLocation, useParams } from "@tanstack/react-router";
22import { useEffect , useRef , useState , type ReactNode } from "react" ;
33import { useAtomValue } from "@effect/atom-react" ;
44import * as AsyncResult from "effect/unstable/reactivity/AsyncResult" ;
5- import { BookOpen , ExternalLink } from "lucide-react" ;
5+ import { BookOpen , Command , ExternalLink } from "lucide-react" ;
66import type { Integration } from "@executor-js/sdk/shared" ;
77import { integrationsOptimisticAtom } from "../api/atoms" ;
88import { trackEvent } from "../api/analytics" ;
@@ -163,6 +163,20 @@ function DocsLink(props: { href: string; onNavigate?: () => void }) {
163163 ) ;
164164}
165165
166+ function CommandsButton ( props : { onOpen : ( ) => void } ) {
167+ return (
168+ < button
169+ type = "button"
170+ onClick = { props . onOpen }
171+ className = "group flex w-full items-center gap-2.5 rounded-md px-2.5 py-1.5 text-sm text-sidebar-foreground transition-colors hover:bg-sidebar-active/60 hover:text-foreground"
172+ >
173+ < Command className = "size-4 shrink-0" />
174+ < span className = "flex-1 text-left" > Commands</ span >
175+ < span className = "font-mono text-[11px] text-muted-foreground" > ⌘K</ span >
176+ </ button >
177+ ) ;
178+ }
179+
166180// ── IntegrationList ───────────────────────────────────────────────────────────
167181
168182// `pathname` is scope-relative (org-slug prefix already stripped).
@@ -326,7 +340,12 @@ function UserFooter(props: Pick<ShellProps, "onSignOut" | "orgMenuSlot">) {
326340// ── SidebarContent ───────────────────────────────────────────────────────
327341
328342function SidebarContent (
329- props : ShellProps & { pathname : string ; onNavigate ?: ( ) => void ; showBrand ?: boolean } ,
343+ props : ShellProps & {
344+ pathname : string ;
345+ onNavigate ?: ( ) => void ;
346+ showBrand ?: boolean ;
347+ onOpenCommands : ( ) => void ;
348+ } ,
330349) {
331350 const plugins = useClientPlugins ( ) ;
332351 const pluginNavItems = plugins . flatMap ( ( plugin ) =>
@@ -371,6 +390,7 @@ function SidebarContent(
371390 < SidebarUpdateCard />
372391
373392 < div className = "shrink-0 border-t border-sidebar-border p-2" >
393+ < CommandsButton onOpen = { props . onOpenCommands } />
374394 < DocsLink href = { props . docsUrl ?? DEFAULT_DOCS_URL } onNavigate = { props . onNavigate } />
375395 { APP_VERSION && (
376396 < p className = "px-2.5 pt-1.5 font-mono text-[11px] text-muted-foreground tabular-nums" >
@@ -392,6 +412,7 @@ export function Shell(props: ShellProps) {
392412 const pathname = useScopeRelativePathname ( ) ;
393413 const lastPathname = useRef ( pathname ) ;
394414 const [ mobileSidebarOpen , setMobileSidebarOpen ] = useState ( false ) ;
415+ const [ commandPaletteOpen , setCommandPaletteOpen ] = useState ( false ) ;
395416 if ( lastPathname . current !== pathname ) {
396417 lastPathname . current = pathname ;
397418 if ( mobileSidebarOpen ) setMobileSidebarOpen ( false ) ;
@@ -408,10 +429,14 @@ export function Shell(props: ShellProps) {
408429
409430 return (
410431 < div className = "flex h-screen overflow-hidden" >
411- < CommandPalette />
432+ < CommandPalette open = { commandPaletteOpen } onOpenChange = { setCommandPaletteOpen } />
412433 { /* Desktop sidebar */ }
413434 < aside className = "hidden w-52 shrink-0 border-r border-sidebar-border bg-sidebar md:flex md:flex-col lg:w-56" >
414- < SidebarContent { ...props } pathname = { pathname } />
435+ < SidebarContent
436+ { ...props }
437+ pathname = { pathname }
438+ onOpenCommands = { ( ) => setCommandPaletteOpen ( true ) }
439+ />
415440 </ aside >
416441
417442 { /* Mobile sidebar overlay */ }
@@ -450,6 +475,10 @@ export function Shell(props: ShellProps) {
450475 pathname = { pathname }
451476 onNavigate = { ( ) => setMobileSidebarOpen ( false ) }
452477 showBrand = { false }
478+ onOpenCommands = { ( ) => {
479+ setMobileSidebarOpen ( false ) ;
480+ setCommandPaletteOpen ( true ) ;
481+ } }
453482 />
454483 </ div >
455484 </ div >
0 commit comments