Skip to content

Commit

Permalink
feat: control whether Tooltip can be closed with Esc key (#5199)
Browse files Browse the repository at this point in the history
* Control whether Tooltip can be closed with Esc key

* Move condition inside the effect

* Add `handler` to deps

* chore: update changeset

* chore: remove noop

Co-authored-by: Tim Kolberger <tim@kolberger.eu>

* test(tooltip): add tests for `closeOnEsc`

* test(tooltip): dispatch keypress event on the tooltip, not document

Co-authored-by: Tim Kolberger <tim@kolberger.eu>
  • Loading branch information
mlajtos and TimKolberger authored Mar 15, 2022
1 parent 613bace commit 73a06ae
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 3 deletions.
6 changes: 6 additions & 0 deletions .changeset/real-cooks-run.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@chakra-ui/hooks": minor
"@chakra-ui/tooltip": minor
---

Control whether Tooltip can be closed with Esc key
8 changes: 6 additions & 2 deletions packages/hooks/src/use-event-listener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export type EventListenerEnv = (() => DocumentOrElement) | DocumentOrElement
*/
export function useEventListener<K extends keyof DocumentEventMap>(
event: K | (string & {}),
handler: (event: DocumentEventMap[K]) => void,
handler?: (event: DocumentEventMap[K]) => void,
env?: EventListenerEnv,
options?: boolean | AddEventListenerOptions,
) {
Expand All @@ -27,11 +27,15 @@ export function useEventListener<K extends keyof DocumentEventMap>(
React.useEffect(() => {
const node = runIfFn(env) ?? document

if (!handler) {
return
}

node.addEventListener(event, listener, options)
return () => {
node.removeEventListener(event, listener, options)
}
}, [event, env, options, listener])
}, [event, env, options, listener, handler])

return () => {
const node = runIfFn(env) ?? document
Expand Down
7 changes: 6 additions & 1 deletion packages/tooltip/src/use-tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export interface UseTooltipProps
* is down
*/
closeOnMouseDown?: boolean
/**
* If `true`, the tooltip will hide on pressing Esc key
*/
closeOnEsc?: boolean
/**
* Callback to run when the tooltip shows
*/
Expand Down Expand Up @@ -64,6 +68,7 @@ export function useTooltip(props: UseTooltipProps = {}) {
closeDelay = 0,
closeOnClick = true,
closeOnMouseDown,
closeOnEsc = true,
onOpen: onOpenProp,
onClose: onCloseProp,
placement,
Expand Down Expand Up @@ -140,7 +145,7 @@ export function useTooltip(props: UseTooltipProps = {}) {
[isOpen, closeWithDelay],
)

useEventListener("keydown", onKeyDown)
useEventListener("keydown", closeOnEsc ? onKeyDown : undefined)

React.useEffect(
() => () => {
Expand Down
39 changes: 39 additions & 0 deletions packages/tooltip/tests/tooltip.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
screen,
testA11y,
waitForElementToBeRemoved,
press,
} from "@chakra-ui/test-utils"
import * as React from "react"
import { Tooltip, TooltipProps } from "../src"
Expand Down Expand Up @@ -125,3 +126,41 @@ test("should close on mouseleave if shouldWrapChildren is true and child is a di

await waitForElementToBeRemoved(() => screen.getByText(tooltipLabel))
})

test("shows on mouseover and closes on pressing 'esc'", async () => {
render(<DummyComponent />)

act(() => {
fireEvent.mouseOver(screen.getByText(buttonLabel))
})

await screen.findByRole("tooltip")

expect(screen.getByText(buttonLabel)).toBeInTheDocument()
expect(screen.getByRole("tooltip")).toBeInTheDocument()

act(() => {
press.Escape(screen.getByRole("tooltip"))
})

await waitForElementToBeRemoved(() => screen.getByText(tooltipLabel))
})

test("shows on mouseover and stays on pressing 'esc' if 'closeOnEsc' is false", async () => {
render(<DummyComponent closeOnEsc={false} />)

act(() => {
fireEvent.mouseOver(screen.getByText(buttonLabel))
})

await screen.findByRole("tooltip")

expect(screen.getByText(buttonLabel)).toBeInTheDocument()
expect(screen.getByRole("tooltip")).toBeInTheDocument()

act(() => {
press.Escape(screen.getByRole("tooltip"))
})

expect(screen.getByRole("tooltip")).toBeInTheDocument()
})

1 comment on commit 73a06ae

@vercel
Copy link

@vercel vercel bot commented on 73a06ae Mar 15, 2022

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.