diff --git a/src/components/BreadcrumbBar.tsx b/src/components/BreadcrumbBar.tsx index 259319b9..2201051a 100644 --- a/src/components/BreadcrumbBar.tsx +++ b/src/components/BreadcrumbBar.tsx @@ -146,7 +146,7 @@ function BreadcrumbActions({ entry, showDiffToggle, diffMode, diffLoading, onTog diff --git a/src/components/Inspector.tsx b/src/components/Inspector.tsx index c92dfd03..e4eafb44 100644 --- a/src/components/Inspector.tsx +++ b/src/components/Inspector.tsx @@ -92,14 +92,14 @@ function InspectorHeader({ collapsed, onToggle }: { collapsed: boolean; onToggle return (
{collapsed ? ( - ) : ( <> Properties - diff --git a/src/hooks/commands/viewCommands.ts b/src/hooks/commands/viewCommands.ts index 9e99ecd1..b0f17bb4 100644 --- a/src/hooks/commands/viewCommands.ts +++ b/src/hooks/commands/viewCommands.ts @@ -26,7 +26,7 @@ export function buildViewCommands(config: ViewCommandsConfig): CommandAction[] { { id: 'view-editor', label: 'Editor Only', group: 'View', shortcut: '⌘1', keywords: ['layout', 'focus'], enabled: true, execute: () => onSetViewMode('editor-only') }, { id: 'view-editor-list', label: 'Editor + Note List', group: 'View', shortcut: '⌘2', keywords: ['layout'], enabled: true, execute: () => onSetViewMode('editor-list') }, { id: 'view-all', label: 'Full Layout', group: 'View', shortcut: '⌘3', keywords: ['layout', 'sidebar'], enabled: true, execute: () => onSetViewMode('all') }, - { id: 'toggle-inspector', label: 'Toggle Properties Panel', group: 'View', keywords: ['properties', 'inspector', 'panel', 'right', 'sidebar'], enabled: true, execute: onToggleInspector }, + { id: 'toggle-inspector', label: 'Toggle Properties Panel', group: 'View', shortcut: '⌘⇧I', keywords: ['properties', 'inspector', 'panel', 'right', 'sidebar'], enabled: true, execute: onToggleInspector }, { id: 'toggle-diff', label: 'Toggle Diff Mode', group: 'View', keywords: ['diff', 'changes', 'git', 'compare', 'version'], enabled: hasActiveNote && activeNoteModified, execute: () => onToggleDiff?.() }, { id: 'toggle-raw-editor', label: 'Toggle Raw Editor', group: 'View', keywords: ['raw', 'source', 'markdown', 'frontmatter', 'code', 'textarea'], enabled: hasActiveNote, execute: () => onToggleRawEditor?.() }, { id: 'toggle-ai-panel', label: 'Toggle AI Panel', group: 'View', shortcut: '⌘I', keywords: ['ai', 'agent', 'chat', 'assistant', 'contextual'], enabled: true, execute: () => onToggleAIChat?.() }, diff --git a/src/hooks/useAppCommands.ts b/src/hooks/useAppCommands.ts index 62a1b49c..23fe345e 100644 --- a/src/hooks/useAppCommands.ts +++ b/src/hooks/useAppCommands.ts @@ -111,6 +111,7 @@ export function useAppCommands(config: AppCommandsConfig): CommandAction[] { onGoForward: config.onGoForward, onToggleAIChat: config.onToggleAIChat, onToggleRawEditor: config.onToggleRawEditor, + onToggleInspector: config.onToggleInspector, onOpenInNewWindow: config.onOpenInNewWindow, activeTabPathRef: config.activeTabPathRef, }) diff --git a/src/hooks/useAppKeyboard.test.ts b/src/hooks/useAppKeyboard.test.ts index 1ca5127a..5553f9b8 100644 --- a/src/hooks/useAppKeyboard.test.ts +++ b/src/hooks/useAppKeyboard.test.ts @@ -200,4 +200,22 @@ describe('useAppKeyboard', () => { fireKey('o', { metaKey: true, shiftKey: true }) expect(onOpenInNewWindow).toHaveBeenCalled() }) + + it('Cmd+Shift+I triggers toggle inspector', () => { + const actions = makeActions() + const onToggleInspector = vi.fn() + renderHook(() => useAppKeyboard({ ...actions, onToggleInspector })) + fireKey('i', { metaKey: true, shiftKey: true }) + expect(onToggleInspector).toHaveBeenCalled() + }) + + it('Cmd+Shift+I does not trigger AI chat toggle', () => { + const actions = makeActions() + const onToggleAIChat = vi.fn() + const onToggleInspector = vi.fn() + renderHook(() => useAppKeyboard({ ...actions, onToggleAIChat, onToggleInspector })) + fireKey('i', { metaKey: true, shiftKey: true }) + expect(onToggleInspector).toHaveBeenCalled() + expect(onToggleAIChat).not.toHaveBeenCalled() + }) }) diff --git a/src/hooks/useAppKeyboard.ts b/src/hooks/useAppKeyboard.ts index 052d9c47..e4b48748 100644 --- a/src/hooks/useAppKeyboard.ts +++ b/src/hooks/useAppKeyboard.ts @@ -19,6 +19,7 @@ interface KeyboardActions { onGoForward?: () => void onToggleAIChat?: () => void onToggleRawEditor?: () => void + onToggleInspector?: () => void onOpenInNewWindow?: () => void activeTabPathRef: React.MutableRefObject } @@ -64,7 +65,7 @@ function handleCmdKey(e: KeyboardEvent, keyMap: Record) export function useAppKeyboard({ onQuickOpen, onCommandPalette, onSearch, onCreateNote, onOpenDailyNote, onSave, onOpenSettings, onTrashNote, onArchiveNote, - onSetViewMode, onZoomIn, onZoomOut, onZoomReset, onGoBack, onGoForward, onToggleAIChat, onToggleRawEditor, onOpenInNewWindow, activeTabPathRef, + onSetViewMode, onZoomIn, onZoomOut, onZoomReset, onGoBack, onGoForward, onToggleAIChat, onToggleRawEditor, onToggleInspector, onOpenInNewWindow, activeTabPathRef, }: KeyboardActions) { useEffect(() => { const withActiveTab = (fn: (path: string) => void): ShortcutHandler => () => { @@ -99,6 +100,12 @@ export function useAppKeyboard({ onSearch() return } + // Cmd+Shift+I: toggle properties/inspector panel + if ((e.metaKey || e.ctrlKey) && e.shiftKey && (e.key === 'i' || e.key === 'I')) { + e.preventDefault() + onToggleInspector?.() + return + } // Cmd+Shift+O: open active note in new window if ((e.metaKey || e.ctrlKey) && e.shiftKey && (e.key === 'o' || e.key === 'O')) { e.preventDefault() @@ -111,5 +118,5 @@ export function useAppKeyboard({ } window.addEventListener('keydown', handleKeyDown) return () => window.removeEventListener('keydown', handleKeyDown) - }, [onQuickOpen, onCommandPalette, onSearch, onCreateNote, onOpenDailyNote, onSave, onOpenSettings, onTrashNote, onArchiveNote, activeTabPathRef, onSetViewMode, onZoomIn, onZoomOut, onZoomReset, onGoBack, onGoForward, onToggleAIChat, onToggleRawEditor, onOpenInNewWindow]) + }, [onQuickOpen, onCommandPalette, onSearch, onCreateNote, onOpenDailyNote, onSave, onOpenSettings, onTrashNote, onArchiveNote, activeTabPathRef, onSetViewMode, onZoomIn, onZoomOut, onZoomReset, onGoBack, onGoForward, onToggleAIChat, onToggleRawEditor, onToggleInspector, onOpenInNewWindow]) } diff --git a/src/hooks/useLayoutPanels.test.ts b/src/hooks/useLayoutPanels.test.ts index d470529a..18fde69f 100644 --- a/src/hooks/useLayoutPanels.test.ts +++ b/src/hooks/useLayoutPanels.test.ts @@ -52,4 +52,14 @@ describe('useLayoutPanels', () => { act(() => result.current.handleInspectorResize(-500)) expect(result.current.inspectorWidth).toBe(500) }) + + it('defaults inspector to collapsed', () => { + const { result } = renderHook(() => useLayoutPanels()) + expect(result.current.inspectorCollapsed).toBe(true) + }) + + it('accepts initial inspector collapsed override', () => { + const { result } = renderHook(() => useLayoutPanels({ initialInspectorCollapsed: false })) + expect(result.current.inspectorCollapsed).toBe(false) + }) }) diff --git a/src/hooks/useLayoutPanels.ts b/src/hooks/useLayoutPanels.ts index 34a31e65..c1310fa5 100644 --- a/src/hooks/useLayoutPanels.ts +++ b/src/hooks/useLayoutPanels.ts @@ -11,7 +11,7 @@ export function useLayoutPanels(options?: { initialInspectorCollapsed?: boolean const [sidebarWidth, setSidebarWidth] = useState(250) const [noteListWidth, setNoteListWidth] = useState(300) const [inspectorWidth, setInspectorWidth] = useState(280) - const [inspectorCollapsed, setInspectorCollapsed] = useState(options?.initialInspectorCollapsed ?? false) + const [inspectorCollapsed, setInspectorCollapsed] = useState(options?.initialInspectorCollapsed ?? true) const handleSidebarResize = useCallback((delta: number) => setSidebarWidth((w) => Math.max(COLUMN_MIN_WIDTHS.sidebar, Math.min(400, w + delta))), []) const handleNoteListResize = useCallback((delta: number) => setNoteListWidth((w) => Math.max(COLUMN_MIN_WIDTHS.noteList, Math.min(500, w + delta))), []) const handleInspectorResize = useCallback((delta: number) => setInspectorWidth((w) => Math.max(COLUMN_MIN_WIDTHS.inspector, Math.min(500, w - delta))), [])