Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 5, 2026

Adds contain: layout style to the Overlay component to isolate layout and style calculations within overlay boundaries, reducing browser work when overlay content changes. The implementation uses a feature flag for safe, opt-in rollout.

Changes

CSS Module (packages/react/src/Overlay/Overlay.module.css):

.OverlayContainment {
  contain: layout style;  /* Isolates layout/style calculations */
}

Feature Flag (packages/react/src/FeatureFlags/DefaultFeatureFlags.ts):

  • Added primer_react_overlay_css_containment: false flag (defaults to disabled)

BaseOverlay Component (packages/react/src/Overlay/Overlay.tsx):

  • Feature flag check is implemented in BaseOverlay component using useFeatureFlag('primer_react_overlay_css_containment')
  • The .OverlayContainment class is conditionally applied via clsx(className, classes.Overlay, cssContainmentEnabled && classes.OverlayContainment)
  • This approach ensures proper className merging with any user-provided className through props

Unit Tests (packages/react/src/Overlay/Overlay.test.tsx):

  • Added test to verify class is not applied when feature flag is disabled
  • Added test to verify class is applied when feature flag is enabled

E2E Tests (e2e/components/Overlay.test.ts):

  • Added comprehensive test suite "with CSS containment feature flag" testing all 9 story variants
  • Includes 81 visual regression tests (@vrt) across all themes with feature flag enabled
  • Includes 81 accessibility tests (@Aat) across all themes with feature flag enabled
  • Screenshot filenames use .with-containment suffix for clarity
  • Total: 162 additional e2e tests ensuring behavior, layout, style, and paint correctness

Performance Impact

When the feature flag is enabled:

  • INP: Layout recalculations scoped to overlay subtree during content changes
  • CLS: Layout shifts inside overlays no longer affect main document

Browser Support

CSS containment supported in Chrome 52+, Firefox 69+, Safari 15.4+, Edge 79+. Progressive enhancement—unsupported browsers ignore the property.

Changelog

New

  • Added primer_react_overlay_css_containment feature flag for opt-in CSS containment
  • Added .OverlayContainment CSS class with contain: layout style
  • Added comprehensive e2e test suite with feature flag enabled (162 tests)

Changed

  • Modified BaseOverlay component to conditionally apply CSS containment based on feature flag
  • Feature flag check placed in BaseOverlay to ensure proper className merging with user-provided classNames

Rollout strategy

  • Patch release
  • Minor release
  • Major release; if selected, include a written rollout or migration plan
  • None; if selected, include a brief description as to why

Testing & Reviewing

Verify existing Overlay visual regression tests and functional behavior (positioning, focus management, click-outside) remain unchanged. The feature flag defaults to false, so there is no behavior change until explicitly enabled. When enabled, the CSS containment property is a progressive enhancement with no breaking changes.

The feature flag check is implemented in BaseOverlay to properly handle className merging when users pass custom classNames through props.

E2E tests with the feature flag enabled provide comprehensive verification across all story variants and themes, ensuring visual consistency, layout correctness, and accessibility compliance.

Merge checklist

Original prompt

Summary

Add contain: layout style to the Overlay component to improve rendering performance by isolating layout calculations within overlay boundaries.

Background

CSS containment tells the browser that an element's subtree is independent from the rest of the page, enabling significant rendering optimizations:

Containment Type What it does Performance Impact
layout Element's internal layout is independent of the rest of the DOM Browser can skip recalculating layouts outside the containment boundary when content inside changes
style CSS counters and quotes won't leak out Prevents style recalculations from propagating outside the contained element

Why Overlay and not the Portal root?

We initially considered applying containment to __primerPortalRoot__, but this causes issues because:

  1. Each Portal creates a wrapper div with position: relative; z-index: 1
  2. The Overlay inside has position: absolute
  3. The Portal wrapper collapses to zero height (no in-flow content)
  4. contain: layout on an ancestor with zero/indeterminate height breaks child layout

The Overlay component is the right place because:

  • It has explicit dimensions (width/height set via props or CSS)
  • Its children are in-flow content (not absolutely positioned)
  • The containment boundary is at the right level where dimensions are known

Implementation

Add contain: layout style to the .Overlay class in packages/react/src/Overlay/Overlay.module.css:

.Overlay {
  position: absolute;
  contain: layout style;  /* ADD THIS */
  max-width: calc(100vw - 2rem);
  /* ... rest of existing styles */
}

Expected Performance Benefits

Interaction to Next Paint (INP):

  • When modal/dialog content changes, layout recalculations are contained to the overlay subtree
  • Reduces main thread blocking time during interactions with overlay content
  • Faster response times for interactions within dropdowns, tooltips, and modals

Cumulative Layout Shift (CLS):

  • Layout changes inside overlays won't trigger shifts in the main document
  • More stable page layout when overlay content changes

Browser Compatibility

CSS containment is well-supported in modern browsers:

  • Chrome 52+
  • Firefox 69+
  • Safari 15.4+
  • Edge 79+

Risk Assessment

Low risk - CSS containment is a progressive enhancement. Browsers that don't support it will simply ignore the property. The Overlay already has explicit dimensions, so containment won't cause any layout issues.

Testing

  • Verify existing Overlay visual regression tests pass
  • Verify Overlay functionality (positioning, focus management, click outside) works correctly
  • Consider adding a performance test or documenting expected improvements

This pull request was created from Copilot chat.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@changeset-bot
Copy link

changeset-bot bot commented Jan 5, 2026

⚠️ No Changeset found

Latest commit: a4961a6

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Co-authored-by: mattcosta7 <8616962+mattcosta7@users.noreply.github.com>
Copilot AI changed the title [WIP] Add contain: layout style to Overlay component Add CSS containment to Overlay for rendering performance optimization Jan 5, 2026
Copilot AI requested a review from mattcosta7 January 5, 2026 13:54
@github-actions
Copy link
Contributor

github-actions bot commented Jan 5, 2026

👋 Hi, this pull request contains changes to the source code that github/github-ui depends on. If you are GitHub staff, test these changes with github/github-ui using the integration workflow. Or, apply the integration-tests: skipped manually label to skip these checks.

@github-actions github-actions bot added the integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm label Jan 5, 2026

.Overlay {
position: absolute;
contain: layout style;
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot we should use a feature flag to toggle a new class that contains these contain calls

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done! I've refactored the implementation to use a feature flag:

  • Created .OverlayContainment class with contain: layout style
  • Added primer_react_overlay_css_containment feature flag (defaults to false)
  • Class is conditionally applied when flag is enabled
  • Added tests to verify the feature flag behavior

Commit: 290a108

- Remove `contain: layout style` from `.Overlay` class
- Add new `.OverlayContainment` class with `contain: layout style`
- Add `primer_react_overlay_css_containment` feature flag
- Conditionally apply `.OverlayContainment` class based on feature flag
- Add tests to verify feature flag behavior

Co-authored-by: mattcosta7 <8616962+mattcosta7@users.noreply.github.com>
Copilot AI changed the title Add CSS containment to Overlay for rendering performance optimization Add feature-flagged CSS containment to Overlay for rendering performance optimization Jan 5, 2026
Copilot AI requested a review from mattcosta7 January 5, 2026 15:16
height={height}
visibility={visibility}
data-responsive={responsiveVariant}
className={cssContainmentEnabled ? classes.OverlayContainment : undefined}
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot should this be handled in BaseOverlay instead? and check the flag in that component so we properly pass className through

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved to BaseOverlay! The feature flag check is now in BaseOverlay where className is applied, ensuring proper merging with user-provided classNames via clsx:

className={clsx(className, classes.Overlay, cssContainmentEnabled && classes.OverlayContainment)}

This ensures any className passed through props is properly combined with the base classes.

Commit: 4e89bd1

- Move useFeatureFlag check from Overlay to BaseOverlay component
- Ensures proper className merging with user-provided className via clsx
- Removes duplicate className prop from Overlay component

Co-authored-by: mattcosta7 <8616962+mattcosta7@users.noreply.github.com>
@github-actions github-actions bot temporarily deployed to storybook-preview-7424 January 6, 2026 13:36 Inactive
Copilot AI requested a review from mattcosta7 January 6, 2026 13:39
@mattcosta7
Copy link
Contributor

@copilot are there snapshots / e2e tests we can use with the flag on to ensure the behavior/layout/style/paint are all correct

@github-actions github-actions bot requested a deployment to storybook-preview-7424 January 6, 2026 14:19 Abandoned
- Add new test suite "with CSS containment feature flag" to Overlay e2e tests
- Tests include visual regression (@vrt) and accessibility (@Aat) checks
- All existing story variants are tested with the feature flag enabled
- Screenshot filenames include ".with-containment" suffix for clarity
- Tests ensure behavior/layout/style/paint are correct with containment

Co-authored-by: mattcosta7 <8616962+mattcosta7@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 6, 2026

@copilot are there snapshots / e2e tests we can use with the flag on to ensure the behavior/layout/style/paint are all correct

Added comprehensive e2e tests with the feature flag enabled! The new test suite includes:

Visual Regression Tests (@vrt):

  • All 9 story variants tested with primer_react_overlay_css_containment: true
  • Screenshots saved as Overlay.{story}.{theme}.with-containment.png
  • Covers all 9 themes (light, dark, dark_dimmed, etc.)
  • Total: 81 VRT snapshots (9 stories × 9 themes)

Accessibility Tests (@Aat):

  • axe accessibility checks for all story/theme combinations with flag enabled
  • Total: 81 accessibility tests (9 stories × 9 themes)

This ensures behavior, layout, style, and paint are all correct with CSS containment applied.

Commit: a4961a6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants