From 71bdfa847d4cc569bb59b0b4e7a3010f1d7a0faa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arma=C4=9Fan?= Date: Mon, 15 Jul 2024 12:46:40 +1000 Subject: [PATCH] Add support for initial focus ref to Dialog 2 (#4729) * Add support for initial focus ref to Dialog 2 * add test and docs * Create seven-phones-talk.md --- .changeset/seven-phones-talk.md | 5 ++++ packages/react/src/Dialog/Dialog.docs.json | 5 ++++ .../src/Dialog/Dialog.features.stories.tsx | 28 ++++++++++++++++++- packages/react/src/Dialog/Dialog.test.tsx | 18 ++++++++++++ packages/react/src/Dialog/Dialog.tsx | 8 +++++- packages/react/src/__tests__/Dialog.test.tsx | 2 +- 6 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 .changeset/seven-phones-talk.md 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">