CreateDialog
A form-style wrapper around Dialog: the default slot becomes the modal body and the footer is pre-built as Cancel / Submit buttons, so creating a record is a one-liner. Like Dialog, it renders a Nuxt UI modal on desktop and collapses into a konsta bottom sheet below 1024px.
vue
<script setup lang="ts">
import RyderCreateDialog from "@opeolluwa/ryder/components/feedback/CreateDialog.vue"
</script>
<template>
<RyderCreateDialog v-model:open="open" title="Create thing" @submit="open = false">
<p>Form fields go in the body.</p>
</RyderCreateDialog>
</template>Examples
vue
<script setup lang="ts">
import { ref } from "vue";
import CreateDialog from "../../../src/components/feedback/CreateDialog.vue";
const open = ref(false);
const name = ref("");
const status = ref("");
function onSubmit() {
status.value = `created "${name.value}"`;
open.value = false;
name.value = "";
}
function onCancel() {
status.value = "cancelled";
}
</script>
<template>
<div class="space-y-3">
<div class="flex flex-wrap items-center gap-3">
<button
type="button"
class="rounded-lg bg-primary-600 px-4 py-2 text-sm font-medium text-white hover:bg-primary-700"
@click="open = true"
>
Create thing
</button>
<span class="text-sm text-gray-500 dark:text-white/50">
Last event: {{ status || "—" }}
</span>
</div>
<CreateDialog
v-model:open="open"
title="Create thing"
description="A modal on desktop, a konsta bottom sheet below 1024px."
submit-label="Create"
:submit-disabled="name.trim() === ''"
@submit="onSubmit"
@cancel="onCancel"
>
<label class="block text-sm font-medium text-gray-700 dark:text-white/80">
Name
<input
v-model="name"
type="text"
placeholder="Name"
class="mt-1 w-full rounded-lg border border-gray-200 px-3 py-2 text-sm dark:border-white/10"
/>
</label>
<p class="pt-2 text-xs text-gray-500 dark:text-white/40">
Submit stays disabled until the field is filled.
</p>
</CreateDialog>
</div>
</template>Props
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | — | Required; the dialog/sheet heading. |
description | string | undefined | undefined | Subtext under the heading. |
loading | boolean | undefined | undefined | Falsy by default; truthy shows a spinner on Submit and disables both footer buttons. |
submitDisabled | boolean | undefined | undefined | Falsy by default; truthy disables only Submit (e.g. until the form validates). |
submitLabel | string | "Submit" | Submit-button label. |
cancelLabel | string | "Cancel" | Cancel-button label. |
Emits
| Event | Payload | When |
|---|---|---|
submit | — | Submit was tapped. The dialog stays open — the app closes it. |
cancel | — | The footer's Cancel button was tapped; the dialog also closes itself. |
Slots
| Slot | Props | Content |
|---|---|---|
default | — | Form body, rendered into the dialog's body slot. |
footer | — | Replaces the built-in Cancel/Submit row (full width, right-aligned is up to you). |
Notes
- Wraps
Dialog, so it inherits the responsive modal → bottom-sheet behaviour. Dialog's own props (size,scrollable,dismissible,closeIcon) are not forwarded — CreateDialog only exposes the submit-form surface.- A backdrop tap closes the overlay but is not emitted here:
Dialogforwardsleave/after:leaveon desktop andcancelon mobile, and CreateDialog forwards neither. Only the footer's own Cancel emitscancel. - Like
BottomSheet, Submit emits without closing; the footer's Cancel closes.