Skip to content

Commit

Permalink
Perform ActionMenu actions after overlay has closed (#1200)
Browse files Browse the repository at this point in the history
  • Loading branch information
dgreif authored Apr 30, 2021
1 parent 84e3c57 commit 7aeb53f
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/twelve-jeans-kneel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/components": patch
---

Perform ActionMenu actions after overlay has closed. This allows the action to move focus if so desired, without the ActionMenu focus trap preventing focus from moving away.
14 changes: 12 additions & 2 deletions src/ActionMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {GroupedListProps, List, ListPropsBase} from './ActionList/List'
import {Item, ItemProps} from './ActionList/Item'
import {Divider} from './ActionList/Divider'
import Button, {ButtonProps} from './Button'
import React, {useCallback, useState} from 'react'
import React, {useCallback, useEffect, useRef, useState} from 'react'
import {AnchoredOverlay} from './AnchoredOverlay'

export interface ActionMenuProps extends Partial<Omit<GroupedListProps, keyof ListPropsBase>>, ListPropsBase {
Expand All @@ -26,6 +26,7 @@ const ActionMenuBase = ({
const [open, setOpen] = useState(false)
const onOpen = useCallback(() => setOpen(true), [])
const onClose = useCallback(() => setOpen(false), [])
const pendingActionRef = useRef<() => unknown>()

const renderMenuAnchor = useCallback(
<T extends React.HTMLAttributes<HTMLElement>>(props: T) => {
Expand All @@ -45,14 +46,23 @@ const ActionMenuBase = ({
role: 'menuitem',
onAction: (props, event) => {
const actionCallback = itemOnAction ?? onAction
actionCallback?.(props as ItemProps, event)
pendingActionRef.current = () => actionCallback?.(props as ItemProps, event)
onClose()
}
})
},
[onAction, onClose, renderItem]
)

useEffect(() => {
// Wait until menu has re-rendered in a closed state before triggering action.
// This is needed in scenarios where the action will move focus, which would otherwise be captured by focus trap
if (!open && pendingActionRef.current) {
pendingActionRef.current()
pendingActionRef.current = undefined
}
}, [open])

return (
<AnchoredOverlay renderAnchor={renderMenuAnchor} open={open} onOpen={onOpen} onClose={onClose}>
<List {...listProps} role="menu" renderItem={renderMenuItem} />
Expand Down

1 comment on commit 7aeb53f

@vercel
Copy link

@vercel vercel bot commented on 7aeb53f Apr 30, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.