Skip to content

feat(web): make left column width adjustable by codex#205

Open
yzs981130 wants to merge 2 commits intotiann:mainfrom
yzs981130:codex/make-left-column-width-adjustable
Open

feat(web): make left column width adjustable by codex#205
yzs981130 wants to merge 2 commits intotiann:mainfrom
yzs981130:codex/make-left-column-width-adjustable

Conversation

@yzs981130
Copy link

Motivation

  • Ensure user-resized sessions sidebar width.

Description

  • Added state and refs (sidebarWidth, sidebarWidthRef, isDraggingSidebar) to manage size.
  • Consolidated width clamping, state update, and localStorage persistence into a single updateSidebarWidth helper and used it for pointer drag and resize-reclamp actions.

Codex Task

@yzs981130 yzs981130 changed the title Codex/make left column width adjustable feat(web): make left column width adjustable by codex Feb 23, 2026
setSidebarWidth(clamped)
if (typeof window !== 'undefined') {
window.localStorage.setItem(SIDEBAR_WIDTH_STORAGE_KEY, String(clamped))
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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)
}

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Minor] Synchronous localStorage.setItem on every pointermove may cause resize jank; consider persisting on pointerup or debouncing web/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)

@tiann tiann force-pushed the codex/make-left-column-width-adjustable branch from e3cbda7 to 7050c9b Compare March 8, 2026 03:23
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Major] Drag state can stick if pointer released outside window; no pointer capture/cancel handling, so pointerup may not fire. Resize mode stuck, cursor/userSelect locked. Evidence web/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.setItem on every pointermove; synchronous write per frame → drag jank. Evidence web/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) => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant