Skip to content

Commit 7ad7219

Browse files
authored
Merge pull request desktop#17823 from desktop/escape-should-close-our-tooltips
Hide tooltip on escape and stop escape from further action
2 parents 3500596 + 1e889d1 commit 7ad7219

File tree

3 files changed

+29
-0
lines changed

3 files changed

+29
-0
lines changed

app/src/ui/changes/commit-message.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,6 +1258,7 @@ export class CommitMessage extends React.Component<
12581258
onClick={this.onSubmit}
12591259
disabled={!buttonEnabled}
12601260
tooltip={tooltip}
1261+
tooltipDismissable={false}
12611262
onlyShowTooltipWhenOverflowed={buttonEnabled}
12621263
>
12631264
<>

app/src/ui/lib/button.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,15 @@ export interface IButtonProps {
180180
* Default: true
181181
* */
182182
readonly applyTooltipAriaDescribedBy?: boolean
183+
184+
/**
185+
* Whether or not the tooltip should be dismissable via the escape key. This
186+
* is generally true, but if the tooltip is communicating something important
187+
* to the user, such as an input error, it should not be dismissable.
188+
*
189+
* Defaults to true
190+
*/
191+
readonly tooltipDismissable?: boolean
183192
}
184193

185194
/**
@@ -251,6 +260,7 @@ export class Button extends React.Component<IButtonProps, {}> {
251260
onlyWhenOverflowed={this.props.onlyShowTooltipWhenOverflowed}
252261
openOnTargetClick={this.props.openTooltipOnClick}
253262
applyAriaDescribedBy={this.props.applyTooltipAriaDescribedBy}
263+
dismissable={this.props.tooltipDismissable}
254264
>
255265
{tooltip}
256266
</Tooltip>

app/src/ui/lib/tooltip.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ export interface ITooltipProps<T> {
5353
*/
5454
readonly interactive?: boolean
5555

56+
/**
57+
* Whether or not the tooltip should be dismissable via the escape key. This
58+
* is generally true, but if the tooltip is communicating something important
59+
* to the user, such as an input error, it should not be dismissable.
60+
*
61+
* Defaults to true
62+
*/
63+
readonly dismissable?: boolean
64+
5665
/**
5766
* The amount of time to wait (in milliseconds) while a user hovers over the
5867
* target before displaying the tooltip. There's typically no reason to
@@ -377,6 +386,13 @@ export class Tooltip<T extends TooltipTarget> extends React.Component<
377386
}
378387
}
379388

389+
private onKeyDown = (event: KeyboardEvent) => {
390+
if (event.key === 'Escape' && this.state.show && this.props.dismissable) {
391+
event.preventDefault()
392+
this.beginHideTooltip()
393+
}
394+
}
395+
380396
private installTooltip(elem: TooltipTarget) {
381397
elem.addEventListener('mouseenter', this.onTargetMouseEnter)
382398
elem.addEventListener('mouseleave', this.onTargetMouseLeave)
@@ -389,6 +405,7 @@ export class Tooltip<T extends TooltipTarget> extends React.Component<
389405
elem.addEventListener('tooltip-shown', this.onTooltipShown)
390406
elem.addEventListener('tooltip-hidden', this.onTooltipHidden)
391407
elem.addEventListener('click', this.onTargetClick)
408+
elem.addEventListener('keydown', this.onKeyDown)
392409
}
393410

394411
private removeTooltip(prevTarget: TooltipTarget | null) {
@@ -405,6 +422,7 @@ export class Tooltip<T extends TooltipTarget> extends React.Component<
405422
prevTarget.removeEventListener('focusout', this.onTargetBlur)
406423
prevTarget.removeEventListener('blur', this.onTargetBlur)
407424
prevTarget.removeEventListener('click', this.onTargetClick)
425+
prevTarget.removeEventListener('keydown', this.onKeyDown)
408426
}
409427
}
410428

0 commit comments

Comments
 (0)