Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
### WHY are these changes introduced? Fixes #12336 Fixes #12249 ### WHAT is this pull request doing? This PR exposes a `close` function on popovers imperative handle to handle accessibility when closing the popover from an outside source. ### WHY did you take this approach? Originally I thought about using an effect to watch the active status, and automatically manage focus when the popover is closed. However, we can't guarantee that the user will always want popover to manage focus. Perhaps, they'll self manage focus to another area of the page, or navigate entirely. Exposing a `close` function allows us to: * Release this in a minor version, rather than a major one * There's less work required to migrate as you won't need to audit all instance of popover * Allows for accessible focus, while allowing popover to contain the business logic * It allows for the flexibility of how you'll manage the user experience when the popover is closed ### Giphy https:/Shopify/polaris/assets/24610840/7b87b030-11ee-43b2-9ea8-da61265e53f1 ### How to 🎩 **Playground code** ``` import React, {useRef, useState, useEffect} from 'react'; import type {PopoverPublicAPI} from '../src'; import {Page, Button, Popover, ActionList} from '../src'; console.log('Logging active element every 15 seconds'); export const Playground = { tags: ['skip-tests'], render() { useEffect(() => { const interval = setInterval(() => { console.log(document.activeElement); }, 15000); return () => { clearInterval(interval); }; }, []); const popoverRef = useRef<PopoverPublicAPI>(null); const [popoverActive, setPopoverActive] = useState(true); const togglePopoverActive = () => setPopoverActive((popoverActive) => !popoverActive); const activator = ( <Button onClick={togglePopoverActive} disclosure> More actions </Button> ); return ( <Page title="Playground"> <Popover active={popoverActive} activator={activator} autofocusTarget="first-node" onClose={togglePopoverActive} ref={popoverRef} > <ActionList actionRole="menuitem" items={[ { content: 'Focus activator', onAction() { popoverRef.current?.close(); }, }, { content: 'Focus next node', onAction() { popoverRef.current?.close('next-node'); }, }, ]} /> </Popover> <Button>Next focusable node</Button> </Page> ); }, }; ``` ### 🎩 checklist - [ ] Tested a [snapshot](https:/Shopify/polaris/blob/main/documentation/Releasing.md#-snapshot-releases) - [ ] Tested on [mobile](https:/Shopify/polaris/blob/main/documentation/Tophatting.md#cross-browser-testing) - [ ] Tested on [multiple browsers](https://help.shopify.com/en/manual/shopify-admin/supported-browsers) - [ ] Tested for [accessibility](https:/Shopify/polaris/blob/main/documentation/Accessibility%20testing.md) - [ ] Updated the component's `README.md` with documentation changes - [ ] [Tophatted documentation](https:/Shopify/polaris/blob/main/documentation/Tophatting%20documentation.md) changes in the style guide
- Loading branch information