Modals

The modal store will display your own components as modal dialogs.

Import and add the ModalContainer in your App.vue:

import { ModalContainer } from "vue-haystack";
<template>
  <div>
    <router-view />
    <ModalContainer />
  </div>
</template>

Creating a modal

You will need to write your own modal components, as a very simple example (MyModalComponent.vue):

<template>
  <div style="padding: 2rem; background-color: white">My modal content</div>
</template>

From withing a modal, you can call useModal() that provides a close function. This also allows you to pass data if needed.

import { useModal } from "vue-haystack";

const modal = useModal();
modal.close();
// with data
modal.close({ foo: "bar" });
// you can explicitely type the data (this does not affect `onClose` unfortunately)
modal.close<{ foo: string }>({ foo: "bar" });

Showing a modal

import { useModalStore } from "vue-haystack";
import MyModalComponent from "./MyModalComponent.vue";

useModalStore().push(MyModalComponent);

push allows you to pass props, event listeners and modal options, here is a full example:

modalStore.push(
  MyModalComponent,
  { foo: "bar" }, // props
  { log: (text: string) => console.log(text) }, // listeners
  { closeOnOverlayClick: true }, // options
);

push also returns an object with an onClose function to react to close events. If using typescript, set the generic type onClose so the data parameter is properly typed.

modalStore.push(MyModalComponent).onClose<MyDataType>((data) => {
  if (data === undefined) {
    // data will be undefined if the modal is closed without data, e.g. when it is closed by clicking the overlay
    return;
  }
  console.log(data);
});

Customization

The model store will display the modal centered and with an overlay. The default overlay can be customized using the overlay slot.

<ModalContainer>
  <template #overlay>
    <div style="width: 100%; height: 100%; background-color: red;"></div>
  </template>
</ModalContainer>

You can also customize the component rendering. This is a bit more complicated but is rarely necessary. The default

<ModalContainer>
  <template #default="{modal, activeModal}">
    <component
      :is="modal.component"
      v-show="modal.id === activeModal?.id"
      :key="modal.id"
      v-bind="modal.props"
      v-on="modal.listeners"
    />
  </template>
</ModalContainer>

If you need more control (e.g. for animations), you can always implement your own ModalContainer. The default component is relatively simple and can be used as templateopen in new window.