Skip to content

Commit

Permalink
Dialog: Full screen & Bottom sheet support (#4048)
Browse files Browse the repository at this point in the history
* Kickoff

* Start adding action-sheet

* WIP

* Fix dragging

* Improvements

* Add hover state

* Remove unused backdropRef

* Remove listeners

* Fix warnings

* Reduce code

* Fix reduce motion

* Add open animation

* Improvements

* Improve the docs

* Make the storybook easier to manage

* Fix

* Make it easier to get the code for custom renderes

* Revert

* Remove unused imports

* Use ' instead

* Remove unused props

* Improve accessibility further

* Fix typescript warnings

* Remove more warnings

* Remove more warnings

* Fix

* Update docs

* Fix

* Use a slider instead of resizing

* Improve code

* Fix

* Fix dragging

* Create rare-geese-melt.md

* Update rare-geese-melt.md

* Fixes for FireFox

* Fix: Type number trivially inferred from a number literal, remove type annotation

* Switch refs to const

* Fix linter warnings

* Add missing props back

* Increase the hit target on mobile

* Add preventDefault() for Firefox

* Add support for setting overflow area height

* Rename ActionSheet to BottomSheet and add max-width

* Remove minHeight

* Fix merge conflicts

* Fix close button interactions

* Remove gestures we won't use

* Fix copy

* Remove overkill isReduced

* Auto focus on close button if no buttons

* Remove gestures

* Revert

* Fix JEST files

* Update exports.test.ts.snap

* Fix isReduced function

* Keep dialog open

* Remove Truncate

* Fix test

* Fix close button in custom UI

* Update Dialog.tsx

* Fix test

* test(vrt): update snapshots

* Add more snapshots

* test(vrt): update snapshots

* Can't get this to work

* Update src/Dialog/DialogBottomSheet.tsx

Co-authored-by: Keith Cirkel <keithamus@users.noreply.github.com>

* Remove test

* Push it real good

* Remove test

* Adress PR feedback

* Revert PR suggestions

* Fix

* Fix close button

* adds an option to render tests using testing-library render in behavesAsComponent

* Add a simple test

* Update snapshot

* Push

* Add test for expanding

* Add more tests based on Mike's

* Add more tests and update snapshot

* Add another test

* Linter fixes

* Fix border in dark mode

* Fix linter

* test(vrt): update snapshots

---------

Co-authored-by: Mike Perrotti <mperrotti@github.com>
Co-authored-by: maximedegreve <maximedegreve@users.noreply.github.com>
Co-authored-by: Keith Cirkel <keithamus@users.noreply.github.com>
  • Loading branch information
4 people authored Jan 24, 2024
1 parent 2d9435d commit b99e5ff
Show file tree
Hide file tree
Showing 99 changed files with 1,811 additions and 237 deletions.
5 changes: 5 additions & 0 deletions .changeset/rare-geese-melt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/react": minor
---

Dialog: `full-screen` and `action-sheet` variants
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
187 changes: 184 additions & 3 deletions e2e/components/Dialog.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,190 @@ test.describe('Dialog', () => {
}
})

test.describe('Bottom Sheet', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-dialog-features--bottom-sheet',
globals: {
colorScheme: theme,
},
})
expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot(`Dialog.Bottom Sheet.${theme}.png`)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-dialog-features--bottom-sheet',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations()
})
})
}
})

test.describe('Full Screen', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-dialog-features--full-screen',
globals: {
colorScheme: theme,
},
})
expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot(`Dialog.Full Screen.${theme}.png`)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-dialog-features--full-screen',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations()
})
})
}
})

test.describe('Non Declaritive', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-dialog-features--non-declaritive',
globals: {
colorScheme: theme,
},
})
expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot(`Dialog.Non Declaritve.${theme}.png`)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-dialog-features--non-declaritive',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations()
})
})
}
})

test.describe('Responsive', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-dialog-features--responsive',
globals: {
colorScheme: theme,
},
})
expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot(`Dialog.Responsive.${theme}.png`)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-dialog-features--responsive',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations()
})
})
}
})

test.describe('Size Large', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-dialog-features--size-large',
globals: {
colorScheme: theme,
},
})
expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot(`Dialog.Size Large.${theme}.png`)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-dialog-features--size-large',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations()
})
})
}
})

test.describe('Size Small', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-dialog-features--size-small',
globals: {
colorScheme: theme,
},
})
expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot(`Dialog.Size Small.${theme}.png`)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-dialog-features--size-small',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations()
})
})
}
})

test.describe('Size X Dialog', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-dialog-features--size-x-large',
globals: {
colorScheme: theme,
},
})
expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot(
`Dialog.Size X Large Test.${theme}.png`,
)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-dialog-features--size-x-large',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations()
})
})
}
})

test.describe('Stress Test', () => {
for (const theme of themes) {
test.describe(theme, () => {
Expand All @@ -42,8 +226,6 @@ test.describe('Dialog', () => {
colorScheme: theme,
},
})

await page.getByRole('button', {name: 'Show dialog'}).click()
expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot(`Dialog.Stress Test.${theme}.png`)
})

Expand Down Expand Up @@ -71,7 +253,6 @@ test.describe('Dialog', () => {
},
})

await page.getByRole('button', {name: 'Show dialog'}).click()
expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot(
`Dialog.With Custom Renderers.${theme}.png`,
)
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions src/ConfirmationDialog/ConfirmationDialog.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,22 @@ import {ThemeProvider} from '../ThemeProvider'
import {SSRProvider} from '../utils/ssr'
import {behavesAsComponent, checkExports} from '../utils/testing'

// The Dialog uses `matchMedia` to determine whether or not to reduce motion.

Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation(query => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(), // deprecated
removeListener: jest.fn(), // deprecated
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
})

const Basic = ({confirmButtonType}: Pick<React.ComponentProps<typeof ConfirmationDialog>, 'confirmButtonType'>) => {
const [isOpen, setIsOpen] = useState(false)
const buttonRef = useRef<HTMLButtonElement>(null)
Expand Down
3 changes: 1 addition & 2 deletions src/ConfirmationDialog/ConfirmationDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ export interface ConfirmationDialogProps {
* Required. This callback is invoked when a gesture to close the dialog
* is performed. The first argument indicates the gesture.
*/
onClose: (gesture: 'confirm' | 'close-button' | 'cancel' | 'escape') => void

onClose: (gesture: 'confirm' | 'cancel' | 'close-button' | 'escape') => void
/**
* Required. The title of the ConfirmationDialog. This is usually a brief
* question.
Expand Down
16 changes: 16 additions & 0 deletions src/DataTable/__tests__/ErrorDialog.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,22 @@ import {render, screen} from '@testing-library/react'
import React from 'react'
import {ErrorDialog} from '../ErrorDialog'

// The ErrorDialog uses `matchMedia` because the ConfirmationDialog uses it to determine whether or not to reduce motion.

Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation(query => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(), // deprecated
removeListener: jest.fn(), // deprecated
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
})

describe('Table.ErrorDialog', () => {
it('should use a default title of "Error" if `title` is not provided', () => {
render(<ErrorDialog />)
Expand Down
9 changes: 7 additions & 2 deletions src/Dialog/Dialog.docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,19 @@
},
{
"name": "onClose",
"type": "(gesture: 'close-button' | 'escape') => void",
"description": "This method is invoked when a gesture to close the dialog is used (either an Escape key press or clicking the 'X' in the top-right corner). The gesture argument indicates the gesture that was used to close the dialog (either 'close-button' or 'escape')."
"type": "(gesture: 'close-button' | 'escape' | 'drag' | 'overlay') => void",
"description": "This method is invoked when a gesture to close the dialog is used (either an Escape key press, clicking/tapping on the backdrop, clicking/tapping the 'X' in the top-right corner or dragging away a bottom sheet). The gesture argument indicates the gesture that was used to close the dialog."
},
{
"name": "role",
"type": "'dialog' | 'alertdialog'",
"description": "The ARIA role to assign to this dialog."
},
{
"name": "type",
"type": "'default' | 'full-screen' | 'bottom-sheet'",
"description": "The type of dialog to render. 'default' renders a dialog in the center of the screen. 'full-screen' renders the dialog full screen and ignored the width and height. 'full-screen' is often used for mobile breakpoints."
},
{
"name": "width",
"type": "'small' | 'medium' | 'large' | 'xlarge'"
Expand Down
Loading

0 comments on commit b99e5ff

Please sign in to comment.