@sanity/ui 1.8.3 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -275,4 +275,71 @@ describe('Tooltip', () => {
|
|
|
275
275
|
jest.clearAllMocks()
|
|
276
276
|
})
|
|
277
277
|
})
|
|
278
|
+
describe('Closing the <Tooltip /> with the Escape key', () => {
|
|
279
|
+
it('Standalone tooltip closes immediately with Escape key', () => {
|
|
280
|
+
const delay = 150
|
|
281
|
+
|
|
282
|
+
jest.useFakeTimers()
|
|
283
|
+
|
|
284
|
+
render(
|
|
285
|
+
<Tooltip
|
|
286
|
+
content={<Text size={1}>{'Tooltip content'}</Text>}
|
|
287
|
+
placement={'top'}
|
|
288
|
+
delay={delay}
|
|
289
|
+
>
|
|
290
|
+
<Button mode="bleed" text="Hover me" />
|
|
291
|
+
</Tooltip>,
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
const button = screen.getByText('Hover me')
|
|
295
|
+
|
|
296
|
+
// Validate tooltip content is not rendered
|
|
297
|
+
expect(screen.queryByText('Tooltip content')).not.toBeInTheDocument()
|
|
298
|
+
fireEvent.focus(button)
|
|
299
|
+
act(() => jest.advanceTimersByTime(delay))
|
|
300
|
+
|
|
301
|
+
// Validate tooltip content is rendered
|
|
302
|
+
screen.getByText('Tooltip content')
|
|
303
|
+
|
|
304
|
+
act(() => {
|
|
305
|
+
fireEvent.keyDown(button, {key: 'Escape', code: 'Escape'})
|
|
306
|
+
})
|
|
307
|
+
// Validate tooltip content is not rendered anymore
|
|
308
|
+
expect(screen.queryByText('Tooltip content')).not.toBeInTheDocument()
|
|
309
|
+
})
|
|
310
|
+
it('With <TooltipDelayGroupProvider /> closes immediately with Escape key', () => {
|
|
311
|
+
const delay = 150
|
|
312
|
+
|
|
313
|
+
jest.useFakeTimers()
|
|
314
|
+
|
|
315
|
+
render(
|
|
316
|
+
<TooltipDelayGroupProvider delay={{close: delay}}>
|
|
317
|
+
<Tooltip
|
|
318
|
+
content={<Text size={1}>{'Tooltip content'}</Text>}
|
|
319
|
+
placement={'top'}
|
|
320
|
+
delay={{close: delay}}
|
|
321
|
+
>
|
|
322
|
+
<Button mode="bleed" text="Hover me" />
|
|
323
|
+
</Tooltip>
|
|
324
|
+
</TooltipDelayGroupProvider>,
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
const button = screen.getByText('Hover me')
|
|
328
|
+
|
|
329
|
+
// Validate tooltip content is not rendered
|
|
330
|
+
expect(screen.queryByText('Tooltip content')).not.toBeInTheDocument()
|
|
331
|
+
fireEvent.focus(button)
|
|
332
|
+
|
|
333
|
+
act(() => jest.advanceTimersByTime(delay))
|
|
334
|
+
|
|
335
|
+
// Validate tooltip content is rendered
|
|
336
|
+
screen.getByText('Tooltip content')
|
|
337
|
+
|
|
338
|
+
act(() => {
|
|
339
|
+
fireEvent.keyDown(button, {key: 'Escape', code: 'Escape'})
|
|
340
|
+
})
|
|
341
|
+
// Validate tooltip content is not rendered anymore
|
|
342
|
+
expect(screen.queryByText('Tooltip content')).not.toBeInTheDocument()
|
|
343
|
+
})
|
|
344
|
+
})
|
|
278
345
|
})
|
|
@@ -177,23 +177,27 @@ export const Tooltip = forwardRef(function Tooltip(
|
|
|
177
177
|
const closeDelay = isInsideGroup ? delayGroupContext.closeDelay : closeDelayProp
|
|
178
178
|
|
|
179
179
|
const handleIsOpenChange = useCallback(
|
|
180
|
-
(open: boolean) => {
|
|
180
|
+
(open: boolean, immediate?: boolean) => {
|
|
181
181
|
if (isInsideGroup) {
|
|
182
182
|
// When it's inside a group, the open or close status will be handled by the group.
|
|
183
183
|
if (open) {
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
const groupedOpenDelay = immediate ? 0 : openDelay
|
|
185
|
+
|
|
186
|
+
delayGroupContext.setIsGroupActive(open, groupedOpenDelay)
|
|
187
|
+
delayGroupContext.setOpenTooltipId(tooltipId, groupedOpenDelay)
|
|
186
188
|
} else {
|
|
187
189
|
const minimumGroupDeactivateDelay = 200 // We should provide some delay to allow the user to reach the next tooltip.
|
|
188
190
|
const groupDeactivateDelay =
|
|
189
191
|
closeDelay > minimumGroupDeactivateDelay ? closeDelay : minimumGroupDeactivateDelay
|
|
190
192
|
|
|
191
193
|
delayGroupContext.setIsGroupActive(open, groupDeactivateDelay)
|
|
192
|
-
delayGroupContext.setOpenTooltipId(null, closeDelay)
|
|
194
|
+
delayGroupContext.setOpenTooltipId(null, immediate ? 0 : closeDelay)
|
|
193
195
|
}
|
|
194
196
|
} else {
|
|
197
|
+
const standaloneDelay = immediate ? 0 : open ? openDelay : closeDelay
|
|
198
|
+
|
|
195
199
|
// When it's not inside a group, the open or close status will be handled by the tooltip itself.
|
|
196
|
-
setIsOpen(open,
|
|
200
|
+
setIsOpen(open, standaloneDelay)
|
|
197
201
|
}
|
|
198
202
|
},
|
|
199
203
|
[isInsideGroup, delayGroupContext, openDelay, tooltipId, closeDelay, setIsOpen],
|
|
@@ -243,6 +247,22 @@ export const Tooltip = forwardRef(function Tooltip(
|
|
|
243
247
|
// Update reference
|
|
244
248
|
useEffect(() => refs.setReference(referenceElement), [referenceElement, refs])
|
|
245
249
|
|
|
250
|
+
useEffect(() => {
|
|
251
|
+
// If the user clicks on escape key, close the tooltip.
|
|
252
|
+
if (!showTooltip) return
|
|
253
|
+
|
|
254
|
+
function handleWindowKeyDown(event: KeyboardEvent) {
|
|
255
|
+
if (event.key === 'Escape') {
|
|
256
|
+
handleIsOpenChange(false, true)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
window.addEventListener('keydown', handleWindowKeyDown)
|
|
261
|
+
|
|
262
|
+
return () => {
|
|
263
|
+
window.removeEventListener('keydown', handleWindowKeyDown)
|
|
264
|
+
}
|
|
265
|
+
}, [handleIsOpenChange, showTooltip])
|
|
246
266
|
const setArrow = useCallback(
|
|
247
267
|
(arrowEl: HTMLDivElement | null) => {
|
|
248
268
|
arrowRef.current = arrowEl
|