Skip to content

Modal ​

A modal can be used in a variaty of ways. It can be used to display a message to the user, ask for a confirmation or to display a form. The appropriate type can be set with the type property.

Example Usage ​

Example

vue
<template>
  <SkButton class="mr-s mb-s" @click="modal.open()">Open Alert</SkButton>
  <SkButton class="mr-s mb-s" @click="modal2.open()">Async Confirm</SkButton>
  <SkButton class="mr-s mb-s" @click="programmaticConfirm()">Programmatic Confirm</SkButton>
  <SkButton class="mr-s mb-s" @click="programmaticPrompt()">Programmatic Prompt</SkButton>

  <SkModal
    ref="modal"
    type="alert"
    title="Ich bin ein einfaches Modal"
    description="Das ist meine Beschreibung. "
    action-text="Ok, verstanden"
    class="bg-orange"
  />

  <SkModal
    ref="modal2"
    type="confirm"
    title="Möchtest du wirklich löschen?"
    action-text="Löschen"
    :action="deleteDummyItem"
  >
    <h1>Wirklich löschen?</h1>
    <p>Das kann nicht rückgängig gemacht werden.</p>

    <template #footer="{ action, close, loading }">
      <SkButton type="secondary" @click="close()">Abbrechen</SkButton>
      <SkButton v-if="!loading" type="primary" @click="action()">Löschen</SkButton>
      <SkButton v-else type="primary" :loading="true">Löschen...</SkButton>
    </template>
  </SkModal>
</template>

<script setup>
import { onMounted, ref } from 'vue';
// import { useModal } from '@/composables';
const modal = ref(undefined);
const modal2 = ref(undefined);

// const { createModal } = useModal();
let createModal = undefined;
async function deleteDummyItem() {
  const prom = new Promise((resolve, reject) => {
    setTimeout(() => {
      Math.random() > 0.5 ? resolve() : reject('This is an error');
    }, 1000);
  });
  await prom;
}

// this is only neccessary for server side rendering
onMounted(async () => {
  const { useModal } = await import('my-lib/composables');
  createModal = useModal().createModal;
});

// two different usecases
async function programmaticPrompt() {
  const modal3 = await createModal({
    title: 'Vergib einen Namen',
    description: 'Wie soll die Serie heißen?',
    actionText: 'Speichern',
    type: 'prompt',
  });
  const result = await modal3.open();
  alert(result);
}

async function programmaticConfirm() {
  const modal4 = await createModal({
    title: 'Element wirklich löschen?',
    description: 'Dies kann nicht rückgängig gemacht werden.',
    actionText: 'Löschen',
    type: 'confirm',
  });
  modal4.action(async () => {
    await deleteDummyItem();
  });
  modal4.open();
}
</script>

Composable ​

You can use the useModal composable to create a modal instance. This can be used to open and close the modal programmatically.

vue
<script setup>
import { useModal } from '@/composables';
const { createModal } = useModal();

async function programmaticConfirm() {
  const modal4 = await createModal({
    title: 'Element wirklich löschen?',
    // ... other component props
  })
    .action(async () => {
      // some async action
    })
    .open();
}
</script>

Reference ​

Props ​

NameTypeDefaultDescription
typeString'confirm'Type of modal - 'alert', 'prompt' or 'confirm'
titleString'Are you sure?'Title text shown in modal
actionTextStringText for action button
actionFunctionCallback for action button
descriptionStringDescriptive text shown under title

Events ​

NameDescription
closeEmitted when modal closes
confirmEmitted when action is confirmed
errorEmitted on any error

Methods ​

MethodDescription
open()Open the modal
close()Close the modal
action()Set callback for action button, can be an async function to automaticly show loading state

Exposed ​

PropertyTypeDescription
loadingBooleanLoading state
elElementModal element reference

Slots ​

NameDescription
defaultDefault slot for modal content
footerFooter slot for action buttons

Slot Props ​

The footer slot is provided the following props:

PropTypeDescription
actionFunctionCall this prop to trigger the primary action
closeFunctionCall this prop to close the modal
loadingBooleanIndicates background action is in progress

For example:

<template #footer="{ action, close, loading }">
  <button :disabled="loading" @click="action">
    Confirm
  </button>
  <button @click="close">
    Cancel
  </button>
</template>

The default slot does not have any provided props. Any content can be passed to this slot, for example:

<template #default>
   <p>Custom modal content</p>
</template>