-
Notifications
You must be signed in to change notification settings - Fork 648
perf(Dialog): Move data-dialog-scroll-optimized to FeatureFlags provider level #7393
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
mattcosta7
merged 7 commits into
perf/dialog-has-selector
from
copilot/set-dialog-scroll-attribute
Dec 30, 2025
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
023b52f
Initial plan
Copilot 901507e
Implement Dialog scroll optimization improvements
Copilot c5eb1bf
Add ref counting for data-dialog-scroll-optimized attribute
Copilot 495091b
Use merged flag value from value.enabled() for optimization check
Copilot 06aefc9
Implement WeakMap-based ref counting and add comprehensive tests
Copilot 0163141
Simplify FeatureFlags ref counting by removing WeakMap (#7394)
Copilot 19f89cd
Fix test isolation and add flag transition coverage for dialog scroll…
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,57 @@ | ||
| import type React from 'react' | ||
| import {useContext, useMemo} from 'react' | ||
| import {useContext, useMemo, useEffect} from 'react' | ||
| import {FeatureFlagContext} from './FeatureFlagContext' | ||
| import {FeatureFlagScope, type FeatureFlags} from './FeatureFlagScope' | ||
|
|
||
| export type FeatureFlagsProps = React.PropsWithChildren<{ | ||
| flags: FeatureFlags | ||
| }> | ||
|
|
||
| /** | ||
| * Ref count for data-dialog-scroll-optimized attribute management. | ||
| * | ||
| * NOTE: This is temporary infrastructure while we feature flag the CSS :has() | ||
| * performance optimization (primer_react_css_has_selector_perf). Once the flag | ||
| * is removed and the optimization is the default behavior, this ref counting | ||
| * can be removed - the attribute can simply always be present. | ||
| * | ||
| * @internal - Not part of the public API | ||
| */ | ||
| let dialogScrollOptimizedCount = 0 | ||
|
|
||
| /** | ||
| * Reset the ref count for testing purposes only. | ||
| * | ||
| * @internal - Not part of the public API. Only exported for test isolation. | ||
| */ | ||
| export function __resetDialogScrollOptimizedCount(): void { | ||
| dialogScrollOptimizedCount = 0 | ||
| document.body.removeAttribute('data-dialog-scroll-optimized') | ||
| } | ||
|
|
||
| export function FeatureFlags({children, flags}: FeatureFlagsProps) { | ||
| const parentFeatureFlags = useContext(FeatureFlagContext) | ||
| const value = useMemo(() => { | ||
| const scope = FeatureFlagScope.merge(parentFeatureFlags, FeatureFlagScope.create(flags)) | ||
| return scope | ||
| }, [parentFeatureFlags, flags]) | ||
|
|
||
| const isOptimizationEnabled = value.enabled('primer_react_css_has_selector_perf') | ||
|
|
||
| // Set body attribute for CSS :has() optimization when flag is enabled | ||
| useEffect(() => { | ||
| if (isOptimizationEnabled) { | ||
| dialogScrollOptimizedCount++ | ||
| document.body.setAttribute('data-dialog-scroll-optimized', '') | ||
|
|
||
| return () => { | ||
| dialogScrollOptimizedCount-- | ||
| if (dialogScrollOptimizedCount === 0) { | ||
| document.body.removeAttribute('data-dialog-scroll-optimized') | ||
| } | ||
| } | ||
| } | ||
| }, [isOptimizationEnabled]) | ||
|
|
||
| return <FeatureFlagContext.Provider value={value}>{children}</FeatureFlagContext.Provider> | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The global ref counter dialogScrollOptimizedCount could potentially leak state between test runs if a test fails before properly unmounting components. Consider adding a beforeEach or afterEach hook in the Dialog test file that resets this counter to 0 and removes any lingering body attributes to ensure test isolation.
Example:
However, this would require exporting the counter or creating a reset function, which may not be desirable. An alternative is to use a WeakMap keyed by FeatureFlags instances instead of a global counter, though that has its own tradeoffs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implemented WeakMap-based ref counting in 06aefc9. Each component instance uses a unique ref object tracked in a WeakMap, ensuring proper garbage collection and test isolation without exposing internal state or requiring test helpers.