Skip to content
On this page

Dialog

A Dialog component is a modal window that can be used to display information or ask for user input. It is a wrapper around the Headless UI Dialog component.

Preview & Playground 🖼️

Here you may find a preview of the component, with error & possible variants.

🏄 Click to expand the code
vue
<script setup lang="ts">
import { Button, Dialog, RichSelect } from '@flavorly/vanilla-components'
import { ref } from 'vue'
import CheckIcon from '~icons/heroicons/check-solid'
const open = ref(false)
const open2 = ref(false)
const valueFromSelect = ref()
const shouldDivide = ref(false)
const position = ref('center')

const openDivided = () => {
  open2.value = !open2.value
  shouldDivide.value = true
}

const openPlain = () => {
  open2.value = !open2.value
  shouldDivide.value = false
}

const openAligned = (align = 'center') => {
  open2.value = !open2.value
  position.value = align
  shouldDivide.value = false
}
</script>

<template>
  <PreviewWrapper>
    <div class="flex flex-col items-center justify-center mx-auto space-y-3 ">
      <Button
        label="Open Dialog"
        @click="open = !open"
      />

      <Button
        label="Open another Dialog"
        @click="openPlain"
      />

      <Button
        label="Open Divided Dialog"
        @click="openDivided"
      />

      <Button
        label="Centered Dialog"
        @click="openAligned('center')"
      />

      <Button
        label="Bottom Dialog"
        @click="openAligned('bottom')"
      />

      <Button
        label="Top Dialog"
        @click="openAligned('top')"
      />
    </div>

    <Dialog v-model="open">
      <div>
        <div class="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100">
          <CheckIcon
            class="h-6 w-6 text-green-600"
            aria-hidden="true"
          />
        </div>
        <div class="mt-3 text-center sm:mt-5">
          <h3 class="text-lg font-medium leading-6 text-gray-900 dark:text-white">
            🎉 Thank you for testing Vanilla!
          </h3>
          <div class="mt-2">
            <p class="text-sm text-gray-500 dark:text-gray-400">
              Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur amet labore.
            </p>
          </div>

          <div class="my-2">
            <RichSelect
              v-model="valueFromSelect"
              :options="[
                { value: 'Option 1', text: 'One Option' },
                { value: 'Option 2', text: 'Two Options' },
              ]"
              :teleport="true"
              :clearable="true"
              :hide-search-box="true"
              feedback="Im useful helper out here, choose wisely"
              placeholder="Please select an option"
            />
          </div>
        </div>
      </div>
      <div class="mt-5 sm:mt-6">
        <Button
          type="button"
          class="w-full"
          variant="primary"
          @click="open = false"
        >
          Yeah, now close me.
        </Button>
      </div>
    </Dialog>

    <Dialog
      v-model="open2"
      :divided="shouldDivide"
      :position="position"
      title="Another Dialog"
    >
      <div class="text-center">
        <p class="text-sm text-gray-500 dark:text-gray-200">
          This is just another modal, divided, and with padded body
          and also two action buttons.
        </p>
      </div>
      <template #footer>
        <Button
          type="button"
          variant="primary"
          @click="open2 = false"
        >
          Yeah, now close me.
        </Button>
        <Button
          type="button"
          variant="secondary"
          @click="open2 = false"
        >
          No wait.
        </Button>
      </template>
    </Dialog>
  </PreviewWrapper>
</template>

Props 📥

Props available for this component extending the default variant & global props.

PropDescriptionAccepted ValuesDefault
modelValueControls the open/close of the dialogBooleanfalse
titleA title for the dialogStringundefined
teleportIf we should teleport the dropdownBooleantrue
teleportToElement to teleportstringbody
closeableOnClickOutsideClicking outside closes the dialogBooleantrue
overlayAdds a overlay behind the dialogBooleantrue
closeableIf we should allow open/close the dialogBooleantrue
closeableOnPressEscapeKeyboard ESC closes the dialogBooleantrue
paddingGive padding to the whole modalBooleanfalse
paddingBodyGive padding to the Body of the modalBooleantrue
dividedDivide header and footer with borderBooleanfalse
dividedDivide header, body & footerBooleantrue
asRender the modal as this elementStringdiv
sizeSize of the modaldefault,small,medium,large,fulldefault
positionPosition of the modalcenter-bottom, center-top, center, top, bottomcenter

Slots 🧬

Current slots available for this component are the following:

Slot default

Actual content to show inside the modal

Slot header

Header part of the modal, usually used to place the title or/and subtitle.

Footer part of the modal, usually used to place buttons or actions.

Events 🚇

Here you may find the events emitted by this component.

EventDescriptionValue
update:modelValueWhen the value changesany

| open | Dialog was opened | Boolean | | close | Dialog was closed | Boolean | | opening | Dialog is about to be opened — before the transition starts | Boolean | | opened | Dialog was opened — after the transition finishes | Boolean | | closing | Dialog is about to be closed — before the transition starts | Boolean | | closed | Dialog was closed — after the transition finishes | Boolean |

💡 A note on closing and open

The open and close events are emitted when the dialog is opened or closed, but the modelValue is not updated yet. It will take a few milliseconds in order to circumvent the transition effect and provide a smooth experience.

Additional Components

Because this is mostly a wrapper around HeadlessUI, you can still use the native headlessUI compoments like DialogTitle to achieve any accessibility needs.

The dialog footer component is a smart component that will take from 1 to 3 items and will divide them in a smart way. This is really useful when you have one or more actions on the dialog, it will make sure to apply the correct grid.

Released under the MIT License.