feat(web): make left column width adjustable by codex#205
feat(web): make left column width adjustable by codex#205yzs981130 wants to merge 2 commits intotiann:mainfrom
Conversation
| setSidebarWidth(clamped) | ||
| if (typeof window !== 'undefined') { | ||
| window.localStorage.setItem(SIDEBAR_WIDTH_STORAGE_KEY, String(clamped)) | ||
| } |
There was a problem hiding this comment.
[MINOR] [PERF] localStorage write on every pointermove
Why this is a problem: pointermove fires at high frequency; localStorage.setItem is synchronous and can block the main thread, making the resize feel janky on lower-end devices. This path runs on every drag tick.
Suggested fix:
const updateSidebarWidth = useCallback((nextWidth: number) => {
const clamped = clampSidebarWidth(nextWidth)
if (sidebarWidthRef.current === clamped) return
sidebarWidthRef.current = clamped
setSidebarWidth(clamped)
}, [clampSidebarWidth])
const persistSidebarWidth = useCallback(() => {
if (typeof window !== 'undefined' && sidebarWidthRef.current != null) {
window.localStorage.setItem(SIDEBAR_WIDTH_STORAGE_KEY, String(sidebarWidthRef.current))
}
}, [])
const handlePointerUp = () => {
persistSidebarWidth()
setIsDraggingSidebar(false)
}There was a problem hiding this comment.
Findings
- [Minor] Synchronous
localStorage.setItemon everypointermovemay cause resize jank; consider persisting on pointerup or debouncingweb/src/router.tsx:129
Summary
- 1 minor perf issue. Residual risk: drag feels sluggish on low-end devices if left as-is.
Testing
- Not run (automation)
e3cbda7 to
7050c9b
Compare
There was a problem hiding this comment.
Findings
- [Major] Drag state can stick if pointer released outside window; no pointer capture/cancel handling, so
pointerupmay not fire. Resize mode stuck, cursor/userSelect locked. Evidenceweb/src/router.tsx:179,web/src/router.tsx:273.
Suggested fix:onPointerDown={(event) => { if (event.button !== 0) return event.preventDefault() event.currentTarget.setPointerCapture(event.pointerId) setIsDraggingSidebar(true) }} useEffect(() => { if (!isDraggingSidebar) return const stopDragging = (event: PointerEvent) => { ;(event.target as HTMLElement | null)?.releasePointerCapture?.(event.pointerId) setIsDraggingSidebar(false) } window.addEventListener('pointerup', stopDragging) window.addEventListener('pointercancel', stopDragging) return () => { window.removeEventListener('pointerup', stopDragging) window.removeEventListener('pointercancel', stopDragging) } }, [isDraggingSidebar])
- [Minor]
localStorage.setItemon everypointermove; synchronous write per frame → drag jank. Evidenceweb/src/router.tsx:129,web/src/router.tsx:184.
Suggested fix:const updateSidebarWidth = useCallback((nextWidth: number, persist = true) => { const clamped = clampSidebarWidth(nextWidth) sidebarWidthRef.current = clamped setSidebarWidth(clamped) if (persist && typeof window !== 'undefined') { window.localStorage.setItem(SIDEBAR_WIDTH_STORAGE_KEY, String(clamped)) } }, [clampSidebarWidth]) const handlePointerMove = (event: PointerEvent) => { updateSidebarWidth(event.clientX, false) } const handlePointerUp = () => { if (sidebarWidthRef.current != null) { updateSidebarWidth(sidebarWidthRef.current, true) } setIsDraggingSidebar(false) }
Summary
- Review mode: initial
- 2 findings. Residual risk: drag UX regressions; no web tests.
Testing
- Not run (automation)
- Suggested: manual drag resize, release outside window, window resize clamp
| role="separator" | ||
| aria-label="Resize sessions sidebar" | ||
| aria-orientation="vertical" | ||
| onPointerDown={(event) => { |
There was a problem hiding this comment.
[MAJOR] Drag state can stick if pointer released outside window; no pointer capture/cancel handling, so pointerup may not fire. Resize mode stuck.
Suggested fix:
onPointerDown={(event) => {
if (event.button !== 0) return
event.preventDefault()
event.currentTarget.setPointerCapture(event.pointerId)
setIsDraggingSidebar(true)
}}
useEffect(() => {
if (!isDraggingSidebar) return
const stopDragging = (event: PointerEvent) => {
;(event.target as HTMLElement | null)?.releasePointerCapture?.(event.pointerId)
setIsDraggingSidebar(false)
}
window.addEventListener('pointerup', stopDragging)
window.addEventListener('pointercancel', stopDragging)
return () => {
window.removeEventListener('pointerup', stopDragging)
window.removeEventListener('pointercancel', stopDragging)
}
}, [isDraggingSidebar])| sidebarWidthRef.current = clamped | ||
| setSidebarWidth(clamped) | ||
| if (typeof window !== 'undefined') { | ||
| window.localStorage.setItem(SIDEBAR_WIDTH_STORAGE_KEY, String(clamped)) |
There was a problem hiding this comment.
[MINOR] localStorage.setItem on every pointermove; synchronous write per frame → drag jank.
Suggested fix:
const updateSidebarWidth = useCallback((nextWidth: number, persist = true) => {
const clamped = clampSidebarWidth(nextWidth)
sidebarWidthRef.current = clamped
setSidebarWidth(clamped)
if (persist && typeof window !== 'undefined') {
window.localStorage.setItem(SIDEBAR_WIDTH_STORAGE_KEY, String(clamped))
}
}, [clampSidebarWidth])
const handlePointerMove = (event: PointerEvent) => {
updateSidebarWidth(event.clientX, false)
}
const handlePointerUp = () => {
if (sidebarWidthRef.current != null) {
updateSidebarWidth(sidebarWidthRef.current, true)
}
setIsDraggingSidebar(false)
}
Motivation
Description
sidebarWidth,sidebarWidthRef,isDraggingSidebar) to manage size.updateSidebarWidthhelper and used it for pointer drag and resize-reclamp actions.Codex Task