mirror of
https://github.com/mudler/LocalAI.git
synced 2026-06-18 21:58:58 -04:00
fix(react-ui): restore sidebar collapse in dev + stop Talk page auto-scroll (#10383)
The sidebar collapse toggle silently no-op'd in dev builds. toggleCollapse ran its side effects (localStorage write + sidebar-collapse dispatch) inside the setCollapsed updater. StrictMode double-invokes updaters in dev to surface impurity, and the synchronous dispatch re-entered setState from the App/Sidebar listeners mid-update, so the toggle never committed. Production builds don't double-invoke, which is why only the dev server was affected. Compute next from current state and move the persist + broadcast into the handler body so the updater is pure. Also fix the Talk page anchoring to the transcript box on load. The transcript is its own overflow container, but scrollIntoView bubbles to every scrollable ancestor including the window, yanking the whole page down on mount. Scroll the transcript container directly instead. Assisted-by: Claude:claude-opus-4-8 [Claude Code] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
@@ -130,12 +130,14 @@ export default function Sidebar({ isOpen, onClose }) {
|
||||
}, [location.pathname])
|
||||
|
||||
const toggleCollapse = () => {
|
||||
setCollapsed(prev => {
|
||||
const next = !prev
|
||||
try { localStorage.setItem(COLLAPSED_KEY, String(next)) } catch (_) { /* ignore */ }
|
||||
window.dispatchEvent(new CustomEvent('sidebar-collapse', { detail: { collapsed: next } }))
|
||||
return next
|
||||
})
|
||||
// Side effects (persist + broadcast) live in the handler body, never inside
|
||||
// the setState updater: StrictMode double-invokes updaters in dev, and the
|
||||
// synchronous sidebar-collapse dispatch re-entered setState from the
|
||||
// listeners mid-update, so the toggle silently no-op'd in dev builds.
|
||||
const next = !collapsed
|
||||
try { localStorage.setItem(COLLAPSED_KEY, String(next)) } catch (_) { /* ignore */ }
|
||||
setCollapsed(next)
|
||||
window.dispatchEvent(new CustomEvent('sidebar-collapse', { detail: { collapsed: next } }))
|
||||
}
|
||||
|
||||
const toggleSection = (id) => {
|
||||
|
||||
@@ -127,9 +127,12 @@ export default function Talk() {
|
||||
.finally(() => setModelsLoading(false))
|
||||
}, [])
|
||||
|
||||
// Auto-scroll transcript
|
||||
// Auto-scroll the transcript's own overflow container. scrollIntoView bubbles
|
||||
// to every scrollable ancestor (incl. the window), which yanked the whole
|
||||
// page down to the transcript box on mount; scoping to the box avoids it.
|
||||
useEffect(() => {
|
||||
transcriptEndRef.current?.scrollIntoView({ behavior: 'smooth' })
|
||||
const box = transcriptEndRef.current?.parentElement
|
||||
box?.scrollTo({ top: box.scrollHeight, behavior: 'smooth' })
|
||||
}, [transcript])
|
||||
|
||||
// Mirror Chat.jsx: connect / disconnect client MCP servers as the user toggles them.
|
||||
|
||||
Reference in New Issue
Block a user