fix(desktop): move power-user views out of sidebar
Keep Cron and Profiles available through lower-prominence chrome entry points so the workspace sidebar stays focused on core chat navigation. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -14,7 +14,7 @@ import {
|
||||
} from '@/components/ui/sidebar'
|
||||
import { Skeleton } from '@/components/ui/skeleton'
|
||||
import type { SessionInfo } from '@/hermes'
|
||||
import { Brain, ChevronDown, Clock, Layers3, MessageCircle, Plus, RefreshCw, Users } from '@/lib/icons'
|
||||
import { Brain, ChevronDown, Layers3, MessageCircle, Plus, RefreshCw } from '@/lib/icons'
|
||||
import { cn } from '@/lib/utils'
|
||||
import {
|
||||
$pinnedSessionIds,
|
||||
@@ -28,14 +28,7 @@ import {
|
||||
} from '@/store/layout'
|
||||
import { $selectedStoredSessionId, $sessions, $sessionsLoading, $workingSessionIds } from '@/store/session'
|
||||
|
||||
import {
|
||||
type AppView,
|
||||
ARTIFACTS_ROUTE,
|
||||
CRON_ROUTE,
|
||||
MESSAGING_ROUTE,
|
||||
PROFILES_ROUTE,
|
||||
SKILLS_ROUTE
|
||||
} from '../../routes'
|
||||
import { type AppView, ARTIFACTS_ROUTE, MESSAGING_ROUTE, SKILLS_ROUTE } from '../../routes'
|
||||
import { SidebarPanelLabel } from '../../shell/sidebar-label'
|
||||
import type { SidebarNavItem } from '../../types'
|
||||
|
||||
@@ -50,9 +43,7 @@ const SIDEBAR_NAV: SidebarNavItem[] = [
|
||||
},
|
||||
{ id: 'skills', label: 'Skills', icon: Brain, route: SKILLS_ROUTE },
|
||||
{ id: 'messaging', label: 'Messaging', icon: MessageCircle, route: MESSAGING_ROUTE },
|
||||
{ id: 'artifacts', label: 'Artifacts', icon: Layers3, route: ARTIFACTS_ROUTE },
|
||||
{ id: 'cron', label: 'Cron', icon: Clock, route: CRON_ROUTE },
|
||||
{ id: 'profiles', label: 'Profiles', icon: Users, route: PROFILES_ROUTE }
|
||||
{ id: 'artifacts', label: 'Artifacts', icon: Layers3, route: ARTIFACTS_ROUTE }
|
||||
]
|
||||
|
||||
interface ChatSidebarProps extends React.ComponentProps<typeof Sidebar> {
|
||||
@@ -126,9 +117,7 @@ export function ChatSidebar({
|
||||
const active =
|
||||
(item.id === 'skills' && currentView === 'skills') ||
|
||||
(item.id === 'messaging' && currentView === 'messaging') ||
|
||||
(item.id === 'artifacts' && currentView === 'artifacts') ||
|
||||
(item.id === 'cron' && currentView === 'cron') ||
|
||||
(item.id === 'profiles' && currentView === 'profiles')
|
||||
(item.id === 'artifacts' && currentView === 'artifacts')
|
||||
|
||||
return (
|
||||
<SidebarMenuItem key={item.id}>
|
||||
|
||||
@@ -78,7 +78,7 @@ export function AppShell({
|
||||
// between the pane-tool cluster and the system cluster so they don't sit
|
||||
// flush against each other. Modeled as N gaps (N - 1 inner + 1 trailing)
|
||||
// to keep the formula generic for any pane-tool count.
|
||||
const SYSTEM_TOOL_COUNT = 3
|
||||
const SYSTEM_TOOL_COUNT = 4
|
||||
const paneToolCount = titlebarTools?.filter(tool => !tool.hidden).length ?? 0
|
||||
const systemToolsWidth = `calc(${SYSTEM_TOOL_COUNT} * (var(--titlebar-control-size) + 0.25rem))`
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useCallback, useMemo, useState } from 'react'
|
||||
import type { CommandCenterSection } from '@/app/command-center'
|
||||
import { GatewayMenuPanel } from '@/app/shell/gateway-menu-panel'
|
||||
import { restartGateway } from '@/hermes'
|
||||
import { Activity, AlertCircle, Command, Cpu, FolderOpen, GitBranch, Hash, Loader2, Sparkles } from '@/lib/icons'
|
||||
import { Activity, AlertCircle, Clock, Command, Cpu, FolderOpen, GitBranch, Hash, Loader2, Sparkles } from '@/lib/icons'
|
||||
import { compactPath, contextBarLabel, LiveDuration, usageContextLabel } from '@/lib/statusbar'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { $desktopActionTasks } from '@/store/activity'
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
import { $desktopVersion, $updateApply, $updateStatus, setUpdateOverlayOpen } from '@/store/updates'
|
||||
import type { StatusResponse } from '@/types/hermes'
|
||||
|
||||
import { CRON_ROUTE } from '../../routes'
|
||||
import type { StatusbarItem } from '../statusbar-controls'
|
||||
|
||||
interface StatusbarItemsOptions {
|
||||
@@ -203,6 +204,14 @@ export function useStatusbarItems({
|
||||
onSelect: openAgents,
|
||||
title: agentsOpen ? 'Close agents' : 'Open agents',
|
||||
variant: 'action'
|
||||
},
|
||||
{
|
||||
icon: <Clock className="size-3" />,
|
||||
id: 'cron',
|
||||
label: 'Cron',
|
||||
title: 'Open cron jobs',
|
||||
to: CRON_ROUTE,
|
||||
variant: 'action'
|
||||
}
|
||||
],
|
||||
[
|
||||
|
||||
@@ -2,12 +2,22 @@ import { useStore } from '@nanostores/react'
|
||||
import type { ComponentProps, ReactNode } from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger
|
||||
} from '@/components/ui/dropdown-menu'
|
||||
import { triggerHaptic } from '@/lib/haptics'
|
||||
import { FolderOpen, NotebookTabs, Settings, Volume2, VolumeX } from '@/lib/icons'
|
||||
import { FolderOpen, NotebookTabs, Settings, Users, Volume2, VolumeX } from '@/lib/icons'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { $hapticsMuted, toggleHapticsMuted } from '@/store/haptics'
|
||||
import { $fileBrowserOpen, $sidebarOpen, toggleFileBrowserOpen, toggleSidebarOpen } from '@/store/layout'
|
||||
|
||||
import { PROFILES_ROUTE } from '../routes'
|
||||
|
||||
import { titlebarButtonClass } from './titlebar'
|
||||
|
||||
export interface TitlebarTool {
|
||||
@@ -95,6 +105,8 @@ export function TitlebarControls({ leftTools = [], tools = [], onOpenSettings }:
|
||||
]
|
||||
|
||||
const visibleSystemTools = systemTools.filter(tool => !tool.hidden)
|
||||
const settingsTool = visibleSystemTools.find(tool => tool.id === 'settings')
|
||||
const visibleSystemToolsBeforeSettings = visibleSystemTools.filter(tool => tool.id !== 'settings')
|
||||
const visiblePaneTools = tools.filter(tool => !tool.hidden)
|
||||
|
||||
return (
|
||||
@@ -133,14 +145,55 @@ export function TitlebarControls({ leftTools = [], tools = [], onOpenSettings }:
|
||||
aria-label="App controls"
|
||||
className="fixed right-(--titlebar-tools-right) top-(--titlebar-controls-top) z-70 flex flex-row items-center justify-end gap-x-1 pointer-events-auto select-none [-webkit-app-region:no-drag]"
|
||||
>
|
||||
{visibleSystemTools.map(tool => (
|
||||
{visibleSystemToolsBeforeSettings.map(tool => (
|
||||
<TitlebarToolButton key={tool.id} navigate={navigate} tool={tool} />
|
||||
))}
|
||||
<ProfilesMenuButton navigate={navigate} />
|
||||
{settingsTool && <TitlebarToolButton navigate={navigate} tool={settingsTool} />}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function ProfilesMenuButton({ navigate }: { navigate: ReturnType<typeof useNavigate> }) {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<button
|
||||
aria-label="Profiles"
|
||||
className={cn(
|
||||
titlebarButtonClass,
|
||||
'grid place-items-center bg-transparent select-none [&_svg]:size-4'
|
||||
)}
|
||||
onPointerDown={event => event.stopPropagation()}
|
||||
title="Profiles"
|
||||
type="button"
|
||||
>
|
||||
<Users />
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-64" sideOffset={8}>
|
||||
<DropdownMenuLabel>
|
||||
<div className="text-sm font-medium text-foreground">Profiles</div>
|
||||
<div className="mt-1 text-xs font-normal leading-4 text-muted-foreground">
|
||||
Advanced Hermes environments for separate personas, config, skills, and SOUL.md.
|
||||
</div>
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem
|
||||
onSelect={() => {
|
||||
triggerHaptic('open')
|
||||
navigate(PROFILES_ROUTE)
|
||||
}}
|
||||
>
|
||||
<Users className="size-4" />
|
||||
<span>Manage profiles</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
}
|
||||
|
||||
function TitlebarToolButton({ navigate, tool }: { navigate: ReturnType<typeof useNavigate>; tool: TitlebarTool }) {
|
||||
const className = cn(
|
||||
titlebarButtonClass,
|
||||
|
||||
@@ -54,10 +54,8 @@ export type CommandDispatchResponse =
|
||||
export type SidebarNavId =
|
||||
| 'artifacts'
|
||||
| 'command-center'
|
||||
| 'cron'
|
||||
| 'messaging'
|
||||
| 'new-session'
|
||||
| 'profiles'
|
||||
| 'settings'
|
||||
| 'skills'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user