46 lines
1.3 KiB
Vue
46 lines
1.3 KiB
Vue
<script setup lang="ts">
|
|
import Button from '~/components/ui/Button.vue'
|
|
|
|
const { title, overPopover = false } = defineProps<{ title:string, overPopover?:true }>()
|
|
const isOpen = defineModel<boolean>({ default:false })
|
|
|
|
// TODO:
|
|
// - [ ] Trap focus while open
|
|
// - [ ] Close on ESC (Implement a global stack of closable/focusable elements)
|
|
// - [ ] Add aria role to inform screenreaders
|
|
</script>
|
|
|
|
<template>
|
|
<Teleport to="body">
|
|
<Transition mode="out-in">
|
|
<div v-if="isOpen" @click.exact.stop="isOpen = false" class="funkwhale overlay">
|
|
<div @click.stop class="funkwhale modal" :class="[$slots.alert && 'has-alert', overPopover && 'over-popover']" >
|
|
<h2>
|
|
{{ title }}
|
|
<Button icon="bi-x-lg" ghost @click="isOpen = false" />
|
|
</h2>
|
|
|
|
<div class="modal-content">
|
|
<Transition>
|
|
<div v-if="$slots.alert" class="alert-container">
|
|
<div>
|
|
<slot name="alert" />
|
|
</div>
|
|
</div>
|
|
</Transition>
|
|
|
|
<slot />
|
|
</div>
|
|
<div v-if="$slots.actions" class="modal-actions">
|
|
<slot name="actions" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Transition>
|
|
</Teleport>
|
|
</template>
|
|
|
|
<style lang="scss">
|
|
@import './modal.scss'
|
|
</style>
|