Components

Modal

Show dialogs and confirmations with UiModal and UiConfirmModal.

UiModal presents content in an overlay; UiConfirmModal adds confirm / cancel actions. Open and close them through their exposed handle (showDialog / closeDialog).

Open a modal

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

const modal = ref()
</script>

<template>
  <UiButton variant="filled" text="Open" @click="modal.showDialog()" />

  <UiModal ref="modal" title="Profile" size="md">
    <template #body>
      <p>Modal content…</p>
    </template>
  </UiModal>
</template>

Start in a field

When a modal opens, the browser focuses its first focusable element, often the close button. To start in a field, mark the field autofocus. On a Colorffy input the attribute lands on the component's wrapper, so UiModal focuses the control inside it:

<template>
  <UiModal ref="modal" title="Invite members" size="md">
    <template #body>
      <UiInputTags id="emails" v-model="emails" label="Email addresses" autofocus />
    </template>
  </UiModal>
</template>

Pick a mode and size

<template>
  <UiModal ref="sheet" mode="side-sheet" size="lg" title="Filters" />
</template>

Confirm a destructive action

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

const confirm = ref()

function remove() {
  // delete, then close
  confirm.value.closeDialog()
}
</script>

<template>
  <UiConfirmModal
    ref="confirm"
    variant="danger"
    title="Delete item?"
    message="This can't be undone."
    confirm-label="Delete"
    cancel-label="Cancel"
    @confirm="remove"
  />
</template>

UiModal props

PropTypeDefaultDescription
mode'modal' | 'side-sheet' | 'headless'—Dialog shape.
size'sm' | 'md' | 'lg' | 'fullscreen'—Dialog size: up to --cffy-container-md (28rem), --cffy-container-2xl (42rem) or --cffy-container-4xl (56rem); fullscreen fills the viewport.
titlestring | null—Header title.
messagestring | null—Body message.
closeOnClickOutsidebooleantrueDismiss when clicking the backdrop.
showAsModalboolean | nulltrueLegacy modal toggle.
customClass / bodyDialogClassstring | string[] | Record<string, boolean> | null—Extra classes.

Exposed: showDialog(), closeDialog(). Emits: close, whenever the dialog closes: closeDialog(), a click outside, or Esc. Slots: #header (defaults to title), #body (defaults to message), #footer.

UiConfirmModal

Extends UiModal with:

PropTypeDefaultDescription
variant'danger' | 'warning' | 'success' | 'primary''danger'Icon and confirm-button color.
confirmLabelstring | null'Delete'Confirm button label.
cancelLabelstring'Cancel'Cancel button label.
isLoadingbooleanfalseLoading state on the confirm button.
loadingLabelstring'Deleting...'Text while loading.

Emits: confirm (the dialog stays open until you call closeDialog()), and close whenever it closes: the cancel button, a click outside, Esc or closeDialog(). Slots: #messages — extra body content, rendered after title and message.

CSS variables

Every dialog (UiModal, UiConfirmModal, side sheets) reads these variables. Set them on :root to restyle all dialogs. On screens below 992px the bottom sheet keeps its own motion and top-rounded corners.

:root {
  --cffy-dialog-radius: var(--cffy-radius-xl);
  --cffy-dialog-backdrop-color: color-mix(in oklab, black 60%, transparent);
  --cffy-dialog-duration: var(--cffy-duration-400);
}
VariableDefaultControls
--cffy-dialog-bg-color / --cffy-dialog-color--cffy-surface-overlay / --cffy-on-backgroundBackground, and title and body text
--cffy-dialog-border-color--cffy-outline-overlayBorder
--cffy-dialog-radius--cffy-shape-container (12px)Corners of modals, side sheets and confirms
--cffy-dialog-shadow--cffy-shadow-xlShadow
--cffy-dialog-padding--cffy-space-16Content padding
--cffy-dialog-spacing--cffy-space-20Space around the body and between footer buttons (half)
--cffy-dialog-max-size90%Maximum width and height
--cffy-dialog-title-font-size / --cffy-dialog-title-font-weight--cffy-fs-base / --cffy-fw-700Title
--cffy-dialog-subtitle-color / --cffy-dialog-subtitle-font-size--cffy-muted-a10 / --cffy-fs-2xsSubtitle
--cffy-dialog-icon-bg-color / --cffy-dialog-icon-color--cffy-primary-a10 / --cffy-on-primaryHeadless-mode icon
--cffy-dialog-backdrop-color--cffy-overlay-backdropBackdrop behind modals
--cffy-dialog-backdrop-blur5pxBlur with dialog-backdrop-blur
--cffy-dialog-easing / --cffy-dialog-duration--cffy-ease-overshoot-soft / --cffy-duration-600Opening animation of modals and side sheets
Copyright © 2026