fix(sidebar): unfreeze view after scan triggers history panel

forceView prop was overriding local activeView on every render. Once parent
set sidebarForceView='history' after starting a scan, it never cleared, so
clicks on other nav items were ignored. Treat forceView as a one-shot
trigger via the previous-prop pattern; user clicks afterward control view.
This commit is contained in:
Pouzor
2026-05-03 16:03:30 +02:00
parent 785be6a5dd
commit dfa4a9c849
2 changed files with 23 additions and 5 deletions
+11 -5
View File
@@ -43,13 +43,19 @@ interface SidebarProps {
}
export function Sidebar({ onAddNode, onAddGroupRect, onScan, onSave, onNodeApproved, forceView, highlightPendingId }: SidebarProps) {
const [_collapsed, setCollapsed] = useState(false)
const [_activeView, setActiveView] = useState<SidebarView>('canvas')
const [collapsed, setCollapsed] = useState(false)
const [activeView, setActiveView] = useState<SidebarView>(forceView ?? 'canvas')
const [prevForceView, setPrevForceView] = useState(forceView)
const logout = useAuthStore((s) => s.logout)
// When forceView is set, override local state without useEffect
const collapsed = forceView ? false : _collapsed
const activeView = forceView ?? _activeView
// forceView acts as a one-shot trigger from parent; user clicks afterwards still control view.
if (forceView !== prevForceView) {
setPrevForceView(forceView)
if (forceView) {
setActiveView(forceView)
setCollapsed(false)
}
}
const { nodes, hasUnsavedChanges, hideIp, toggleHideIp } = useCanvasStore()
@@ -267,6 +267,18 @@ describe('Sidebar', () => {
await waitFor(() => expect(screen.getByText('No scans yet')).toBeInTheDocument())
})
// Regression: forceView used to override local state on every render, freezing
// the sidebar on whichever view the parent forced (e.g. 'history' after a scan).
it('allows switching views after forceView is set by parent', async () => {
const { rerender } = render(<Sidebar {...defaultProps} forceView="history" />)
await waitFor(() => expect(screen.getByText('No scans yet')).toBeInTheDocument())
// Parent keeps forceView as 'history'; user clicks another nav item.
rerender(<Sidebar {...defaultProps} forceView="history" />)
fireEvent.click(screen.getByText('Pending Devices'))
await waitFor(() => expect(screen.getByText('No pending devices')).toBeInTheDocument())
expect(screen.queryByText('No scans yet')).not.toBeInTheDocument()
})
it('toggles Settings panel on Settings click', async () => {
render(<Sidebar {...defaultProps} />)
fireEvent.click(screen.getByText('Settings'))