Skip to main content
The CModalDanger component is an organism that extends the BModal component with preset styling for dangerous or destructive actions. It features error-colored primary button and full-width button layout.

Props

state
Record<string, any> | null
default:"null"
The state object for form management
schema
Record<string, any> | null
default:"null"
The schema for form validation
title
string
required
The title of the modal
description
string
required
The description text explaining the dangerous action
text
string
default:""
Simple text content for the modal body (alternative to default slot)
primaryButtonText
string
default:"Eliminar"
Text for the primary (danger) button. Default is “Eliminar” (Delete in Spanish)
secondaryButtonText
string
default:"Cancelar"
Text for the secondary (cancel) button. Default is “Cancelar” (Cancel in Spanish)

Model

v-model
boolean
required
Controls the open/closed state of the modal

Events

on-click-primary-button
() => void
Emitted when the primary (danger) button is clicked
on-click-secondary-button
() => void
Emitted when the secondary (cancel) button is clicked

Slots

default
Custom body content (only used when text prop is not provided)

Preset Configuration

The component automatically applies:
  • Primary Button Color: error (red/danger color)
  • Button Layout: Full-width blocks (has-buttons-block)
  • Default Primary Text: “Eliminar” (Delete)
  • Default Secondary Text: “Cancelar” (Cancel)

Usage

Basic Delete Confirmation

<template>
  <div>
    <UButton color="error" @click="isOpen = true">Delete Item</UButton>
    
    <CModalDanger
      v-model="isOpen"
      title="Delete Item"
      description="This action cannot be undone"
      text="Are you sure you want to delete this item? All associated data will be permanently removed."
      @on-click-primary-button="handleDelete"
    />
  </div>
</template>

<script setup>
const isOpen = ref(false)

function handleDelete() {
  console.log('Item deleted')
  isOpen.value = false
}
</script>

Custom Button Text

<template>
  <CModalDanger
    v-model="isOpen"
    title="Remove User"
    description="Permanent account deletion"
    text="This will permanently delete the user account and all associated data."
    primary-button-text="Remove User"
    secondary-button-text="Keep User"
    @on-click-primary-button="handleRemoveUser"
  />
</template>

With Custom Content

<template>
  <CModalDanger
    v-model="isOpen"
    title="Delete Project"
    description="This will affect multiple resources"
    @on-click-primary-button="handleDelete"
  >
    <div class="space-y-3">
      <p class="font-semibold">The following will be deleted:</p>
      <ul class="list-disc list-inside space-y-1">
        <li>{{ itemCount }} tasks</li>
        <li>{{ fileCount }} files</li>
        <li>{{ memberCount }} team members will lose access</li>
      </ul>
      <p class="text-error font-medium">
        This action is irreversible!
      </p>
    </div>
  </CModalDanger>
</template>

<script setup>
const itemCount = ref(42)
const fileCount = ref(156)
const memberCount = ref(8)
</script>

With Form Validation

<template>
  <CModalDanger
    v-model="isOpen"
    title="Delete Account"
    description="Type DELETE to confirm"
    :state="formState"
    :schema="formSchema"
    @on-click-primary-button="handleDeleteAccount"
  >
    <UFormField label="Type DELETE to confirm" name="confirmation">
      <UInput 
        v-model="formState.confirmation" 
        placeholder="DELETE"
      />
    </UFormField>
  </CModalDanger>
</template>

<script setup>
import { z } from 'zod'

const isOpen = ref(false)

const formState = reactive({
  confirmation: ''
})

const formSchema = z.object({
  confirmation: z.literal('DELETE', {
    errorMap: () => ({ message: 'You must type DELETE to confirm' })
  })
})

function handleDeleteAccount() {
  console.log('Account deleted')
  isOpen.value = false
}
</script>

Batch Delete Confirmation

<template>
  <div>
    <UButton 
      color="error" 
      :disabled="selectedItems.length === 0"
      @click="isOpen = true"
    >
      Delete Selected ({{ selectedItems.length }})
    </UButton>
    
    <CModalDanger
      v-model="isOpen"
      title="Delete Multiple Items"
      description="Bulk deletion warning"
      :text="`You are about to delete ${selectedItems.length} items. This cannot be undone.`"
      primary-button-text="Delete All"
      @on-click-primary-button="handleBulkDelete"
    />
  </div>
</template>

<script setup>
const selectedItems = ref([1, 2, 3, 4, 5])

function handleBulkDelete() {
  console.log('Deleting items:', selectedItems.value)
  selectedItems.value = []
  isOpen.value = false
}
</script>

Deactivate vs Delete

<template>
  <CModalDanger
    v-model="isOpen"
    title="Deactivate User"
    description="Temporary suspension"
    text="The user will be deactivated but their data will be preserved. You can reactivate them later."
    primary-button-text="Deactivate"
    @on-click-primary-button="handleDeactivate"
    @on-click-secondary-button="handleCancel"
  />
</template>

Best Practices

  1. Clear Communication: Always provide clear title and description explaining the consequence
  2. Specific Actions: Use specific button text (“Delete Project” vs generic “Delete”)
  3. Additional Context: Include details about what will be affected
  4. Confirmation: For critical actions, require typing confirmation or additional verification
  5. Undo Information: If possible, mention if the action can be undone or recovered

Styling

The modal inherits all styling from BModal but overrides:
  • Primary button color is always error
  • Buttons are always full-width (has-buttons-block)
Source: /home/daytona/workspace/source/app/components/c/modal/c-modal-danger.vue:70

Build docs developers (and LLMs) love