Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
5 changes: 0 additions & 5 deletions .changeset/healthy-poets-act.md

This file was deleted.

5 changes: 5 additions & 0 deletions .changeset/shiny-buckets-study.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/react': patch
---

reapplies PageLayout resizable enhancements without INP drop from expensive selectors
2 changes: 2 additions & 0 deletions e2e/components/Axe.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ const SKIPPED_TESTS = [
'components-flash-features--with-icon-action-dismiss', // TODO: Remove once color-contrast issues have been resolved
'components-flash-features--with-icon-and-action', // TODO: Remove once color-contrast issues have been resolved
'components-filteredactionlist--default',
'components-pagelayout-performance-tests--medium-content',
'components-pagelayout-performance-tests--heavy-content',
]

type Component = {
Expand Down
80 changes: 70 additions & 10 deletions packages/react/src/PageLayout/PageLayout.module.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
/* Maintain resize cursor while dragging */
/* stylelint-disable-next-line selector-no-qualifying-type */
body[data-page-layout-dragging='true'] {
cursor: col-resize;
}

/* Disable text selection while dragging */
/* stylelint-disable-next-line selector-no-qualifying-type */
body[data-page-layout-dragging='true'] * {
user-select: none;
/* Exported values for JavaScript consumption */
:export {
/* Breakpoint where --pane-max-width-diff changes (used in usePaneWidth.ts) */
paneMaxWidthDiffBreakpoint: 1280;
/* Default value for --pane-max-width-diff below the breakpoint */
paneMaxWidthDiffDefault: 511;
}
Comment on lines +1 to 7

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.

not sure if we have prefernces for using these across JS/CSS or just duplicating them?

@siddharthkp siddharthkp Dec 12, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

TIL about :export

Sorry, trying to understand the goal here. Why are these exported from PageLayout.module.css? We don't use them in this file

Nevermind, I realise you can't use the exports within the file because they will be removed during compilation


.PageLayoutRoot {
Expand All @@ -31,6 +27,7 @@ body[data-page-layout-dragging='true'] * {
--pane-width-small: 100%;
--pane-width-medium: 100%;
--pane-width-large: 100%;
/* NOTE: This value is exported via :export for use in usePaneWidth.ts */
--pane-max-width-diff: 511px;

@media screen and (min-width: 768px) {
Expand All @@ -45,6 +42,7 @@ body[data-page-layout-dragging='true'] * {
--pane-width-large: 320px;
}

/* NOTE: This breakpoint value is exported via :export for use in usePaneWidth.ts */
@media screen and (min-width: 1280px) {
--pane-max-width-diff: 959px;
}
Expand Down Expand Up @@ -383,6 +381,26 @@ body[data-page-layout-dragging='true'] * {
}
}

/**
* OPTIMIZATION: Aggressive containment during drag for ContentWrapper
* data-dragging is set on PageLayoutContent by JavaScript
* This avoids expensive :has() selectors
*/
.PageLayoutContent[data-dragging='true'] .ContentWrapper {
/* Add paint containment during drag - safe since user can't interact */
contain: layout style paint;

/* Disable interactions */
pointer-events: none;

/* Disable transitions to prevent expensive recalculations */
transition: none;

/* Force compositor layer for hardware acceleration */
will-change: width;
transform: translateZ(0);
}

.Content {
width: 100%;

Expand All @@ -409,6 +427,16 @@ body[data-page-layout-dragging='true'] * {
}
}

/**
* OPTIMIZATION: Freeze content layout during resize drag
* This prevents expensive recalculations of large content areas
* while keeping content visible (just frozen in place)
*/
.PageLayoutContent[data-dragging='true'] .Content {
/* Full containment (without size) - isolate from layout recalculations */
contain: layout style paint;
}

.PaneWrapper {
display: flex;
width: 100%;
Expand Down Expand Up @@ -598,6 +626,27 @@ body[data-page-layout-dragging='true'] * {
}
}

/**
* OPTIMIZATION: Performance enhancements for Pane during drag
* data-dragging is set on PageLayoutContent by JavaScript
* This avoids expensive :has() selectors
*/
.PageLayoutContent[data-dragging='true'] .Pane {
/* Full containment - isolate from layout recalculations */
contain: layout style paint;

/* Disable interactions during drag */
pointer-events: none;

/* Disable transitions during drag */
transition: none;

/* Force hardware acceleration */
will-change: width, transform;
transform: translateZ(0);
backface-visibility: hidden;
}

.PaneHorizontalDivider {
&:where([data-position='start']) {
/* stylelint-disable-next-line primer/spacing */
Expand Down Expand Up @@ -696,12 +745,22 @@ body[data-page-layout-dragging='true'] * {
padding: var(--spacing);
}

/**
* DraggableHandle - Interactive resize handle
*/
.DraggableHandle {
position: absolute;
inset: 0 -2px;
cursor: col-resize;
background-color: transparent;
transition-delay: 0.1s;

/**
* OPTIMIZATION: Prevent touch scrolling and text selection during drag
* This is done in CSS because it needs to be set before any pointer events
*/
touch-action: none;
user-select: none;
}

.DraggableHandle:hover {
Expand All @@ -710,6 +769,7 @@ body[data-page-layout-dragging='true'] * {

.DraggableHandle[data-dragging='true'] {
background-color: var(--bgColor-accent-emphasis);
cursor: col-resize;
}

.DraggableHandle[data-dragging='true']:hover {
Expand Down
Loading
Loading