Skip to content

Commit

Permalink
feat(Overlay): Convert Overlay to CSS modules behind team feature flag
Browse files Browse the repository at this point in the history
  • Loading branch information
francinelucca committed Nov 18, 2024
1 parent 65802fc commit c269372
Show file tree
Hide file tree
Showing 5 changed files with 481 additions and 60 deletions.
134 changes: 134 additions & 0 deletions e2e/components/Overlay.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import {test, expect, type Page} from '@playwright/test'
import {visit} from '../test-helpers/storybook'
import {themes} from '../test-helpers/themes'

const stories = [
{
title: 'Default',
id: 'private-components-overlay--default',
setup: async (page: Page) => {
await page.keyboard.press('Tab')
await page.keyboard.press('Enter')
},
},
{
title: 'Playground',
id: 'private-components-overlay-dev--sx-props',
setup: async (page: Page) => {
await page.keyboard.press('Tab')
await page.keyboard.press('Enter')
},
},
{
title: 'Dialog Overlay',
id: 'private-components-overlay-features--dialog-overlay',
setup: async (page: Page) => {
await page.keyboard.press('Tab')
await page.keyboard.press('Enter')
},
},
{
title: 'Dropdown Overlay',
id: 'private-components-overlay-features--dropdown-overlay',
setup: async (page: Page) => {
await page.keyboard.press('Tab')
await page.keyboard.press('Enter')
},
},
{
title: 'Memex Issue Overlay',
id: 'private-components-overlay-features--memex-issue-overlay',
setup: async (page: Page) => {
await page.keyboard.press('Tab')
await page.keyboard.press('Enter')
},
},
{
title: 'Memex Nested Overlays',
id: 'private-components-overlay-features--memex-nested-overlays',
setup: async (page: Page) => {
await page.keyboard.press('Tab')
await page.keyboard.press('Tab')
await page.keyboard.press('Enter')
await page.keyboard.press('Tab')
await page.keyboard.press('Enter')
},
},
{
title: 'Nested Overlays',
id: 'private-components-overlay-features--nested-overlays',
setup: async (page: Page) => {
await page.keyboard.press('Tab')
await page.keyboard.press('Tab')
await page.keyboard.press('Tab')
await page.keyboard.press('Enter')
await page.keyboard.press('Tab')
await page.keyboard.press('Tab')
await page.keyboard.press('Enter')
},
},
{
title: 'Overlay On Top Of Overlay',
id: 'private-components-overlay-features--overlay-on-top-of-overlay',
setup: async (page: Page) => {
await page.keyboard.press('Tab')
await page.keyboard.press('Tab')
await page.keyboard.press('Enter')
await page.keyboard.press('Enter')
await page.keyboard.press('Enter')
},
},
{
title: 'Positioned Overlays',
id: 'private-components-overlay-features--positioned-overlays',
setup: async (page: Page) => {
await page.keyboard.press('Tab')
await page.keyboard.press('Tab')
await page.keyboard.press('Enter')
},
},
{
title: 'SX Props',
id: 'components-popover-dev--sx-props',
setup: async (page: Page) => {
await page.keyboard.press('Tab')
await page.keyboard.press('Enter')
},
},
] as const

test.describe('Popover', () => {
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,
},
})

await story.setup(page)

// Default state
expect(await page.screenshot()).toMatchSnapshot(`Overlay.${story.title}.${theme}.png`)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: story.id,
globals: {
colorScheme: theme,
},
})
await story.setup(page)

await expect(page).toHaveNoViolations()
})
})
}
})
}
})
81 changes: 81 additions & 0 deletions packages/react/src/Overlay/Overlay.dev.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React, {useRef, useState} from 'react'
import type {Meta} from '@storybook/react'
import Text from '../Text'
import {Button, IconButton} from '../Button'
import Overlay from './Overlay'
import {useFocusTrap} from '../hooks/useFocusTrap'
import Box from '../Box'
import {XIcon} from '@primer/octicons-react'

export default {
title: 'Private/Components/Overlay/Dev',
component: Overlay,
} as Meta<typeof Overlay>

export const SxProps = () => {
const [isOpen, setIsOpen] = useState(false)
const buttonRef = useRef<HTMLButtonElement>(null)
const confirmButtonRef = useRef<HTMLButtonElement>(null)
const anchorRef = useRef<HTMLDivElement>(null)
const closeOverlay = () => setIsOpen(false)
const containerRef = useRef<HTMLDivElement>(null)
useFocusTrap({
containerRef,
disabled: !isOpen,
})
return (
<Box ref={anchorRef}>
<Button
ref={buttonRef}
onClick={() => {
setIsOpen(!isOpen)
}}
>
Open overlay
</Button>
{isOpen ? (
<Overlay
initialFocusRef={confirmButtonRef}
returnFocusRef={buttonRef}
ignoreClickRefs={[buttonRef]}
onEscape={closeOverlay}
onClickOutside={closeOverlay}
width="large"
anchorSide="inside-right"
role="dialog"
aria-modal="true"
ref={containerRef}
sx={{
left: '50%',
mt: 2,
color: 'var(--bgColor-danger-muted)',
}}
style={{padding: '16px'}}
>
<Box
sx={{
height: '100vh',
maxWidth: 'calc(-1rem + 100vw)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<IconButton
aria-label="Close"
onClick={closeOverlay}
icon={XIcon}
variant="invisible"
sx={{
position: 'absolute',
left: '5px',
top: '5px',
}}
/>
<Text>Look! an overlay</Text>
</Box>
</Overlay>
) : null}
</Box>
)
}
158 changes: 158 additions & 0 deletions packages/react/src/Overlay/Overlay.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
.Overlay {
position: absolute;
width: auto;
min-width: 192px;
height: auto;
overflow: hidden;
background-color: var(--overlay-bgColor);
border-radius: var(--borderRadius-large);
box-shadow: var(--shadow-floating-small);
animation: overlay-appear 200ms cubic-bezier(0.33, 1, 0.68, 1);

@keyframes overlay-appear {
0% {
opacity: 0;
}

100% {
opacity: 1;
}
}

:focus {
outline: none;
}

@media (forced-colors: active) {
/* Support for Windows high contrast https://sarahmhigley.com/writing/whcm-quick-tips */
outline: solid 1px transparent;
}

&:where([data-reflow-container='true']) {
max-width: calc(100vw - 2rem);
}

&:where([data-overflow-auto]) {
overflow: auto;
}

&:where([data-overflow-hidden]) {
overflow: hidden;
}

&:where([data-overflow-scroll]) {
overflow: scroll;
}

&:where([data-overflow-visible]) {
overflow: visible;
}

&:where([data-height-xsmall]) {
height: 192px;
}

&:where([data-height-small]) {
height: 256px;
}

&:where([data-height-medium]) {
height: 320px;
}

&:where([data-height-large]) {
height: 432px;
}

&:where([data-height-xlarge]) {
height: 600px;
}

&:where([data-height-auto]),
&:where([data-height-initial]) {
height: auto;
}

&:where([data-height-fit-content]) {
height: fit-content;
}

&:where([data-max-height-xsmall]) {
max-height: 192px;
}

&:where([data-max-height-small]) {
max-height: 256px;
}

&:where([data-max-height-medium]) {
max-height: 320px;
}

&:where([data-max-height-large]) {
max-height: 432px;
}

&:where([data-max-height-xlarge]) {
max-height: 600px;
}

&:where([data-max-height-fit-content]) {
max-height: fit-content;
}

&:where([data-width-small]) {
width: 256px;
}

&:where([data-width-medium]) {
width: 320px;
}

&:where([data-width-large]) {
/* stylelint-disable-next-line primer/responsive-widths */
width: 480px;
}

&:where([data-width-xlarge]) {
/* stylelint-disable-next-line primer/responsive-widths */
width: 640px;
}

&:where([data-width-xxlarge]) {
/* stylelint-disable-next-line primer/responsive-widths */
width: 960px;
}

&:where([data-width-auto]) {
width: auto;
}

&:where([data-max-width-small]) {
max-width: 256px;
}

&:where([data-max-width-medium]) {
max-width: 320px;
}

&:where([data-max-width-large]) {
max-width: 480px;
}

&:where([data-max-width-xlarge]) {
max-width: 640px;
}

&:where([data-max-width-xxlarge]) {
max-width: 960px;
}

&:where([data-visibility-visible]) {
visibility: visible;
}

&:where([data-visibility-hidden]) {
visibility: hidden;
}
}
Loading

0 comments on commit c269372

Please sign in to comment.