Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions packages/react/src/PageLayout/PageLayout.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,69 @@ describe('PageLayout', async () => {
fireEvent.lostPointerCapture(divider, {pointerId: 1})
expect(pane!.style.willChange).toBe('')
})

it('should set contain-intrinsic-size during pointer drag', async () => {
const {container} = render(
<PageLayout>
<PageLayout.Pane resizable>
<Placeholder height={320} label="Pane" />
</PageLayout.Pane>
<PageLayout.Content>
<Placeholder height={640} label="Content" />
</PageLayout.Content>
</PageLayout>,
)

const pane = container.querySelector<HTMLElement>('[class*="Pane"][data-resizable]')
const contentWrapper = container.querySelector<HTMLElement>('[class*="ContentWrapper"]')
const divider = await screen.findByRole('slider')

// Before drag - no contain-intrinsic-size
expect(pane!.style.containIntrinsicSize).toBe('')
expect(contentWrapper!.style.containIntrinsicSize).toBe('')

// Start drag - contain-intrinsic-size should be set with auto keyword
fireEvent.pointerDown(divider, {clientX: 300, clientY: 200, pointerId: 1})
expect(pane!.style.containIntrinsicSize).toMatch(/^auto \d+(\.\d+)?px auto \d+(\.\d+)?px$/)
expect(contentWrapper!.style.containIntrinsicSize).toMatch(/^auto \d+(\.\d+)?px auto \d+(\.\d+)?px$/)

// End drag - contain-intrinsic-size should be removed
fireEvent.lostPointerCapture(divider, {pointerId: 1})
expect(pane!.style.containIntrinsicSize).toBe('')
expect(contentWrapper!.style.containIntrinsicSize).toBe('')
})

it('should set contain-intrinsic-size during keyboard resize', async () => {
const {container} = render(
<PageLayout>
<PageLayout.Pane resizable>
<Placeholder height={320} label="Pane" />
</PageLayout.Pane>
<PageLayout.Content>
<Placeholder height={640} label="Content" />
</PageLayout.Content>
</PageLayout>,
)

const pane = container.querySelector<HTMLElement>('[class*="Pane"][data-resizable]')
const contentWrapper = container.querySelector<HTMLElement>('[class*="ContentWrapper"]')
const divider = await screen.findByRole('slider')

// Before interaction - no contain-intrinsic-size
expect(pane!.style.containIntrinsicSize).toBe('')
expect(contentWrapper!.style.containIntrinsicSize).toBe('')

// Start keyboard resize - should set with auto keyword
fireEvent.focus(divider)
fireEvent.keyDown(divider, {key: 'ArrowRight'})
expect(pane!.style.containIntrinsicSize).toMatch(/^auto \d+(\.\d+)?px auto \d+(\.\d+)?px$/)
expect(contentWrapper!.style.containIntrinsicSize).toMatch(/^auto \d+(\.\d+)?px auto \d+(\.\d+)?px$/)

// End keyboard resize - contain-intrinsic-size should be removed
fireEvent.keyUp(divider, {key: 'ArrowRight'})
expect(pane!.style.containIntrinsicSize).toBe('')
expect(contentWrapper!.style.containIntrinsicSize).toBe('')
})
})

describe('PageLayout.Content', () => {
Expand Down
16 changes: 16 additions & 0 deletions packages/react/src/PageLayout/paneUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ export function setDraggingStyles({handle, pane, contentWrapper}: DraggingStyles
handle?.style.setProperty('--draggable-handle--drag-opacity', '1')
handle?.style.setProperty('--draggable-handle--transition', 'none')

// Capture current dimensions and set contain-intrinsic-size BEFORE setting data-dragging
// This ensures the element maintains its size when content-visibility: auto is applied
// Use 'auto' for width since it changes during drag, allowing browser to track actual size
if (pane) {
const rect = pane.getBoundingClientRect()
pane.style.setProperty('contain-intrinsic-size', `auto ${rect.width}px auto ${rect.height}px`)
}
if (contentWrapper) {
const rect = contentWrapper.getBoundingClientRect()
contentWrapper.style.setProperty('contain-intrinsic-size', `auto ${rect.width}px auto ${rect.height}px`)
}

// Set attribute for CSS containment (O(1) direct selector, not descendant)
pane?.setAttribute(DATA_DRAGGING_ATTR, 'true')
contentWrapper?.setAttribute(DATA_DRAGGING_ATTR, 'true')
Expand All @@ -28,4 +40,8 @@ export function removeDraggingStyles({handle, pane, contentWrapper}: DraggingSty

pane?.removeAttribute(DATA_DRAGGING_ATTR)
contentWrapper?.removeAttribute(DATA_DRAGGING_ATTR)

// Remove contain-intrinsic-size after removing data-dragging
pane?.style.removeProperty('contain-intrinsic-size')
contentWrapper?.style.removeProperty('contain-intrinsic-size')
}
Loading