Skip to content

Instantly share code, notes, and snippets.

@JavascriptMick
Created May 13, 2023 14:27
Show Gist options
  • Save JavascriptMick/77838a21d4ec1b5606dd5ae09ad21a67 to your computer and use it in GitHub Desktop.
Save JavascriptMick/77838a21d4ec1b5606dd5ae09ad21a67 to your computer and use it in GitHub Desktop.
Modal Component wrapper for Nuxt 3 + DaisyUI
import { Modal } from '#components';
// seems pretty stoopid that I need to do this in a seperate file but it seems to work
export type ModalType = typeof Modal extends new () => infer T ? T : never;
<script lang="ts" setup>
/*
pre-requisites.. Tailwind + DaisyUI
setup...
import { ModalType } from '~~/components/modal.type';
const myCoolModal = ref<ModalType>();
myCoolModal.value!.open();
template...
<Modal ref="myCoolModal" showCancel @closeOk="doSomethingUsefulOnClose()">
<h3 class="font-bold text-xl">Modal Title</h3>
<p class="py-4">Some kind of text</p>
</Modal>
*/
import { ref } from 'vue';
// component property that controls the visibility of the modal
const modalIsVisible = ref(false);
// props for which buttons to show
interface Props {
showOk?: boolean
showCancel?: boolean
}
const props = withDefaults(defineProps<Props>(), {
showOk: true,
showCancel: false,
})
// open event (exposed to parent)
const open = () => {
modalIsVisible.value = true;
}
defineExpose({ open });
// close events emitted on modal close
const emit = defineEmits(['closeOk', 'closeCancel']);
const closeOk = () => {
emit('closeOk');
modalIsVisible.value = false;
}
const closeCancel = () => {
emit('closeCancel');
modalIsVisible.value = false;
}
</script>
<template>
<!-- the input controls the visibility of the modal (css shenanigans) the v-model allows me to control it in turn from the wrapper component -->
<input type="checkbox" id="my-modal" class="modal-toggle" v-model="modalIsVisible" />
<div class="modal">
<div class="modal-box">
<slot />
<div class="flex justify-end space-x-2">
<!-- I decided not to use the 'for' directives which do the close in css so I can control the emission of events explicitly -->
<div class="modal-action" v-if="showOk">
<label class="btn btn-success" @click="closeOk()">Ok</label>
</div>
<div class="modal-action" v-if="showCancel">
<label class="btn btn-error" @click="closeCancel()">Cancel</label>
</div>
</div>
</div>
</div>
</template>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment