Skip to content

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 ​

PropTypeDefaultDescription
titlestring—Required; the dialog/sheet heading.
descriptionstring | undefinedundefinedSubtext under the heading.
loadingboolean | undefinedundefinedFalsy by default; truthy shows a spinner on Submit and disables both footer buttons.
submitDisabledboolean | undefinedundefinedFalsy by default; truthy disables only Submit (e.g. until the form validates).
submitLabelstring"Submit"Submit-button label.
cancelLabelstring"Cancel"Cancel-button label.

Emits ​

EventPayloadWhen
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 ​

SlotPropsContent
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: Dialog forwards leave/after:leave on desktop and cancel on mobile, and CreateDialog forwards neither. Only the footer's own Cancel emits cancel.
  • Like BottomSheet, Submit emits without closing; the footer's Cancel closes.