Skip to content

Commit e642ff7

Browse files
authored
Revert "Revert accessible Tooltip + IconButton (#2092)"
This reverts commit c67568b.
1 parent c67568b commit e642ff7

28 files changed

+1347
-1052
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@primer/react': minor
3+
---
4+
5+
[IconButton](https://primer.style/react/IconButton) now has a tooltip by default, it can be [customised by wrapping in a Tooltip](https://primer.style/react/IconButton#customize-description--tooltip-text) ([#2006](https://github.com/primer/react/pull/2006))

.changeset/improved-tooltip.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@primer/react': patch
3+
---
4+
5+
Accessibility and position fixes (backward compatible) for Tooltip ([#2006](https://github.com/primer/react/pull/2006))
6+

docs/content/IconButton.mdx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ A separate component called `IconButton` is used if the action shows only an ico
3535
</>
3636
```
3737

38+
### Customize description / tooltip text
39+
40+
To add description for the button, wrap `IconButton` in a `Tooltip`. Make sure you pass `aria-label` to the button as well.
41+
42+
```jsx live
43+
<Tooltip text="You have no unread notifications">
44+
<IconButton icon={BellIcon} aria-label="Notifications" />
45+
</Tooltip>
46+
```
47+
3848
## API reference
3949

4050
Native `<button>` HTML attributes are forwarded to the underlying React `button` component and are not listed below.

docs/content/Tooltip.md

Lines changed: 0 additions & 34 deletions
This file was deleted.

docs/content/Tooltip.mdx

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
---
2+
componentId: tooltip
3+
title: Tooltip
4+
status: Alpha
5+
source: https://github.com/primer/react/tree/main/src/Tooltip
6+
storybook: '/react/storybook?path=/story/composite-components-tooltip'
7+
description: Use tooltips to add context to elements on the page.
8+
---
9+
10+
Tooltip only appears on mouse hover or keyboard focus and contain a label or description text. Use tooltips sparingly and as a last resort. [Consider these alternatives](https://primer.style/design/accessibility/tooltip-alternatives).
11+
12+
import {Tooltip, IconButton, Button} from '@primer/react'
13+
import {BellIcon, MentionIcon} from '@primer/octicons-react'
14+
import InlineCode from '@primer/gatsby-theme-doctocat/src/components/inline-code'
15+
16+
<Box
17+
sx={{
18+
display: 'flex',
19+
justifyContent: 'center',
20+
border: '1px solid',
21+
borderColor: 'border.default',
22+
borderRadius: 2,
23+
padding: 6,
24+
paddingTop: 8,
25+
marginBottom: 3
26+
}}
27+
>
28+
<Tooltip text="You have no unread notifications" sx={{visibility: 'visible', opacity: 1}}>
29+
<IconButton icon={BellIcon} aria-label="Notifications" />
30+
</Tooltip>
31+
</Box>
32+
33+
When using a tooltip, follow the provided guidelines to avoid accessibility issues:
34+
35+
- Tooltip text should be brief and to the point.
36+
- Tooltips should contain only **non-essential text**. Tooltips can easily be missed and are not accessible on touch devices so never use tooltips to convey critical information.
37+
38+
## Examples
39+
40+
### As a description for icon-only button
41+
42+
If the tooltip content provides supplementary description, wrap the target in a `Tooltip`. The trigger element should also have a concise accessible label via `aria-label`.
43+
44+
```jsx live
45+
<Tooltip text="Directly mention a team or user">
46+
<IconButton aria-label="Mentions" icon={MentionIcon} variant="invisible" />
47+
</Tooltip>
48+
```
49+
50+
### As a description for a button with visible label
51+
52+
```jsx live
53+
<Tooltip text="This will immediately impact all organization members">
54+
<Button variant="primary">Save</Button>
55+
</Tooltip>
56+
```
57+
58+
### With direction
59+
60+
Set direction of tooltip with `direction`. The tooltip is responsive and will automatically adjust direction to avoid cutting off.
61+
62+
```jsx live
63+
<Box
64+
sx={{
65+
display: 'flex',
66+
flexDirection: 'column',
67+
gap: 8,
68+
marginY: 4,
69+
'[data-component=tooltip]': {visibility: 'visible', opacity: 1}
70+
}}
71+
>
72+
<Box sx={{display: 'flex', justifyContent: 'space-between', gap: 1}}>
73+
<Tooltip direction="nw" text="Tooltip text">
74+
<Button>North west</Button>
75+
</Tooltip>
76+
<Tooltip direction="n" text="Tooltip text">
77+
<Button>North</Button>
78+
</Tooltip>
79+
<Tooltip direction="ne" text="Tooltip text">
80+
<Button>North east</Button>
81+
</Tooltip>
82+
</Box>
83+
<Box sx={{display: 'flex', justifyContent: 'space-between', gap: 1}}>
84+
<Tooltip direction="e" text="Tooltip text">
85+
<Button>East</Button>
86+
</Tooltip>
87+
<Tooltip direction="w" text="Tooltip text">
88+
<Button>West</Button>
89+
</Tooltip>
90+
</Box>
91+
<Box sx={{display: 'flex', justifyContent: 'space-between', gap: 1}}>
92+
<Tooltip direction="sw" text="Tooltip text">
93+
<Button>South west</Button>
94+
</Tooltip>
95+
<Tooltip direction="s" text="Tooltip text">
96+
<Button>South</Button>
97+
</Tooltip>
98+
<Tooltip direction="se" text="Tooltip text">
99+
<Button>South east</Button>
100+
</Tooltip>
101+
</Box>
102+
</Box>
103+
```
104+
105+
## Props
106+
107+
### Tooltip
108+
109+
<PropsTable>
110+
<PropsTableRow name="children" required type="React.ReactNode" description="Tooltip target, single element" />
111+
112+
<PropsTableRow
113+
name="text"
114+
type="string"
115+
description="The text content of the tooltip. This should be brief and no longer than a sentence"
116+
/>
117+
<PropsTableRow
118+
deprecated
119+
name="aria-label"
120+
type="string"
121+
description={
122+
<>
123+
Use <InlineCode>text</InlineCode> instead
124+
</>
125+
}
126+
/>
127+
<PropsTableRow
128+
name="type"
129+
type="'description' | 'label'"
130+
defaultValue="'description'"
131+
description={
132+
<>
133+
Use <InlineCode>aria-describedby</InlineCode> or <InlineCode>aria-labelledby</InlineCode>
134+
</>
135+
}
136+
/>
137+
<PropsTableRow
138+
name="direction"
139+
type="'nw' | 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w'"
140+
defaultValue="'n'"
141+
description="Sets where the tooltip renders in relation to the target"
142+
/>
143+
<PropsTableRow name="align" deprecated type="'left' | 'right'" description="Use direction instead. Alignment relative to target" />
144+
<PropsTableRow
145+
name="noDelay"
146+
type="boolean"
147+
defaultValue="false"
148+
description={
149+
<>
150+
When set to <InlineCode>true</InlineCode>, tooltip appears without any delay
151+
</>
152+
}
153+
/>
154+
<PropsTableRow
155+
name="wrap"
156+
type="boolean"
157+
deprecated
158+
description={
159+
<>
160+
Use to allow text within tooltip to wrap. Deprecated: always set to <InlineCode>true</InlineCode> now.
161+
</>
162+
}
163+
/>
164+
<PropsTableSxRow />
165+
</PropsTable>
166+
167+
## Status
168+
169+
<ComponentChecklist
170+
items={{
171+
propsDocumented: true,
172+
noUnnecessaryDeps: true,
173+
adaptsToThemes: true,
174+
adaptsToScreenSizes: true,
175+
fullTestCoverage: true,
176+
usedInProduction: true,
177+
usageExamplesDocumented: true,
178+
hasStorybookStories: true,
179+
designReviewed: false,
180+
a11yReviewed: false,
181+
stableApi: true,
182+
addressedApiFeedback: false,
183+
hasDesignGuidelines: false,
184+
hasFigmaComponent: true
185+
}}
186+
/>
187+
188+
## Further reading
189+
190+
- [Tooltip alternatives](https://primer.style/design/accessibility/tooltip-alternatives)
191+
192+
## Related components
193+
194+
- [IconButton](/IconButton)

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
"npm": ">=7"
7979
},
8080
"dependencies": {
81-
"@primer/behaviors": "1.1.1",
81+
"@primer/behaviors": "^1.1.3",
8282
"@primer/octicons-react": "16.1.1",
8383
"@primer/primitives": "7.6.0",
8484
"@radix-ui/react-polymorphic": "0.0.14",

src/Button/Button.stories.tsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import {EyeClosedIcon, EyeIcon, SearchIcon, TriangleDownIcon, XIcon} from '@primer/octicons-react'
1+
import {BellIcon, EyeClosedIcon, EyeIcon, SearchIcon, TriangleDownIcon, XIcon} from '@primer/octicons-react'
22
import {Meta} from '@storybook/react'
33
import React, {useState} from 'react'
44
import {Button, ButtonProps, IconButton} from '.'
55
import {BaseStyles, ThemeProvider} from '..'
66
import Box from '../Box'
7+
import {Tooltip} from '../Tooltip'
78

89
export default {
910
title: 'Composite components/Button',
@@ -93,6 +94,35 @@ export const iconButton = ({...args}: ButtonProps) => {
9394
)
9495
}
9596

97+
export const iconButtonWithTooltip = ({...args}: ButtonProps) => {
98+
return (
99+
<>
100+
<Box sx={{mt: 4, display: 'grid', gridTemplateColumns: '1fr 1fr', rowGap: 2}}>
101+
Default tooltip
102+
<span>
103+
<IconButton icon={BellIcon} aria-label="Notifications" {...args} />
104+
</span>
105+
Custom tooltip text
106+
<span>
107+
<Tooltip text="You have no unread notifications">
108+
<IconButton icon={BellIcon} aria-label="Notifications" {...args} />
109+
</Tooltip>
110+
</span>
111+
Custom tooltip direction
112+
<span>
113+
<Tooltip text="Notifications" direction="e">
114+
<IconButton icon={BellIcon} aria-label="Notifications" {...args} />
115+
</Tooltip>
116+
</span>
117+
Disable tooltip
118+
<span>
119+
<IconButton icon={BellIcon} aria-label="Notifications" disableTooltip {...args} />
120+
</span>
121+
</Box>
122+
</>
123+
)
124+
}
125+
96126
export const WatchCounterButton = ({...args}: ButtonProps) => {
97127
const [count, setCount] = useState(0)
98128
return (

0 commit comments

Comments
 (0)