| ... | ... | @@ -369,9 +369,6 @@ function SidebarRail({ |
| 369 | 369 | const suppressClickRef = React.useRef(false); |
| 370 | 370 | const resolvedResizable = sidebarInstance?.resizable ?? null; |
| 371 | 371 | const latestResizable = React.useRef(resolvedResizable); |
| 372 | | React.useLayoutEffect(() => { |
| 373 | | latestResizable.current = resolvedResizable; |
| 374 | | }, [resolvedResizable]); |
| 375 | 372 | const canResize = resolvedResizable !== null && open; |
| 376 | 373 | const railLabel = canResize ? "Resize Sidebar" : "Toggle Sidebar"; |
| 377 | 374 | const railTitle = canResize ? "Drag to resize sidebar" : "Toggle Sidebar"; |
| ... | ... | @@ -390,14 +387,22 @@ function SidebarRail({ |
| 390 | 387 | sidebarContainer.getBoundingClientRect().width, |
| 391 | 388 | resolvedResizable, |
| 392 | 389 | ); |
| 393 | | const transitionTargets = [ |
| 390 | // Drag frames write width to the gap and container only. Changing the |
| 391 | // inherited --sidebar-width on the wrapper restyles the whole app, so it is |
| 392 | // written once when the drag commits. |
| 393 | const widthTargets = [ |
| 394 | 394 | sidebarRoot.querySelector<HTMLElement>("[data-slot='sidebar-gap']"), |
| 395 | 395 | sidebarContainer, |
| 396 | 396 | ].filter((element): element is HTMLElement => element !== null); |
| 397 | | transitionTargets.forEach((element) => { |
| 397 | const setTargetWidth = (value: number) => { |
| 398 | widthTargets.forEach((element) => { |
| 399 | element.style.setProperty("width", `${value}px`); |
| 400 | }); |
| 401 | }; |
| 402 | widthTargets.forEach((element) => { |
| 398 | 403 | element.style.setProperty("transition-duration", "0ms"); |
| 399 | 404 | }); |
| 400 | | wrapper.style.setProperty("--sidebar-width", `${width}px`); |
| 405 | setTargetWidth(width); |
| 401 | 406 | |
| 402 | 407 | return { |
| 403 | 408 | width, |
| ... | ... | @@ -416,12 +421,13 @@ function SidebarRail({ |
| 416 | 421 | wrapper, |
| 417 | 422 | }) ?? true; |
| 418 | 423 | if (accepted) { |
| 419 | | wrapper.style.setProperty("--sidebar-width", `${nextWidth}px`); |
| 424 | setTargetWidth(nextWidth); |
| 420 | 425 | width = nextWidth; |
| 421 | 426 | } |
| 422 | 427 | return width; |
| 423 | 428 | }, |
| 424 | 429 | finish(finalWidth, moved) { |
| 430 | wrapper.style.setProperty("--sidebar-width", `${finalWidth}px`); |
| 425 | 431 | suppressClickRef.current = moved; |
| 426 | 432 | const options = latestResizable.current; |
| 427 | 433 | if (options?.storageKey) { |
| ... | ... | @@ -434,12 +440,20 @@ function SidebarRail({ |
| 434 | 440 | options?.onResize?.(finalWidth); |
| 435 | 441 | }, |
| 436 | 442 | cleanup() { |
| 437 | | transitionTargets.forEach((element) => { |
| 443 | widthTargets.forEach((element) => { |
| 444 | element.style.removeProperty("width"); |
| 438 | 445 | element.style.removeProperty("transition-duration"); |
| 439 | 446 | }); |
| 440 | 447 | }, |
| 441 | 448 | }; |
| 442 | | }); |
| 449 | // Toggling the sidebar cancels a drag so the inline width never pins a |
| 450 | // collapsed sidebar open. |
| 451 | }, String(open)); |
| 452 | React.useLayoutEffect(() => { |
| 453 | latestResizable.current = resolvedResizable; |
| 454 | // Bounds follow the window; keep an active drag's inline width inside them. |
| 455 | resize.refresh(); |
| 456 | }, [resolvedResizable]); |
| 443 | 457 | |
| 444 | 458 | const handleClick = React.useCallback( |
| 445 | 459 | (event: React.MouseEvent<HTMLButtonElement>) => { |