feat: use dialog element for overlay component (#1594)

This commit is contained in:
Phan An 2022-11-18 16:31:36 +01:00 committed by GitHub
parent 2dbda9fe7e
commit bd0585e587
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 67 additions and 74 deletions

View file

@ -17,13 +17,21 @@ global.ResizeObserver = global.ResizeObserver ||
unobserve: vi.fn()
}))
window.HTMLMediaElement.prototype.load = vi.fn()
window.HTMLMediaElement.prototype.play = vi.fn()
window.HTMLMediaElement.prototype.pause = vi.fn()
HTMLMediaElement.prototype.load = vi.fn()
HTMLMediaElement.prototype.play = vi.fn()
HTMLMediaElement.prototype.pause = vi.fn()
window.HTMLDialogElement.prototype.show = vi.fn()
window.HTMLDialogElement.prototype.showModal = vi.fn()
window.HTMLDialogElement.prototype.close = vi.fn()
HTMLDialogElement.prototype.show = vi.fn(function mock () {
this.open = true
})
HTMLDialogElement.prototype.showModal = vi.fn(function mock () {
this.open = true
})
HTMLDialogElement.prototype.close = vi.fn(function mock () {
this.open = false
})
window.BASE_URL = 'http://test/'

View file

@ -1,7 +1,6 @@
import UnitTestCase from '@/__tests__/UnitTestCase'
import { expect, it } from 'vitest'
import { eventBus } from '@/utils'
import { waitFor } from '@testing-library/vue'
import SoundBars from '@/components/ui/SoundBars.vue'
import Overlay from './Overlay.vue'
@ -32,14 +31,18 @@ new class extends UnitTestCase {
['info'],
['warning'],
['error']
])('renders %s type', async (type) => expect((await this.renderComponent(type)).html()).toMatchSnapshot())
])('renders %s type', async type => {
const { getByTestId, html } = await this.renderComponent(type)
expect(html()).toMatchSnapshot()
expect((getByTestId('overlay') as HTMLDialogElement).open).toBe(true)
})
it('closes', async () => {
const { queryByTestId } = await this.renderComponent()
expect(queryByTestId('overlay')).not.toBeNull()
const { getByTestId } = await this.renderComponent()
eventBus.emit('HIDE_OVERLAY')
await waitFor(() => expect(queryByTestId('overlay')).toBeNull())
expect((getByTestId('overlay') as HTMLDialogElement).open).toBe(false)
})
}
}

View file

@ -1,6 +1,6 @@
<template>
<div v-if="state.showing" id="overlay" :class="state.type" class="overlay" data-testid="overlay">
<div class="display">
<dialog ref="el" :class="state.type" @cancel.prevent="onCancel" data-testid="overlay">
<div class="wrapper">
<SoundBars v-if="state.type === 'loading'"/>
<icon v-if="state.type === 'error'" :icon="faCircleExclamation"/>
<icon v-if="state.type === 'warning'" :icon="faWarning"/>
@ -9,49 +9,51 @@
<span class="message" v-html="state.message"/>
</div>
<button v-if="state.dismissible" class="btn-dismiss" type="button" @click.prevent="hide">Close</button>
</div>
</dialog>
</template>
<script lang="ts" setup>
import { faCircleCheck, faCircleExclamation, faCircleInfo, faWarning } from '@fortawesome/free-solid-svg-icons'
import { defineAsyncComponent, reactive, ref } from 'vue'
import { eventBus } from '@/utils'
import { defineAsyncComponent, reactive } from 'vue'
const SoundBars = defineAsyncComponent(() => import('@/components/ui/SoundBars.vue'))
const el = ref<HTMLDialogElement>()
const state = reactive<OverlayState>({
showing: false,
dismissible: false,
type: 'loading',
message: ''
})
const show = (options: Partial<OverlayState>) => {
const show = (options: Partial<OverlayState> = {}) => {
Object.assign(state, options)
state.showing = true
el.value?.open || el.value?.showModal()
}
const hide = () => (state.showing = false)
const hide = () => el.value?.close()
const onCancel = () => state.dismissible && hide()
eventBus.on('SHOW_OVERLAY', options => show(options))
.on('HIDE_OVERLAY', () => hide())
</script>
<style lang="scss">
#overlay {
background-color: var(--color-bg-primary);
flex-direction: column;
<style lang="scss" scoped>
dialog {
border: 0;
padding: 0;
background: transparent;
.display {
&::backdrop {
background: rgba(0, 0, 0, 0.7);
}
.wrapper {
display: flex;
align-items: baseline;
justify-content: center;
.message {
margin-left: 6px;
}
gap: 6px;
}
&.error {
@ -71,7 +73,7 @@ eventBus.on('SHOW_OVERLAY', options => show(options))
}
&.warning {
color: var(--color-highlight);
color: var(--color-orange);
}
}
</style>

View file

@ -1,61 +1,56 @@
// Vitest Snapshot v1
exports[`renders error type 1`] = `
<div id="overlay" class="error overlay" data-testid="overlay">
<div class="display">
<!--v-if--><br data-testid="icon" icon="[object Object]">
<dialog class="error" data-testid="overlay" data-v-889cac1d="" open="">
<div class="wrapper" data-v-889cac1d="">
<!--v-if--><br data-testid="icon" icon="[object Object]" data-v-889cac1d="">
<!--v-if-->
<!--v-if-->
<!--v-if--><span class="message">Look at me now</span>
<!--v-if--><span class="message" data-v-889cac1d="">Look at me now</span>
</div>
<!--v-if-->
</div>
</dialog>
`;
exports[`renders info type 1`] = `
<div id="overlay" class="info overlay" data-testid="overlay">
<div class="display">
<dialog class="info" data-testid="overlay" data-v-889cac1d="" open="">
<div class="wrapper" data-v-889cac1d="">
<!--v-if-->
<!--v-if-->
<!--v-if--><br data-testid="icon" icon="[object Object]">
<!--v-if--><span class="message">Look at me now</span>
<!--v-if--><br data-testid="icon" icon="[object Object]" data-v-889cac1d="">
<!--v-if--><span class="message" data-v-889cac1d="">Look at me now</span>
</div>
<!--v-if-->
</div>
</dialog>
`;
exports[`renders loading type 1`] = `
<div id="overlay" class="loading overlay" data-testid="overlay">
<div class="display"><i data-v-47e95701=""><span data-v-47e95701=""></span><span data-v-47e95701=""></span><span data-v-47e95701=""></span></i>
<dialog class="loading" data-testid="overlay" data-v-889cac1d="" open="">
<div class="wrapper" data-v-889cac1d=""><i data-v-47e95701="" data-v-889cac1d=""><span data-v-47e95701=""></span><span data-v-47e95701=""></span><span data-v-47e95701=""></span></i>
<!--v-if-->
<!--v-if-->
<!--v-if-->
<!--v-if--><span class="message">Look at me now</span>
<!--v-if--><span class="message" data-v-889cac1d="">Look at me now</span>
</div>
<!--v-if-->
</div>
</dialog>
`;
exports[`renders success type 1`] = `
<div id="overlay" class="success overlay" data-testid="overlay">
<div class="display">
<dialog class="success" data-testid="overlay" data-v-889cac1d="" open="">
<div class="wrapper" data-v-889cac1d="">
<!--v-if-->
<!--v-if-->
<!--v-if-->
<!--v-if--><br data-testid="icon" icon="[object Object]"><span class="message">Look at me now</span>
<!--v-if--><br data-testid="icon" icon="[object Object]" data-v-889cac1d=""><span class="message" data-v-889cac1d="">Look at me now</span>
</div>
<!--v-if-->
</div>
</dialog>
`;
exports[`renders warning type 1`] = `
<div id="overlay" class="warning overlay" data-testid="overlay">
<div class="display">
<dialog class="warning" data-testid="overlay" data-v-889cac1d="" open="">
<div class="wrapper" data-v-889cac1d="">
<!--v-if-->
<!--v-if--><br data-testid="icon" icon="[object Object]">
<!--v-if--><br data-testid="icon" icon="[object Object]" data-v-889cac1d="">
<!--v-if-->
<!--v-if--><span class="message">Look at me now</span>
<!--v-if--><span class="message" data-v-889cac1d="">Look at me now</span>
</div>
<!--v-if-->
</div>
</dialog>
`;

View file

@ -6,7 +6,6 @@ import Router from '@/router'
export type ReadonlyInjectionKey<T> = InjectionKey<[Readonly<T> | DeepReadonly<T>, Closure]>
export const RouterKey: InjectionKey<Router> = Symbol('Router')
export const ScreenNameKey: ReadonlyInjectionKey<ScreenName> = Symbol('ScreenName')
export const DialogBoxKey: InjectionKey<Ref<InstanceType<typeof DialogBox>>> = Symbol('DialogBox')
export const MessageToasterKey: InjectionKey<Ref<InstanceType<typeof MessageToaster>>> = Symbol('MessageToaster')

View file

@ -267,7 +267,6 @@ interface EqualizerBandElement extends HTMLElement {
}
type OverlayState = {
showing: boolean
dismissible: boolean
type: 'loading' | 'success' | 'info' | 'warning' | 'error'
message: string

View file

@ -185,19 +185,6 @@ label {
height: 32px;
}
.overlay {
position: fixed;
top: 0;
left: 0;
z-index: 9999;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, .7);
@include vertical-center();
}
.font-size- {
&0 {
font-size: 0;