diff --git a/packages/react/src/PageLayout/PageLayout.test.tsx b/packages/react/src/PageLayout/PageLayout.test.tsx
index 5f022c5aea6..9d640f0fb8c 100644
--- a/packages/react/src/PageLayout/PageLayout.test.tsx
+++ b/packages/react/src/PageLayout/PageLayout.test.tsx
@@ -259,6 +259,35 @@ describe('PageLayout', async () => {
fireEvent.lostPointerCapture(divider, {pointerId: 1})
expect(pane!.style.willChange).toBe('')
})
+
+ it('should cleanup dragging styles on unmount mid-drag', async () => {
+ const {container, unmount} = render(
+
+
+
+
+
+
+
+ ,
+ )
+
+ const pane = container.querySelector('[class*="Pane"][data-resizable]')
+ const content = container.querySelector('[class*="PageLayoutContent"]')
+ const divider = await screen.findByRole('slider')
+
+ // Start drag
+ fireEvent.pointerDown(divider, {clientX: 300, clientY: 200, pointerId: 1})
+ expect(pane).toHaveAttribute('data-dragging', 'true')
+ expect(content).toHaveAttribute('data-dragging', 'true')
+
+ // Unmount mid-drag
+ unmount()
+
+ // Attributes should be cleaned up
+ expect(pane).not.toHaveAttribute('data-dragging')
+ expect(content).not.toHaveAttribute('data-dragging')
+ })
})
describe('PageLayout.Content', () => {
diff --git a/packages/react/src/PageLayout/PageLayout.tsx b/packages/react/src/PageLayout/PageLayout.tsx
index 943c9561d50..2d17911817f 100644
--- a/packages/react/src/PageLayout/PageLayout.tsx
+++ b/packages/react/src/PageLayout/PageLayout.tsx
@@ -244,10 +244,19 @@ const DragHandle = memo(function DragHandle({
// Dragging state as a ref - cheaper than reading from DOM style
const isDraggingRef = React.useRef(false)
+
+ // Cache DOM elements for cleanup - refs from context get cleared during unmount
+ const cachedHandleRef = React.useRef(null)
+ const cachedPaneRef = React.useRef(null)
+ const cachedContentRef = React.useRef(null)
// Set inline styles for drag optimizations - zero overhead at rest
const startDragging = React.useCallback(() => {
if (isDraggingRef.current) return
+ // Cache current element references for cleanup
+ cachedHandleRef.current = handleRef.current
+ cachedPaneRef.current = paneRef.current
+ cachedContentRef.current = contentRef.current
setDraggingStyles({
handle: handleRef.current,
pane: paneRef.current,
@@ -378,10 +387,20 @@ const DragHandle = memo(function DragHandle({
// Cleanup rAF on unmount to prevent stale callbacks
React.useEffect(() => {
return () => {
+ // Cancel pending rAF
if (rafIdRef.current !== null) {
cancelAnimationFrame(rafIdRef.current)
rafIdRef.current = null
}
+ // Clean up dragging state if unmounting mid-drag
+ // Use cached element references since refs from context get cleared during unmount
+ if (isDraggingRef.current) {
+ removeDraggingStyles({
+ handle: cachedHandleRef.current,
+ pane: cachedPaneRef.current,
+ content: cachedContentRef.current,
+ })
+ }
}
}, [])