diff --git a/.changeset/seven-phones-talk.md b/.changeset/seven-phones-talk.md new file mode 100644 index 00000000000..e5ea9ac7d5e --- /dev/null +++ b/.changeset/seven-phones-talk.md @@ -0,0 +1,5 @@ +--- +"@primer/react": minor +--- + +Dialog2: Add support for "InitialFocusRef" that allows to specify an element that should receive focus when the dialog opens. diff --git a/packages/react/src/Dialog/Dialog.docs.json b/packages/react/src/Dialog/Dialog.docs.json index c81463bcf4b..f0e54d1ccd7 100644 --- a/packages/react/src/Dialog/Dialog.docs.json +++ b/packages/react/src/Dialog/Dialog.docs.json @@ -59,6 +59,11 @@ "name": "returnFocusRef", "type": "React.RefObject", "describedby": "Return focus to this element when the Dialog closes, instead of the element that had focus immediately before the Dialog opened" + }, + { + "name": "initialFocusRef", + "type": "React.RefObject", + "description": "Focus this element when the Dialog opens" } ], "subcomponents": [] diff --git a/packages/react/src/Dialog/Dialog.features.stories.tsx b/packages/react/src/Dialog/Dialog.features.stories.tsx index 8fd38bf40d6..7f694ce9908 100644 --- a/packages/react/src/Dialog/Dialog.features.stories.tsx +++ b/packages/react/src/Dialog/Dialog.features.stories.tsx @@ -1,5 +1,5 @@ import React, {useState, useRef, useCallback} from 'react' -import {Box, TextInput, Text, Button} from '..' +import {Box, TextInput, Text, Button, ActionList} from '..' import type {DialogProps, DialogWidth, DialogHeight} from './Dialog' import {Dialog} from './Dialog' @@ -304,3 +304,29 @@ export const ReturnFocusRef = () => { ) } + +export const NewIssues = () => { + const [isOpen, setIsOpen] = useState(false) + const onDialogClose = useCallback(() => setIsOpen(false), []) + const initialFocusRef = useRef(null) + return ( + <> + + {isOpen ? ( + ( + + + Item 1 + + Link + + )} + > + ) : null} + + ) +} diff --git a/packages/react/src/Dialog/Dialog.test.tsx b/packages/react/src/Dialog/Dialog.test.tsx index f1d33d57d49..c63823a28e9 100644 --- a/packages/react/src/Dialog/Dialog.test.tsx +++ b/packages/react/src/Dialog/Dialog.test.tsx @@ -209,3 +209,21 @@ describe('Dialog', () => { expect(getByRole('button', {name: 'return focus to (button 2)'})).toHaveFocus() }) }) + +it('automatically focuses the element that is specified as initialFocusRef', () => { + const initialFocusRef = React.createRef() + const {getByRole} = render( + {}} + title="New issue" + renderBody={() => ( + + Item 1 + + )} + >, + ) + + expect(getByRole('link')).toHaveFocus() +}) diff --git a/packages/react/src/Dialog/Dialog.tsx b/packages/react/src/Dialog/Dialog.tsx index 40026326b58..7e2925492a3 100644 --- a/packages/react/src/Dialog/Dialog.tsx +++ b/packages/react/src/Dialog/Dialog.tsx @@ -138,6 +138,11 @@ export interface DialogProps extends SxProp { * instead of the element that had focus immediately before the Dialog opened */ returnFocusRef?: React.RefObject + + /** + * The element to focus when the Dialog opens + */ + initialFocusRef?: React.RefObject } /** @@ -403,6 +408,7 @@ const _Dialog = React.forwardRef null} aria-labelledby="header">