Skip to content

Calendar in a modal

Mount the calendar only while the dialog is open (v-if). Initialization runs on mount and needs real viewport widths to pick the compact layout.

vue
<template>
  <button @click="open = true">Book a call</button>

  <dialog ref="dialog" @close="open = false">
    <ZaptimeCalendar v-if="open" :config="config" @booking-confirmed="onBooked" />
    <button @click="dialog?.close()">Close</button>
  </dialog>
</template>

<script setup lang="ts">
import { ref, watch } from "vue";
import { ZaptimeCalendar } from "@zaptime/vue3";
import type { ZaptimeConfig } from "@zaptime/vue3";
import type { ReservationResponse } from "@zaptime/core";

const open = ref(false);
const dialog = ref<HTMLDialogElement>();

const config: ZaptimeConfig = { token: import.meta.env.VITE_ZAPTIME_TOKEN, compact: true };

watch(open, (v) => (v ? dialog.value?.showModal() : dialog.value?.close()));

function onBooked(reservation: ReservationResponse) {
  setTimeout(() => (open.value = false), 2000); // let the success screen show briefly
}
</script>

Set compact: true when the dialog is narrower than 860px so the calendar does not overflow.