Skip to content
navy

Modal

Animated modal with origin morphing effect.

Live Demo

Usage

Basic Modal (Manual State)

If title not provided - header not drawn;

You can control width of the modal with width of inner content

vue
<template>
  <orio-button @click="showModal = true"> Open </orio-button>

  <orio-modal v-model:show="showModal" :origin="null" title="Modal title">
    <p style="width: 50rem;">Your content here</p>
  </orio-modal>
</template>

<script setup>
const showModal = ref(false);
</script>

The useModal() composable simplifies modal management and automatically handles animation origins:

vue
<template>
  <orio-button @click="openModal"> Open Modal </orio-button>

  <orio-modal v-bind="modalProps">
    <h2>Modal Title</h2>
    <p>Content here</p>
    <orio-button @click="modalProps.show = false">Close</orio-button>
  </orio-modal>
</template>

<script setup>
const { modalProps, openModal } = useModal();
</script>

Animation Control: With vs Without Event

The key difference between openModal() and openModal is how the click event is handled:

vue
<template>
  <div class="demo-row">
    <!-- NO Animation - Calling with () without passing event -->
    <orio-button @click="openModal()"> Open Modal (No Animation) </orio-button>

    <!-- WITH Animation - Passing event automatically -->
    <orio-button @click="openModal"> Open Modal (With Animation) </orio-button>

    <!-- WITH Animation - Explicitly passing event -->
    <orio-button @click="openModal($event)">
      Open Modal (Explicit Event)
    </orio-button>
  </div>

  <orio-modal v-bind="modalProps">
    <h2>Modal Content</h2>
    <p>This modal may or may not animate based on how it was opened!</p>
  </orio-modal>
</template>

<script setup>
const { modalProps, openModal } = useModal();
</script>

Explanation:

  • @click="openModal()" - Calls the function immediately, no event is passed → Simple fade-in
  • @click="openModal" - Vue passes the click event automatically → Morphing animation from button
  • @click="openModal($event)" - Explicitly passes the event → Morphing animation from button

Manual Origin Tracking (Without useModal)

If you need more control, you can manually track the origin:

vue
<template>
  <orio-button @click="openModal"> Open with Animation </orio-button>

  <orio-modal v-model:show="showModal" :origin="origin">
    <p>Morphs from button!</p>
  </orio-modal>
</template>

<script setup>
const showModal = ref(false);
const origin = ref(null);

function openModal(event) {
  const rect = event.target.getBoundingClientRect();
  origin.value = {
    x: rect.left,
    y: rect.top,
    width: rect.width,
    height: rect.height,
  };
  showModal.value = true;
}
</script>

Props

PropTypeDefaultDescription
showBoolean-Modal visibility (v-model:show)
originOriginRect | nullnullAnimation origin point

OriginRect Type

typescript
interface OriginRect {
  x: number;
  y: number;
  width: number;
  height: number;
}

Events

EventPayloadDescription
update:showbooleanEmitted when modal closes

Features

  • Click outside to close
  • Backdrop blur effect
  • Morphing animation from origin element
  • Smooth fade-in when no origin provided