diff --git a/e2e/components/Overlay.test.ts b/e2e/components/Overlay.test.ts index 556db3c4a10..3f604b69005 100644 --- a/e2e/components/Overlay.test.ts +++ b/e2e/components/Overlay.test.ts @@ -77,4 +77,51 @@ test.describe('Overlay ', () => { } }) } + + // Test with CSS containment feature flag enabled + test.describe('with CSS containment feature flag', () => { + for (const story of stories) { + test.describe(story.title, () => { + for (const theme of themes) { + test.describe(theme, () => { + test('@vrt', async ({page}) => { + await visit(page, { + id: story.id, + globals: { + colorScheme: theme, + featureFlags: { + primer_react_overlay_css_containment: true, + }, + }, + args: { + open: true, + }, + }) + + await expect(page).toHaveScreenshot(`Overlay.${story.title}.${theme}.with-containment.png`, { + animations: 'disabled', + }) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: story.id, + globals: { + colorScheme: theme, + featureFlags: { + primer_react_overlay_css_containment: true, + }, + }, + args: { + open: true, + }, + }) + + await expect(page).toHaveNoViolations() + }) + }) + } + }) + } + }) }) diff --git a/packages/react/src/FeatureFlags/DefaultFeatureFlags.ts b/packages/react/src/FeatureFlags/DefaultFeatureFlags.ts index 4a2c0896f50..9b9ebd0fe51 100644 --- a/packages/react/src/FeatureFlags/DefaultFeatureFlags.ts +++ b/packages/react/src/FeatureFlags/DefaultFeatureFlags.ts @@ -4,6 +4,7 @@ export const DefaultFeatureFlags = FeatureFlagScope.create({ primer_react_action_list_item_as_button: false, primer_react_breadcrumbs_overflow_menu: false, primer_react_css_has_selector_perf: false, + primer_react_overlay_css_containment: false, primer_react_overlay_overflow: false, primer_react_select_panel_fullscreen_on_narrow: false, primer_react_select_panel_order_selected_at_top: false, diff --git a/packages/react/src/Overlay/Overlay.module.css b/packages/react/src/Overlay/Overlay.module.css index a411b34c6f4..4ead53892ba 100644 --- a/packages/react/src/Overlay/Overlay.module.css +++ b/packages/react/src/Overlay/Overlay.module.css @@ -187,6 +187,10 @@ } } +.OverlayContainment { + contain: layout style; +} + @media (prefers-reduced-motion: no-preference) { .Overlay { animation: overlay-appear 200ms cubic-bezier(0.33, 1, 0.68, 1); diff --git a/packages/react/src/Overlay/Overlay.test.tsx b/packages/react/src/Overlay/Overlay.test.tsx index d6dde8d506e..8ea6c6cc480 100644 --- a/packages/react/src/Overlay/Overlay.test.tsx +++ b/packages/react/src/Overlay/Overlay.test.tsx @@ -366,4 +366,28 @@ describe('Overlay', () => { const container = getByRole('dialog') expect(container).toHaveAttribute('data-reflow-container') }) + + it('should not have OverlayContainment class if CSS containment FF is not enabled', async () => { + const user = userEvent.setup() + const {getByRole} = render() + + await user.click(getByRole('button', {name: 'open overlay'})) + + const container = getByRole('dialog') + expect(container).not.toHaveClass(classes.OverlayContainment) + }) + + it('should have OverlayContainment class if CSS containment FF is enabled', async () => { + const user = userEvent.setup() + const {getByRole} = render( + + + , + ) + + await user.click(getByRole('button', {name: 'open overlay'})) + + const container = getByRole('dialog') + expect(container).toHaveClass(classes.OverlayContainment) + }) }) diff --git a/packages/react/src/Overlay/Overlay.tsx b/packages/react/src/Overlay/Overlay.tsx index 9f588146323..98959dac2b0 100644 --- a/packages/react/src/Overlay/Overlay.tsx +++ b/packages/react/src/Overlay/Overlay.tsx @@ -108,6 +108,7 @@ export const BaseOverlay = React.forwardRef( forwardedRef, // eslint-disable-next-line @typescript-eslint/no-explicit-any ): ReactElement => { + const cssContainmentEnabled = useFeatureFlag('primer_react_overlay_css_containment') return ( ) },