Skip to content

Commit 3204599

Browse files
authored
Fix ActionMenu with IconButton (#2084)
* Fix IconButton for ActionMenu * Add test case
1 parent 3252b74 commit 3204599

File tree

2 files changed

+39
-11
lines changed

2 files changed

+39
-11
lines changed

src/Tooltip/index.tsx

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React from 'react'
22
import {useSSRSafeId} from '@react-aria/ssr'
33
import type {AnchorPosition, AnchorSide, AnchorAlignment} from '@primer/behaviors'
44
import Box from '../Box'
5-
import {useAnchoredPosition} from '../hooks'
5+
import {useAnchoredPosition, useProvidedRefOrCreate} from '../hooks'
66
import {SxProp, merge, BetterSystemStyleObject} from '../sx'
77

88
type TooltipDirection = 'nw' | 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w'
@@ -21,7 +21,7 @@ export type TooltipProps = {
2121
/** Use aria-describedby or aria-labelledby */
2222
type?: 'description' | 'label'
2323
/** Tooltip target */
24-
children: React.ReactElement
24+
children: React.ReactElement & {ref?: React.RefObject<HTMLElement>}
2525
/** When set to true, tooltip appears without any delay */
2626
noDelay?: boolean
2727
/** @deprecated Always set to true now. */
@@ -55,8 +55,16 @@ export const Tooltip: React.FC<TooltipProps> = ({
5555
sx = {},
5656
...props
5757
}) => {
58+
const tooltipId = useSSRSafeId()
59+
60+
const childRef = children.ref
61+
const anchorElementRef = useProvidedRefOrCreate(childRef)
5862
const tooltipRef = React.useRef<HTMLDivElement>(null)
59-
const anchorElementRef = React.useRef<HTMLElement>(null)
63+
64+
const child = React.cloneElement(children, {
65+
ref: anchorElementRef,
66+
[type === 'description' ? 'aria-describedby' : 'aria-labelledby']: tooltipId
67+
})
6068

6169
const {position} = useAnchoredPosition({
6270
side: directionToPosition[direction].side,
@@ -66,13 +74,6 @@ export const Tooltip: React.FC<TooltipProps> = ({
6674
anchorElementRef
6775
})
6876

69-
const tooltipId = useSSRSafeId()
70-
71-
const child = React.cloneElement(children, {
72-
ref: anchorElementRef,
73-
[type === 'description' ? 'aria-describedby' : 'aria-labelledby']: tooltipId
74-
})
75-
7677
const tooltipText = text || props['aria-label']
7778

7879
return (

src/__tests__/ActionMenu.test.tsx

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ import 'babel-polyfill'
33
import {axe, toHaveNoViolations} from 'jest-axe'
44
import React from 'react'
55
import theme from '../theme'
6-
import {ActionMenu, ActionList, BaseStyles, ThemeProvider, SSRProvider} from '..'
6+
import {ActionMenu, ActionList, BaseStyles, ThemeProvider, SSRProvider, IconButton} from '..'
77
import {behavesAsComponent, checkExports, checkStoriesForAxeViolations} from '../utils/testing'
88
import {SingleSelection, MixedSelection} from '../stories/ActionMenu/examples.stories'
99
import '@testing-library/jest-dom'
10+
import {TriangleDownIcon} from '@primer/octicons-react'
1011
expect.extend(toHaveNoViolations)
1112

1213
function Example(): JSX.Element {
@@ -136,6 +137,32 @@ describe('ActionMenu', () => {
136137
cleanup()
137138
})
138139

140+
it('should open Menu on MenuAnchor click with IconButton', async () => {
141+
const component = HTMLRender(
142+
<ThemeProvider theme={theme}>
143+
<SSRProvider>
144+
<BaseStyles>
145+
<ActionMenu>
146+
<ActionMenu.Anchor>
147+
<IconButton aria-label="Toggle Menu" icon={TriangleDownIcon} />
148+
</ActionMenu.Anchor>
149+
<ActionMenu.Overlay>
150+
<ActionList>
151+
<ActionList.Item>New file</ActionList.Item>
152+
<ActionList.Item>Copy link</ActionList.Item>
153+
</ActionList>
154+
</ActionMenu.Overlay>
155+
</ActionMenu>
156+
</BaseStyles>
157+
</SSRProvider>
158+
</ThemeProvider>
159+
)
160+
const button = component.getByLabelText('Toggle Menu')
161+
fireEvent.click(button)
162+
expect(component.getByRole('menu')).toBeInTheDocument()
163+
cleanup()
164+
})
165+
139166
it('should have no axe violations', async () => {
140167
const {container} = HTMLRender(<Example />)
141168
const results = await axe(container)

0 commit comments

Comments
 (0)