fix(ui): unify dialogs and complete theme component coverage
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
<script setup lang="ts">
|
||||
import { onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { lockDialogScroll } from './dialogScroll'
|
||||
const props = withDefaults(defineProps<{ label: string; dismissible?: boolean }>(), { dismissible: true })
|
||||
const emit = defineEmits<{ close: [] }>()
|
||||
const dialog = ref<HTMLDialogElement>()
|
||||
let restoreScroll: (() => void) | undefined
|
||||
let previousFocus: HTMLElement | null = null
|
||||
function dismiss() { if (props.dismissible) emit('close') }
|
||||
function keydown(event: KeyboardEvent) {
|
||||
if (event.key === 'Escape') { event.preventDefault(); event.stopPropagation(); dismiss() }
|
||||
}
|
||||
onMounted(() => {
|
||||
previousFocus = document.activeElement as HTMLElement | null
|
||||
if (!dialog.value) return
|
||||
restoreScroll = lockDialogScroll(dialog.value)
|
||||
dialog.value.showModal()
|
||||
const first = dialog.value.querySelector<HTMLElement>('[autofocus], input:not(:disabled):not([type="hidden"]), textarea:not(:disabled), select:not(:disabled), button:not(:disabled)')
|
||||
;(first ?? dialog.value).focus()
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
dialog.value?.close()
|
||||
restoreScroll?.()
|
||||
if (previousFocus?.isConnected) previousFocus.focus()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<dialog ref="dialog" class="app-dialog" :aria-label="label" tabindex="-1" @cancel.prevent="dismiss" @keydown="keydown" @click.self="dismiss">
|
||||
<slot />
|
||||
</dialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.app-dialog { position: fixed; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none; margin: 0; border: 0; padding: clamp(12px, 3vw, 24px); background: transparent; color: var(--color-text-primary); overflow: hidden; overscroll-behavior: contain; }
|
||||
.app-dialog[open] { display: grid; place-items: center; }
|
||||
.app-dialog::backdrop { background: var(--color-background-overlay); }
|
||||
.app-dialog :deep(> .modal), .app-dialog :deep(> .modal-card) { min-width: 0; max-width: 100%; max-height: 100%; overflow: auto; overscroll-behavior: contain; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user