Nychthemeron/packages/library/tests/use-dismissable-layer.spec.ts
Matthew L McPeak 57c94e1207 feat: add useDismissableLayer composable
Replaces reka-ui's Escape/click-outside dismissal behavior for Dialog
and Select.
2026-07-13 18:10:06 -04:00

82 lines
2.7 KiB
TypeScript

import { describe, it, expect, vi, afterEach } from 'vitest'
import { ref } from 'vue'
import { useDismissableLayer } from '../src/lib/use-dismissable-layer'
function firePointerDown(target: EventTarget) {
const event = new PointerEvent('pointerdown', { bubbles: true, cancelable: true })
target.dispatchEvent(event)
}
describe('useDismissableLayer', () => {
afterEach(() => {
document.body.replaceChildren()
})
it('calls onDismiss on Escape keydown while active', () => {
const containerRef = ref<HTMLElement | null>(document.createElement('div'))
const active = ref(true)
const onDismiss = vi.fn()
useDismissableLayer(containerRef, active, { onDismiss })
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
expect(onDismiss).toHaveBeenCalledOnce()
})
it('does not call onDismiss on Escape when inactive', () => {
const containerRef = ref<HTMLElement | null>(document.createElement('div'))
const active = ref(false)
const onDismiss = vi.fn()
useDismissableLayer(containerRef, active, { onDismiss })
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
expect(onDismiss).not.toHaveBeenCalled()
})
it('calls onDismiss on pointerdown outside the container', () => {
const container = document.createElement('div')
const outside = document.createElement('div')
document.body.append(container, outside)
const containerRef = ref<HTMLElement | null>(container)
const active = ref(true)
const onDismiss = vi.fn()
useDismissableLayer(containerRef, active, { onDismiss })
firePointerDown(outside)
expect(onDismiss).toHaveBeenCalledOnce()
})
it('does not call onDismiss on pointerdown inside the container', () => {
const container = document.createElement('div')
const inside = document.createElement('span')
container.append(inside)
document.body.append(container)
const containerRef = ref<HTMLElement | null>(container)
const active = ref(true)
const onDismiss = vi.fn()
useDismissableLayer(containerRef, active, { onDismiss })
firePointerDown(inside)
expect(onDismiss).not.toHaveBeenCalled()
})
it('skips onDismiss when onPointerDownOutside calls preventDefault', () => {
const container = document.createElement('div')
const outside = document.createElement('div')
document.body.append(container, outside)
const containerRef = ref<HTMLElement | null>(container)
const active = ref(true)
const onDismiss = vi.fn()
useDismissableLayer(containerRef, active, {
onDismiss,
onPointerDownOutside: (event) => event.preventDefault(),
})
firePointerDown(outside)
expect(onDismiss).not.toHaveBeenCalled()
})
})