@@ -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,21 @@ function DocsLink(props: { href: string; onNavigate?: () => void }) {
163163 ) ;
164164}
165165
166+ function CommandsButton ( props : { onOpen : ( ) => void } ) {
167+ return (
168+ // oxlint-disable-next-line react/forbid-elements
169+ < button
170+ type = "button"
171+ onClick = { props . onOpen }
172+ 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"
173+ >
174+ < Command className = "size-4 shrink-0" />
175+ < span className = "flex-1 text-left" > Commands</ span >
176+ < span className = "font-mono text-[11px] text-muted-foreground" > ⌘K</ span >
177+ </ button >
178+ ) ;
179+ }
180+
166181// ── IntegrationList ───────────────────────────────────────────────────────────
167182
168183// `pathname` is scope-relative (org-slug prefix already stripped).
@@ -326,7 +341,12 @@ function UserFooter(props: Pick<ShellProps, "onSignOut" | "orgMenuSlot">) {
326341// ── SidebarContent ───────────────────────────────────────────────────────
327342
328343function SidebarContent (
329- props : ShellProps & { pathname : string ; onNavigate ?: ( ) => void ; showBrand ?: boolean } ,
344+ props : ShellProps & {
345+ pathname : string ;
346+ onNavigate ?: ( ) => void ;
347+ showBrand ?: boolean ;
348+ onOpenCommands : ( ) => void ;
349+ } ,
330350) {
331351 const plugins = useClientPlugins ( ) ;
332352 const pluginNavItems = plugins . flatMap ( ( plugin ) =>
@@ -371,6 +391,7 @@ function SidebarContent(
371391 < SidebarUpdateCard />
372392
373393 < div className = "shrink-0 border-t border-sidebar-border p-2" >
394+ < CommandsButton onOpen = { props . onOpenCommands } />
374395 < DocsLink href = { props . docsUrl ?? DEFAULT_DOCS_URL } onNavigate = { props . onNavigate } />
375396 { APP_VERSION && (
376397 < p className = "px-2.5 pt-1.5 font-mono text-[11px] text-muted-foreground tabular-nums" >
@@ -392,6 +413,7 @@ export function Shell(props: ShellProps) {
392413 const pathname = useScopeRelativePathname ( ) ;
393414 const lastPathname = useRef ( pathname ) ;
394415 const [ mobileSidebarOpen , setMobileSidebarOpen ] = useState ( false ) ;
416+ const [ commandPaletteOpen , setCommandPaletteOpen ] = useState ( false ) ;
395417 if ( lastPathname . current !== pathname ) {
396418 lastPathname . current = pathname ;
397419 if ( mobileSidebarOpen ) setMobileSidebarOpen ( false ) ;
@@ -408,10 +430,14 @@ export function Shell(props: ShellProps) {
408430
409431 return (
410432 < div className = "flex h-screen overflow-hidden" >
411- < CommandPalette />
433+ < CommandPalette open = { commandPaletteOpen } onOpenChange = { setCommandPaletteOpen } />
412434 { /* Desktop sidebar */ }
413435 < 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 } />
436+ < SidebarContent
437+ { ...props }
438+ pathname = { pathname }
439+ onOpenCommands = { ( ) => setCommandPaletteOpen ( true ) }
440+ />
415441 </ aside >
416442
417443 { /* Mobile sidebar overlay */ }
@@ -450,6 +476,10 @@ export function Shell(props: ShellProps) {
450476 pathname = { pathname }
451477 onNavigate = { ( ) => setMobileSidebarOpen ( false ) }
452478 showBrand = { false }
479+ onOpenCommands = { ( ) => {
480+ setMobileSidebarOpen ( false ) ;
481+ setCommandPaletteOpen ( true ) ;
482+ } }
453483 />
454484 </ div >
455485 </ div >
0 commit comments