Skip to content

Destructive Action Modal

A safety-first pattern for confirming irreversible or high-impact actions using a modal and clear visual warnings.

Demo

Implementation

vue
<script setup lang="ts">
import { ref } from 'vue';

// 1. Component Imports (Default)
import CLModal from '@codeandfunction/callaloo/CLModal';
import CLButton from '@codeandfunction/callaloo/CLButton';
import CLText from '@codeandfunction/callaloo/CLText';

import { useToast } from '@codeandfunction/callaloo/composables/useToast';

// 2. Enum & Type Imports (Named)
import { 
  CLColors, 
  CLColorVariants,
  CLIconNames,
  CLTextTypes,
  CLBorderRadius,
  CLButtonTypes
} from '@codeandfunction/callaloo';

// 3. State & Logic
const isModalOpen = ref(false);
const isDeleting = ref(false);
const toast = useToast();

const openModal = (): void => {
  isModalOpen.value = true;
};

const closeModal = (): void => {
  isModalOpen.value = false;
};

const handleDelete = async (): Promise<void> => {
  isDeleting.value = true;
  await new Promise(resolve => setTimeout(resolve, 2000));
  isDeleting.value = false;
  isModalOpen.value = false;
  toast.showToast({
    color: CLColors.Success,
    message: 'Project deleted successfully!',
    title: 'Success',
  });
};
</script>

<template>
  <div class="pattern-preview">
    <div class="modal-demo-container">
      <CLButton 
        :color="CLColors.Danger" 
        :icon-before="CLIconNames.Trash"
        :type="CLButtonTypes.Button"
        @click="openModal"
      >
        Delete Project
      </CLButton>
      <CLModal
        modal-id="delete-confirmation"
        :is-open="isModalOpen"
        title="Confirm Deletion"
        :on-close="closeModal"
        max-width="450px"
        :border-radius="CLBorderRadius.Medium"
      >
        <template #body>
          <div class="warning-content">
            <CLText :type="CLTextTypes.Body">Are you sure you want to delete the project <strong>"Callaloo Documentation"</strong>? 
              This action cannot be undone.
            </CLText>
            <CLText :type="CLTextTypes.Small" :color="CLColors.Neutral">All associated data, including components, assets, and version history, will be permanently removed.
            </CLText>
          </div>
        </template>
        <template #footer>
          <div class="modal-footer-actions">
            <CLButton 
              :variant="CLColorVariants.Ghost" 
              :color="CLColors.Neutral"
              :type="CLButtonTypes.Button"
              @click="closeModal"
              :disabled="isDeleting"
            >
              Cancel
            </CLButton>
            <CLButton 
              :color="CLColors.Danger"
              :type="CLButtonTypes.Button"
              @click="handleDelete"
              :busy="isDeleting"
              :disabled="isDeleting"
            >
              Delete Permanently
            </CLButton>
          </div>
        </template>
      </CLModal>
    </div>
  </div>
</template>

<style scoped>
  .pattern-preview {
    display: flex;
    flex-direction: column;
    flex: 1;
  }
.modal-demo-container {
  display: flex;
  flex: 1;
  justify-content: center;
  align-items: center;
  padding: 4rem 2rem;
}
.modal-footer-actions {
  display: flex;
  justify-content: flex-end;
  gap: 1rem;
  width: 100%;
}
.warning-content {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
</style>

Released under the MIT License.