Skip to content

Commit

Permalink
Merge e066cd2 into 0b57996
Browse files Browse the repository at this point in the history
  • Loading branch information
TylerJDev authored Jul 29, 2024
2 parents 0b57996 + e066cd2 commit f738446
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 11 deletions.
5 changes: 5 additions & 0 deletions .changeset/thirty-pets-impress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/react': minor
---

Adds dependencies to `Dialog` focus trap to ensure focus trap is reset when content within changes
57 changes: 55 additions & 2 deletions packages/react/src/Dialog/Dialog.features.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {useState, useRef, useCallback} from 'react'
import React, {useState, useRef, useCallback, useEffect} from 'react'
import {Box, TextInput, Text, Button, ActionList} from '..'
import type {DialogProps, DialogWidth, DialogHeight} from './Dialog'
import {Dialog} from './Dialog'
Expand Down Expand Up @@ -143,7 +143,7 @@ export const StressTest = ({width, height, subtitle}: DialogStoryProps) => {
footerButtons={[
...manyButtons,
{buttonType: 'danger', content: 'Delete the universe', onClick: onDialogClose},
{buttonType: 'primary', content: 'Proceed', onClick: openSecondDialog, autoFocus: true},
{buttonType: 'primary', content: 'Proceed', onClick: openSecondDialog},
]}
>
{lipsum}
Expand Down Expand Up @@ -330,3 +330,56 @@ export const NewIssues = () => {
</>
)
}

export const RetainsFocusTrapWithDynamicContent = () => {
const [isOpen, setIsOpen] = useState(false)
const [secondOpen, setSecondOpen] = useState(false)
const [expandContent, setExpandContent] = useState(false)
const [changeBodyContent, setChangeBodyContent] = useState(false)

const buttonRef = useRef<HTMLButtonElement>(null)
const onDialogClose = useCallback(() => setIsOpen(false), [])
const onSecondDialogClose = useCallback(() => setSecondOpen(false), [])
const openSecondDialog = useCallback(() => setSecondOpen(true), [])

const renderFooterConditionally = () => {
if (!changeBodyContent) return null

return (
<Dialog.Footer>
<Button variant="primary">Submit</Button>
</Dialog.Footer>
)
}

return (
<>
<Button ref={buttonRef} onClick={() => setIsOpen(!isOpen)}>
Show dialog
</Button>
{isOpen && (
<Dialog title="My Dialog" onClose={onDialogClose} renderFooter={renderFooterConditionally}>
<Button onClick={() => setExpandContent(!expandContent)}>
Click me to dynamically {expandContent ? 'remove' : 'render'} content
</Button>
<Button onClick={() => setChangeBodyContent(!changeBodyContent)}>
Click me to {changeBodyContent ? 'remove' : 'add'} a footer
</Button>
<Button onClick={openSecondDialog}>Click me to open a new dialog</Button>
{expandContent && (
<Box>
{lipsum}
<Button>Dialog Button Example 1</Button>
<Button>Dialog Button Example 2</Button>
</Box>
)}
{secondOpen && (
<Dialog title="Inner dialog!" onClose={onSecondDialogClose} width="small">
Hello world
</Dialog>
)}
</Dialog>
)}
</>
)
}
4 changes: 2 additions & 2 deletions packages/react/src/Dialog/Dialog.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const Default = () => {
footerButtons={[
{buttonType: 'default', content: 'Open Second Dialog', onClick: openSecondDialog},
{buttonType: 'danger', content: 'Delete the universe', onClick: onDialogClose},
{buttonType: 'primary', content: 'Proceed', onClick: openSecondDialog, autoFocus: true},
{buttonType: 'primary', content: 'Proceed', onClick: openSecondDialog},
]}
>
{lipsum}
Expand Down Expand Up @@ -119,7 +119,7 @@ export const Playground = (
footerButtons={[
{buttonType: 'default', content: 'Open Second Dialog', onClick: openSecondDialog},
{buttonType: 'danger', content: 'Delete the universe', onClick: onDialogClose},
{buttonType: 'primary', content: 'Proceed', onClick: openSecondDialog, autoFocus: true},
{buttonType: 'primary', content: 'Proceed', onClick: openSecondDialog},
]}
>
{lipsum}
Expand Down
17 changes: 10 additions & 7 deletions packages/react/src/Dialog/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -433,13 +433,6 @@ const _Dialog = React.forwardRef<HTMLDivElement, React.PropsWithChildren<DialogP
useRefObjectAsForwardedRef(forwardedRef, dialogRef)
const backdropRef = useRef<HTMLDivElement>(null)

useFocusTrap({
containerRef: dialogRef,
initialFocusRef: initialFocusRef ?? autoFocusedFooterButtonRef,
restoreFocusOnCleanUp: returnFocusRef?.current ? false : true,
returnFocusRef,
})

useOnEscapePress(
(event: KeyboardEvent) => {
onClose('escape')
Expand Down Expand Up @@ -476,6 +469,16 @@ const _Dialog = React.forwardRef<HTMLDivElement, React.PropsWithChildren<DialogP
}),
)

useFocusTrap(
{
containerRef: dialogRef,
initialFocusRef: initialFocusRef ?? autoFocusedFooterButtonRef,
restoreFocusOnCleanUp: returnFocusRef?.current ? false : true,
returnFocusRef,
},
[dialogRef, body, footer],
)

return (
<>
<Portal>
Expand Down

0 comments on commit f738446

Please sign in to comment.