Composables

useConfirm

Create a confirmation modal for user actions that require confirmation before proceeding.

The useConfirm composable provides a simple way to display a confirmation modal to users before executing potentially destructive or important actions. It uses the Nuxt UI overlay system to show a modal dialog with customizable title, message, and buttons.

Basic Usage

<script setup lang="ts">
const { confirm } = useConfirm({
  title: 'Delete Account',
  body: 'Are you sure you want to delete your account? This action cannot be undone.',
  onConfirm: async () => {
    await $fetch('/api/account', { method: 'DELETE' })
  },
})

async function handleDelete() {
  const confirmed = await confirm()
  if (confirmed) {
    // User clicked "Confirm" and the onConfirm callback completed
    await navigateTo('/goodbye')
  } else {
    // User clicked "Cancel" or closed the modal
    console.log('Deletion canceled')
  }
}
</script>

<template>
  <UButton
    label="Delete Account"
    color="error"
    @click="handleDelete"
  />
</template>

Properties

The useConfirm composable accepts a single object with the following properties:

PropertyTypeRequiredDescription
titlestringYesThe title displayed at the top of the modal
bodystringYesThe message displayed to the user explaining what they're confirming
onConfirm() => Promise<void | false>YesAsync function executed when user clicks the confirm button. Return false to prevent the modal from closing
confirmBtnPropsButtonPropsNoProps to customize the confirm button (defaults: label: "Confirm", color: "error")
cancelBtnPropsButtonPropsNoProps to customize the cancel button (defaults: label: "Cancel", color: "neutral", variant: "ghost")

Return Value

The composable returns an object with:

  • confirm() - An async function that opens the modal and returns a promise that resolves to:
    • true when the user clicks confirm and onConfirm completes successfully
    • false when the user clicks cancel or closes the modal

Examples

Custom Button Labels

const { confirm } = useConfirm({
  title: 'Leave Page',
  body: 'You have unsaved changes. Are you sure you want to leave?',
  confirmBtnProps: {
    label: 'Leave',
    color: 'warning',
  },
  cancelBtnProps: {
    label: 'Stay',
    color: 'primary',
  },
  onConfirm: async () => {
    // Discard changes
  },
})

Inline Usage

For one-off confirmations, you can call the composable inline:

async function deleteItem(itemId: string) {
  const { confirm } = useConfirm({
    title: 'Delete Item',
    body: 'This item will be permanently deleted.',
    onConfirm: async () => {
      await $fetch(`/api/items/${itemId}`, { method: 'DELETE' })
    },
  })

  const confirmed = await confirm()
  if (confirmed) {
    // Item deleted successfully
    await refreshNuxtData()
  }
}

Non-Destructive Confirmation

const { confirm } = useConfirm({
  title: 'Publish Post',
  body: 'Your post will be visible to all users.',
  confirmBtnProps: {
    label: 'Publish',
    color: 'primary',
  },
  onConfirm: async () => {
    await $fetch('/api/posts/publish', { method: 'POST' })
  },
})

With Error Handling

const { successToast, errorToast } = useToastMessage()

const { confirm } = useConfirm({
  title: 'Ban User',
  body: 'This user will be banned from the platform.',
  onConfirm: async () => {
    try {
      await $fetch('/api/users/ban', { method: 'POST' })
      successToast('User banned successfully')
    } catch (error) {
      errorToast('Failed to ban user')
      // Returning false prevents the modal from closing
      return false
    }
  },
})

Notes

The onConfirm callback is automatically wrapped with loading state handling. The modal buttons will be disabled while the callback is executing.
If the onConfirm callback throws an error or returns false, the modal will not close automatically. This allows you to handle errors gracefully without dismissing the modal.
The composable uses the Nuxt UI useOverlay system under the hood, which handles modal stacking and dismissal automatically.

Copyright © 2026