diff --git a/design/vista-changes.pen b/design/vista-changes.pen new file mode 100644 index 00000000..e1f41e80 --- /dev/null +++ b/design/vista-changes.pen @@ -0,0 +1,496 @@ +{ + "children": [ + { + "type": "frame", + "id": "vc001", + "x": 0, + "y": 0, + "name": "Changes — sidebar section with pending notes", + "clip": true, + "width": 550, + "height": 500, + "fill": "$--background", + "layout": "horizontal", + "children": [ + { + "type": "frame", + "id": "vc002", + "name": "Sidebar", + "width": 250, + "height": "fill_container", + "fill": "$--sidebar", + "layout": "vertical", + "children": [ + { + "type": "frame", + "id": "vc003", + "name": "Filters", + "width": "fill_container", + "layout": "vertical", + "gap": 1, + "padding": [8, 8], + "stroke": { + "align": "inside", + "thickness": { "bottom": 1 }, + "fill": "$--border" + }, + "children": [ + { + "type": "frame", + "id": "vc004", + "name": "filterAll", + "width": "fill_container", + "cornerRadius": 6, + "gap": 8, + "padding": [6, 16], + "alignItems": "center", + "children": [ + { "type": "text", "id": "vc005", "text": "All Notes", "fontSize": 13, "fill": "$--foreground" } + ] + }, + { + "type": "frame", + "id": "vc006", + "name": "filterFavorites", + "width": "fill_container", + "cornerRadius": 6, + "gap": 8, + "padding": [6, 16], + "alignItems": "center", + "children": [ + { "type": "text", "id": "vc007", "text": "Favorites", "fontSize": 13, "fill": "$--foreground" } + ] + }, + { + "type": "frame", + "id": "vc008", + "name": "filterTrash", + "width": "fill_container", + "cornerRadius": 6, + "gap": 8, + "padding": [6, 16], + "alignItems": "center", + "children": [ + { "type": "text", "id": "vc009", "text": "Trash", "fontSize": 13, "fill": "$--foreground" } + ] + }, + { + "type": "frame", + "id": "vc010", + "name": "filterChanges-active", + "width": "fill_container", + "fill": "#F5750018", + "cornerRadius": 6, + "gap": 8, + "padding": [6, 16], + "alignItems": "center", + "justifyContent": "space-between", + "children": [ + { "type": "text", "id": "vc011", "text": "Changes", "fontSize": 13, "fontWeight": 500, "fill": "$--accent-orange" }, + { + "type": "frame", + "id": "vc012", + "name": "badge", + "fill": "$--accent-orange", + "cornerRadius": 9999, + "padding": [0, 6], + "height": 20, + "alignItems": "center", + "children": [ + { "type": "text", "id": "vc013", "text": "3", "fontSize": 10, "fontWeight": 600, "fill": "$--white" } + ] + } + ] + } + ] + } + ] + }, + { + "type": "frame", + "id": "vc014", + "name": "NoteList: Changes", + "width": 300, + "height": "fill_container", + "fill": "$--card", + "layout": "vertical", + "stroke": { + "align": "inside", + "thickness": { "right": 1 }, + "fill": "$--border" + }, + "children": [ + { + "type": "frame", + "id": "vc015", + "name": "header", + "width": "fill_container", + "height": 45, + "padding": [0, 16], + "alignItems": "center", + "stroke": { "align": "inside", "thickness": { "bottom": 1 }, "fill": "$--border" }, + "children": [ + { "type": "text", "id": "vc016", "text": "Changes", "fontSize": 14, "fontWeight": 600, "fill": "$--foreground" } + ] + }, + { + "type": "frame", + "id": "vc017", + "name": "note1-modified", + "width": "fill_container", + "padding": [10, 16], + "gap": 4, + "layout": "vertical", + "stroke": { "align": "inside", "thickness": { "bottom": 1 }, "fill": "$--border" }, + "children": [ + { + "type": "frame", + "id": "vc018", + "name": "titleRow", + "gap": 6, + "alignItems": "center", + "children": [ + { "type": "ellipse", "id": "vc019", "name": "modifiedDot", "fill": "$--accent-orange", "width": 6, "height": 6 }, + { "type": "text", "id": "vc020", "text": "Build Laputa App", "fontSize": 13, "fontWeight": 600, "fill": "$--foreground" } + ] + }, + { "type": "text", "id": "vc021", "text": "This paragraph has bold text, italic text…", "fontSize": 12, "fill": "$--muted-foreground" } + ] + }, + { + "type": "frame", + "id": "vc022", + "name": "note2-modified", + "width": "fill_container", + "padding": [10, 16], + "gap": 4, + "layout": "vertical", + "stroke": { "align": "inside", "thickness": { "bottom": 1 }, "fill": "$--border" }, + "children": [ + { + "type": "frame", + "id": "vc023", + "name": "titleRow", + "gap": 6, + "alignItems": "center", + "children": [ + { "type": "ellipse", "id": "vc024", "name": "modifiedDot", "fill": "$--accent-orange", "width": 6, "height": 6 }, + { "type": "text", "id": "vc025", "text": "Facebook Ads Strategy", "fontSize": 13, "fontWeight": 600, "fill": "$--foreground" } + ] + }, + { "type": "text", "id": "vc026", "text": "Lookalike audiences from newsletter subscribers…", "fontSize": 12, "fill": "$--muted-foreground" } + ] + }, + { + "type": "frame", + "id": "vc027", + "name": "note3-added", + "width": "fill_container", + "padding": [10, 16], + "gap": 4, + "layout": "vertical", + "children": [ + { + "type": "frame", + "id": "vc028", + "name": "titleRow", + "gap": 6, + "alignItems": "center", + "children": [ + { "type": "ellipse", "id": "vc029", "name": "modifiedDot", "fill": "$--accent-orange", "width": 6, "height": 6 }, + { "type": "text", "id": "vc030", "text": "AI Agents Primer", "fontSize": 13, "fontWeight": 600, "fill": "$--foreground" } + ] + }, + { "type": "text", "id": "vc031", "text": "AI agents are autonomous systems that can plan…", "fontSize": 12, "fill": "$--muted-foreground" } + ] + } + ] + } + ] + }, + { + "type": "frame", + "id": "vc100", + "x": 600, + "y": 0, + "name": "Changes — empty state (0 pending)", + "clip": true, + "width": 550, + "height": 400, + "fill": "$--background", + "layout": "horizontal", + "children": [ + { + "type": "frame", + "id": "vc101", + "name": "Sidebar (no Changes item)", + "width": 250, + "height": "fill_container", + "fill": "$--sidebar", + "layout": "vertical", + "children": [ + { + "type": "frame", + "id": "vc102", + "name": "Filters", + "width": "fill_container", + "layout": "vertical", + "gap": 1, + "padding": [8, 8], + "stroke": { "align": "inside", "thickness": { "bottom": 1 }, "fill": "$--border" }, + "children": [ + { + "type": "frame", + "id": "vc103", + "name": "filterAll-active", + "width": "fill_container", + "fill": "#4a9eff18", + "cornerRadius": 6, + "gap": 8, + "padding": [6, 16], + "alignItems": "center", + "children": [ + { "type": "text", "id": "vc104", "text": "All Notes", "fontSize": 13, "fontWeight": 500, "fill": "$--primary" } + ] + }, + { + "type": "frame", + "id": "vc105", + "name": "filterFavorites", + "width": "fill_container", + "cornerRadius": 6, + "gap": 8, + "padding": [6, 16], + "alignItems": "center", + "children": [ + { "type": "text", "id": "vc106", "text": "Favorites", "fontSize": 13, "fill": "$--foreground" } + ] + }, + { + "type": "frame", + "id": "vc107", + "name": "filterTrash", + "width": "fill_container", + "cornerRadius": 6, + "gap": 8, + "padding": [6, 16], + "alignItems": "center", + "children": [ + { "type": "text", "id": "vc108", "text": "Trash", "fontSize": 13, "fill": "$--foreground" } + ] + } + ] + }, + { + "type": "frame", + "id": "vc109", + "name": "annotation", + "width": "fill_container", + "padding": [12, 16], + "children": [ + { "type": "text", "id": "vc110", "text": "← No \"Changes\" item when 0 pending", "fontSize": 11, "fill": "$--muted-foreground", "fontStyle": "italic" } + ] + } + ] + }, + { + "type": "frame", + "id": "vc111", + "name": "NoteList: All Notes", + "width": 300, + "height": "fill_container", + "fill": "$--card", + "layout": "vertical", + "stroke": { "align": "inside", "thickness": { "right": 1 }, "fill": "$--border" }, + "children": [ + { + "type": "frame", + "id": "vc112", + "name": "header", + "width": "fill_container", + "height": 45, + "padding": [0, 16], + "alignItems": "center", + "stroke": { "align": "inside", "thickness": { "bottom": 1 }, "fill": "$--border" }, + "children": [ + { "type": "text", "id": "vc113", "text": "Notes", "fontSize": 14, "fontWeight": 600, "fill": "$--foreground" } + ] + }, + { + "type": "frame", + "id": "vc114", + "name": "notesList", + "width": "fill_container", + "height": "fill_container", + "layout": "vertical", + "children": [ + { + "type": "frame", + "id": "vc115", + "name": "note-no-dot", + "width": "fill_container", + "padding": [10, 16], + "gap": 4, + "layout": "vertical", + "stroke": { "align": "inside", "thickness": { "bottom": 1 }, "fill": "$--border" }, + "children": [ + { "type": "text", "id": "vc116", "text": "Build Laputa App", "fontSize": 13, "fontWeight": 600, "fill": "$--foreground" }, + { "type": "text", "id": "vc117", "text": "No orange dot — all committed", "fontSize": 12, "fill": "$--muted-foreground" } + ] + } + ] + } + ] + } + ] + }, + { + "type": "frame", + "id": "vc200", + "x": 0, + "y": 560, + "name": "Changes — real-time update (note disappears after save)", + "clip": true, + "width": 800, + "height": 300, + "fill": "$--background", + "layout": "horizontal", + "gap": 40, + "padding": [20, 20], + "children": [ + { + "type": "frame", + "id": "vc201", + "name": "Before: 3 pending", + "width": 340, + "height": "fill_container", + "fill": "$--card", + "layout": "vertical", + "cornerRadius": 8, + "stroke": { "align": "inside", "thickness": 1, "fill": "$--border" }, + "children": [ + { + "type": "frame", + "id": "vc202", + "name": "header", + "width": "fill_container", + "height": 36, + "padding": [0, 12], + "alignItems": "center", + "stroke": { "align": "inside", "thickness": { "bottom": 1 }, "fill": "$--border" }, + "children": [ + { "type": "text", "id": "vc203", "text": "Changes (before save)", "fontSize": 12, "fontWeight": 600, "fill": "$--foreground" } + ] + }, + { + "type": "frame", + "id": "vc204", + "name": "item1", + "width": "fill_container", + "padding": [8, 12], + "gap": 6, + "alignItems": "center", + "stroke": { "align": "inside", "thickness": { "bottom": 1 }, "fill": "$--border" }, + "children": [ + { "type": "ellipse", "id": "vc205", "fill": "$--accent-orange", "width": 6, "height": 6 }, + { "type": "text", "id": "vc206", "text": "Build Laputa App", "fontSize": 12, "fill": "$--foreground" } + ] + }, + { + "type": "frame", + "id": "vc207", + "name": "item2-highlight", + "width": "fill_container", + "padding": [8, 12], + "gap": 6, + "fill": "#F5750010", + "alignItems": "center", + "stroke": { "align": "inside", "thickness": { "bottom": 1 }, "fill": "$--border" }, + "children": [ + { "type": "ellipse", "id": "vc208", "fill": "$--accent-orange", "width": 6, "height": 6 }, + { "type": "text", "id": "vc209", "text": "Facebook Ads Strategy ← saving…", "fontSize": 12, "fontWeight": 500, "fill": "$--accent-orange" } + ] + }, + { + "type": "frame", + "id": "vc210", + "name": "item3", + "width": "fill_container", + "padding": [8, 12], + "gap": 6, + "alignItems": "center", + "children": [ + { "type": "ellipse", "id": "vc211", "fill": "$--accent-orange", "width": 6, "height": 6 }, + { "type": "text", "id": "vc212", "text": "AI Agents Primer", "fontSize": 12, "fill": "$--foreground" } + ] + } + ] + }, + { + "type": "frame", + "id": "vc220", + "name": "After: 2 pending (note committed)", + "width": 340, + "height": "fill_container", + "fill": "$--card", + "layout": "vertical", + "cornerRadius": 8, + "stroke": { "align": "inside", "thickness": 1, "fill": "$--border" }, + "children": [ + { + "type": "frame", + "id": "vc221", + "name": "header", + "width": "fill_container", + "height": 36, + "padding": [0, 12], + "alignItems": "center", + "stroke": { "align": "inside", "thickness": { "bottom": 1 }, "fill": "$--border" }, + "children": [ + { "type": "text", "id": "vc222", "text": "Changes (after save + commit)", "fontSize": 12, "fontWeight": 600, "fill": "$--foreground" } + ] + }, + { + "type": "frame", + "id": "vc223", + "name": "item1", + "width": "fill_container", + "padding": [8, 12], + "gap": 6, + "alignItems": "center", + "stroke": { "align": "inside", "thickness": { "bottom": 1 }, "fill": "$--border" }, + "children": [ + { "type": "ellipse", "id": "vc224", "fill": "$--accent-orange", "width": 6, "height": 6 }, + { "type": "text", "id": "vc225", "text": "Build Laputa App", "fontSize": 12, "fill": "$--foreground" } + ] + }, + { + "type": "frame", + "id": "vc226", + "name": "item2", + "width": "fill_container", + "padding": [8, 12], + "gap": 6, + "alignItems": "center", + "children": [ + { "type": "ellipse", "id": "vc227", "fill": "$--accent-orange", "width": 6, "height": 6 }, + { "type": "text", "id": "vc228", "text": "AI Agents Primer", "fontSize": 12, "fill": "$--foreground" } + ] + }, + { + "type": "frame", + "id": "vc229", + "name": "removedNote", + "width": "fill_container", + "padding": [12, 12], + "children": [ + { "type": "text", "id": "vc230", "text": "Facebook Ads Strategy removed (committed)", "fontSize": 11, "fontStyle": "italic", "fill": "$--muted-foreground" } + ] + } + ] + } + ] + } + ], + "variables": {} +} \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index 8564f4f6..7b502aa8 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -246,7 +246,7 @@ function App() { /> - setShowSettings(true)} onOpenLocalFolder={handleOpenLocalFolder} onConnectGitHub={() => setShowGitHubVault(true)} hasGitHub={!!settings.github_token} /> + setShowSettings(true)} onOpenLocalFolder={handleOpenLocalFolder} onConnectGitHub={() => setShowGitHubVault(true)} onClickPending={() => setSelection({ kind: 'filter', filter: 'changes' })} hasGitHub={!!settings.github_token} /> setToastMessage(null)} /> setShowQuickOpen(false)} /> setShowCreateTypeDialog(false)} onCreate={handleCreateType} /> diff --git a/src/components/NoteList.test.tsx b/src/components/NoteList.test.tsx index 66d53c50..c21ee357 100644 --- a/src/components/NoteList.test.tsx +++ b/src/components/NoteList.test.tsx @@ -896,4 +896,52 @@ describe('NoteList — virtual list with large datasets', () => { fireEvent.click(screen.getByText('Note 50')) expect(noopReplace).toHaveBeenCalledWith(entries[50]) }) + + describe('changes filter', () => { + const changesSelection: SidebarSelection = { kind: 'filter', filter: 'changes' } + const modifiedFiles = [ + { path: mockEntries[0].path, relativePath: 'project/26q1-laputa-app.md', status: 'modified' as const }, + { path: mockEntries[1].path, relativePath: 'note/facebook-ads-strategy.md', status: 'modified' as const }, + ] + + it('shows only modified notes in changes view', () => { + render( + + ) + expect(screen.getByText('Build Laputa App')).toBeInTheDocument() + expect(screen.getByText('Facebook Ads Strategy')).toBeInTheDocument() + expect(screen.queryByText('Matteo Cellini')).not.toBeInTheDocument() + expect(screen.queryByText('Kickoff Meeting')).not.toBeInTheDocument() + }) + + it('shows header title "Changes"', () => { + render( + + ) + expect(screen.getByText('Changes')).toBeInTheDocument() + }) + + it('shows empty state when no modified files', () => { + render( + + ) + expect(screen.getByText('No pending changes')).toBeInTheDocument() + }) + + it('updates list when modifiedFiles changes', () => { + const { rerender } = render( + + ) + expect(screen.getByText('Build Laputa App')).toBeInTheDocument() + expect(screen.getByText('Facebook Ads Strategy')).toBeInTheDocument() + + // Simulate one file being committed (removed from modifiedFiles) + const fewerModified = [modifiedFiles[0]] + rerender( + + ) + expect(screen.getByText('Build Laputa App')).toBeInTheDocument() + expect(screen.queryByText('Facebook Ads Strategy')).not.toBeInTheDocument() + }) + }) }) diff --git a/src/components/NoteList.tsx b/src/components/NoteList.tsx index 2b3d4414..da80bbce 100644 --- a/src/components/NoteList.tsx +++ b/src/components/NoteList.tsx @@ -99,6 +99,7 @@ function resolveHeaderTitle(selection: SidebarSelection, typeDocument: VaultEntr if (typeDocument) return typeDocument.title if (selection.kind === 'filter' && selection.filter === 'archived') return 'Archive' if (selection.kind === 'filter' && selection.filter === 'trash') return 'Trash' + if (selection.kind === 'filter' && selection.filter === 'changes') return 'Changes' return 'Notes' } @@ -146,13 +147,13 @@ function ListViewHeader({ typeDocument, isTrashView, expiredTrashCount, typeEntr ) } -function ListView({ typeDocument, isTrashView, expiredTrashCount, searched, query, renderItem, typeEntryMap, onClickNote }: { - typeDocument: VaultEntry | null; isTrashView: boolean; expiredTrashCount: number +function ListView({ typeDocument, isTrashView, isChangesView, expiredTrashCount, searched, query, renderItem, typeEntryMap, onClickNote }: { + typeDocument: VaultEntry | null; isTrashView: boolean; isChangesView?: boolean; expiredTrashCount: number searched: VaultEntry[]; query: string renderItem: (entry: VaultEntry) => React.ReactNode typeEntryMap: Record; onClickNote: (entry: VaultEntry, e: React.MouseEvent) => void }) { - const emptyText = isTrashView ? 'Trash is empty' : (query ? 'No matching notes' : 'No notes found') + const emptyText = isChangesView ? 'No pending changes' : isTrashView ? 'Trash is empty' : (query ? 'No matching notes' : 'No notes found') const hasHeader = typeDocument || (isTrashView && expiredTrashCount > 0) if (searched.length === 0) { @@ -208,11 +209,13 @@ function routeNoteClick( interface NoteListDataParams { entries: VaultEntry[]; selection: SidebarSelection; allContent: Record query: string; listSort: SortOption; listDirection: SortDirection + modifiedPathSet: Set } -function useNoteListData({ entries, selection, allContent, query, listSort, listDirection }: NoteListDataParams) { +function useNoteListData({ entries, selection, allContent, query, listSort, listDirection, modifiedPathSet }: NoteListDataParams) { const isEntityView = selection.kind === 'entity' const isTrashView = selection.kind === 'filter' && selection.filter === 'trash' + const isChangesView = selection.kind === 'filter' && selection.filter === 'changes' const typeDocument = useMemo(() => { if (selection.kind !== 'sectionGroup') return null @@ -221,9 +224,13 @@ function useNoteListData({ entries, selection, allContent, query, listSort, list const searched = useMemo(() => { if (isEntityView) return [] + if (isChangesView) { + const sorted = [...entries.filter((e) => modifiedPathSet.has(e.path))].sort(getSortComparator(listSort, listDirection)) + return filterByQuery(sorted, query) + } const sorted = [...filterEntries(entries, selection)].sort(getSortComparator(listSort, listDirection)) return filterByQuery(sorted, query) - }, [entries, selection, isEntityView, listSort, listDirection, query]) + }, [entries, selection, isEntityView, isChangesView, listSort, listDirection, query, modifiedPathSet]) const searchedGroups = useMemo(() => { if (!isEntityView) return [] @@ -236,7 +243,7 @@ function useNoteListData({ entries, selection, allContent, query, listSort, list [isTrashView, searched], ) - return { isEntityView, isTrashView, typeDocument, searched, searchedGroups, expiredTrashCount } + return { isEntityView, isTrashView, isChangesView, typeDocument, searched, searchedGroups, expiredTrashCount } } // --- Main component --- @@ -265,7 +272,7 @@ function NoteListInner({ entries, selection, selectedNote, allContent, modifiedF const listConfig = sortPrefs['__list__'] ?? { option: 'modified' as SortOption, direction: 'desc' as SortDirection } const listSort = listConfig.option const listDirection = listConfig.direction - const { isEntityView, isTrashView, typeDocument, searched, searchedGroups, expiredTrashCount } = useNoteListData({ entries, selection, allContent, query, listSort, listDirection }) + const { isEntityView, isTrashView, isChangesView, typeDocument, searched, searchedGroups, expiredTrashCount } = useNoteListData({ entries, selection, allContent, query, listSort, listDirection, modifiedPathSet }) const handleClickNote = useCallback((entry: VaultEntry, e: React.MouseEvent) => { routeNoteClick(entry, e, onSelectNote, onReplaceActiveTab) @@ -300,7 +307,7 @@ function NoteListInner({ entries, selection, selectedNote, allContent, modifiedF {isEntityView && selection.kind === 'entity' ? ( ) : ( - + )} diff --git a/src/components/Sidebar.test.tsx b/src/components/Sidebar.test.tsx index d74e56f6..fb71b18f 100644 --- a/src/components/Sidebar.test.tsx +++ b/src/components/Sidebar.test.tsx @@ -334,7 +334,26 @@ describe('Sidebar', () => { it('shows badge on commit button when modified files exist', () => { render( {}} modifiedCount={3} onCommitPush={() => {}} />) - expect(screen.getByText('3')).toBeInTheDocument() + expect(screen.getByText('Commit & Push')).toBeInTheDocument() + const badges = screen.getAllByText('3') + expect(badges.length).toBeGreaterThanOrEqual(1) + }) + + it('shows Changes nav item when modifiedCount > 0', () => { + render( {}} modifiedCount={5} />) + expect(screen.getByText('Changes')).toBeInTheDocument() + }) + + it('hides Changes nav item when modifiedCount is 0', () => { + render( {}} modifiedCount={0} />) + expect(screen.queryByText('Changes')).not.toBeInTheDocument() + }) + + it('calls onSelect with changes filter when clicking Changes', () => { + const onSelect = vi.fn() + render() + fireEvent.click(screen.getByText('Changes')) + expect(onSelect).toHaveBeenCalledWith({ kind: 'filter', filter: 'changes' }) }) describe('dynamic custom type sections', () => { diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index d941fd58..7ebdc53c 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -12,7 +12,7 @@ import { import { CSS } from '@dnd-kit/utilities' import { FileText, Star, Wrench, Flask, Target, ArrowsClockwise, - Users, CalendarBlank, Tag, TagSimple, Trash, StackSimple, Archive, CaretLeft, + Users, CalendarBlank, Tag, TagSimple, Trash, StackSimple, Archive, CaretLeft, GitDiff, } from '@phosphor-icons/react' import { GitCommitHorizontal, SlidersHorizontal } from 'lucide-react' import { @@ -296,6 +296,9 @@ export const Sidebar = memo(function Sidebar({ onSelect({ kind: 'filter', filter: 'archived' })} /> onSelect({ kind: 'filter', filter: 'trash' })} /> + {modifiedCount > 0 && ( + onSelect({ kind: 'filter', filter: 'changes' })} /> + )} {/* Sections header + visibility popover */} diff --git a/src/components/StatusBar.test.tsx b/src/components/StatusBar.test.tsx index b19faedc..0bedebe5 100644 --- a/src/components/StatusBar.test.tsx +++ b/src/components/StatusBar.test.tsx @@ -133,4 +133,20 @@ describe('StatusBar', () => { // Menu should close after clicking an action expect(screen.queryByText('Open local folder')).not.toBeInTheDocument() }) + + it('calls onClickPending when clicking the pending count', () => { + const onClickPending = vi.fn() + render( + + ) + fireEvent.click(screen.getByTestId('status-modified-count')) + expect(onClickPending).toHaveBeenCalledOnce() + }) + + it('pending count has title for accessibility', () => { + render( + + ) + expect(screen.getByTitle('View pending changes')).toBeInTheDocument() + }) }) diff --git a/src/components/StatusBar.tsx b/src/components/StatusBar.tsx index b2e5faae..0f94fd37 100644 --- a/src/components/StatusBar.tsx +++ b/src/components/StatusBar.tsx @@ -15,6 +15,7 @@ interface StatusBarProps { onOpenSettings?: () => void onOpenLocalFolder?: () => void onConnectGitHub?: () => void + onClickPending?: () => void hasGitHub?: boolean } @@ -104,7 +105,7 @@ const ICON_STYLE = { display: 'flex', alignItems: 'center', gap: 4 } as const const DISABLED_STYLE = { display: 'flex', alignItems: 'center', opacity: 0.4, cursor: 'not-allowed' } as const const SEP_STYLE = { color: 'var(--border)' } as const -export function StatusBar({ noteCount, modifiedCount = 0, vaultPath, vaults, onSwitchVault, onOpenSettings, onOpenLocalFolder, onConnectGitHub, hasGitHub }: StatusBarProps) { +export function StatusBar({ noteCount, modifiedCount = 0, vaultPath, vaults, onSwitchVault, onOpenSettings, onOpenLocalFolder, onConnectGitHub, onClickPending, hasGitHub }: StatusBarProps) { return (