react icon indicating copy to clipboard operation
react copied to clipboard

Overlay: Add `role="dialog"`, focus trap to `Overlay`

Open TylerJDev opened this issue 1 year ago • 7 comments

Closes https://github.com/github/primer/issues/3378

Usages of Overlay tend to lean more towards a dialog across GH. This PR aims to define it as a dialog in most cases, provided with a focus trap that's toggled via the newly added focusTrap prop.

Changelog

New

  • Add role="dialog" and aria-modal="true" to Overlay component

Rollout strategy

  • [ ] Patch release
  • [x] Minor release
  • [ ] Major release; if selected, include a written rollout or migration plan
  • [ ] None; if selected, include a brief description as to why

Testing & Reviewing

Merge checklist

  • [x] Added/updated tests
  • [x] Added/updated documentation
  • [ ] Added/updated previews (Storybook)
  • [ ] Changes are SSR compatible
  • [x] Tested in Chrome
  • [ ] Tested in Firefox
  • [ ] Tested in Safari
  • [ ] Tested in Edge
  • [x] (GitHub staff only) Integration tests pass at github/github (Learn more about how to run integration tests)

TylerJDev avatar Sep 19 '24 14:09 TylerJDev

🦋 Changeset detected

Latest commit: 5627e4f46fcca2f566788268b29c31df695da940

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@primer/react Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

changeset-bot[bot] avatar Sep 19 '24 14:09 changeset-bot[bot]

size-limit report 📦

Path Size
packages/react/dist/browser.esm.js 97.85 KB (+0.02% 🔺)
packages/react/dist/browser.umd.js 98.16 KB (+0.1% 🔺)

github-actions[bot] avatar Sep 19 '24 14:09 github-actions[bot]

:wave: Hi from github/github! Your integration PR is ready: https://github.com/github/github/pull/343407

primer-integration[bot] avatar Sep 20 '24 21:09 primer-integration[bot]

This change essentially turns Overlay into a "Dialog" in the sense of role="dialog" and aria-modal="true" being added. A focus trap is also added by default, and is enabled if there are focusable elements inside of the overlay. This change will not affect overlays that already have a role attribute, as long as that role attribute isn't role="dialog".

Rollout plan:

  • Add role="none" to existing Overlay components that do not implicitly set role already
  • Add focusTrap={false} to Overlay components that are used as Dialogs currently, but do not utilize a focus trap.

TylerJDev avatar Sep 20 '24 22:09 TylerJDev

@primer/engineer-reviewers - Hey team! Would love any additional eyes on this PR, mainly in regards to my rollout plan.

TylerJDev avatar Sep 24 '24 18:09 TylerJDev

If it is a role=dialog and has focus trapping, it should be a <dialog> element with showModal() called.

We should steer away from useFocusTrap and use showModal() on <dialog> elements instead. It comes with many other small benefits such as retaining previously-focused-element.

That makes sense! I'm curious if we'd want this to be true for components that consume Overlay or AnchoredOverlay (e.g. ActionMenu, SelectPanel), as they rely on Overlay internally. I guess it would be worth making those components utilize Dialog, as we utilize it in the PVC SelectPanel already. But I'm curious what you think? This seems like it would require more effort and testing, but could be worth it in the long run.

Right now, this PR will only affect components that utilize Overlay in a standalone context. Components that utilize Overlay like ActionMenu would retain the same semantics/roles even though it technically uses it internally to render the menu. We could see about conditionally rendering a <dialog> vs the current <div> container but only in instances where it's being used as a standalone component, but I'm wondering if that's worth it or not 🤔

TylerJDev avatar Sep 25 '24 02:09 TylerJDev

I think Dialog and components that use <dialog> can be discrete. I see little value in mapping our React library to individual HTML elements.

As for conditionally rendering <dialog> vs <div>, that kind of seems fine to me but I’d actually sooner see us split out ActionMenu to not use Overlay which is a case I’ve made before about the general reuse of these components; I don’t think there is enough overlap to consider reuse here. There can be multiple discrete types of floating UI.

keithamus avatar Sep 25 '24 07:09 keithamus