Skip to content
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 @@
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
fireEvent.pointerDown(divider, {clientX: 300, clientY: 200, pointerId: 1})
expect(pane!.style.containIntrinsicSize).toMatch(/^\d+(\.\d+)?px \d+(\.\d+)?px$/)

Check failure on line 285 in packages/react/src/PageLayout/PageLayout.test.tsx

View workflow job for this annotation

GitHub Actions / copilot

[@primer/react (chromium)] src/PageLayout/PageLayout.test.tsx > PageLayout > PageLayout.Pane > should set contain-intrinsic-size during pointer drag

AssertionError: expected 'auto 299px auto 640px' to match /^\d+(\.\d+)?px \d+(\.\d+)?px$/ - Expected: /^\d+(\.\d+)?px \d+(\.\d+)?px$/ + Received: "auto 299px auto 640px" ❯ toMatch src/PageLayout/PageLayout.test.tsx:285:47
expect(contentWrapper!.style.containIntrinsicSize).toMatch(/^\d+(\.\d+)?px \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
fireEvent.focus(divider)
fireEvent.keyDown(divider, {key: 'ArrowRight'})
expect(pane!.style.containIntrinsicSize).toMatch(/^\d+(\.\d+)?px \d+(\.\d+)?px$/)

Check failure on line 317 in packages/react/src/PageLayout/PageLayout.test.tsx

View workflow job for this annotation

GitHub Actions / copilot

[@primer/react (chromium)] src/PageLayout/PageLayout.test.tsx > PageLayout > PageLayout.Pane > should set contain-intrinsic-size during keyboard resize

AssertionError: expected 'auto 299px auto 640px' to match /^\d+(\.\d+)?px \d+(\.\d+)?px$/ - Expected: /^\d+(\.\d+)?px \d+(\.\d+)?px$/ + Received: "auto 299px auto 640px" ❯ toMatch src/PageLayout/PageLayout.test.tsx:317:47
expect(contentWrapper!.style.containIntrinsicSize).toMatch(/^\d+(\.\d+)?px \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
15 changes: 15 additions & 0 deletions packages/react/src/PageLayout/paneUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ 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
if (pane) {
const rect = pane.getBoundingClientRect()
pane.style.setProperty('contain-intrinsic-size', `${rect.width}px ${rect.height}px`)
}
if (contentWrapper) {
const rect = contentWrapper.getBoundingClientRect()
contentWrapper.style.setProperty('contain-intrinsic-size', `${rect.width}px ${rect.height}px`)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@copilot should we use auto width here instead of a fixed width, since we're changing width or is this ok

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch! Updated to use auto ${width}px auto ${height}px format. This allows the browser to track the actual rendered size rather than using a fixed size captured at drag start, which is important since the pane width changes dynamically during drag via --pane-width CSS variable updates.

Fixed in commit 1d93cdb.

}

// 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 +39,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