Skip to content

@overlastic/vue

@overlastic/vue is used to define Overlay components in Vue3 and supports both imperative and declarative usage!

Installation

Use vue-demi to support the composition-api usage in Vue2 & 3!

If you are using Vue version 2.7 or below, please install @vue/composition-api.

If you cannot use composition-api for some reason, use @overlastic/vue2.

Install

With pnpm:

sh
pnpm add @overlastic/vue

With yarn:

sh
yarn add @overlastic/vue

Usage

Step 1: Define Component

overlays is suitable for most components. Using useOverlayDefine can provide finer control over the component process.

vue
<!-- overlay.vue -->
<script setup>
import { defineEmits, defineProps } from 'vue'
import { useOverlayDefine } from '@overlastic/vue'
const props = defineProps({
  title: String,
})
const { visible, resolve, reject } = useOverlayDefine({
  // Duration of overlay duration to avoid premature destruction of the component
  duration: 1000,
})
</script>

<template>
  <div v-if="visible" @click="resolve(`${title}:confirmed`)">
    {{ title }}
  </div>
</template>

Step 2: Create Overlay

You can use the defineOverlay method to convert the component into a modal dialog in Javascript / Typescript, which allows you to call it.

ts
import { defineOverlay } from '@overlastic/vue'
import OverlayComponent from './overlay.vue'

// Convert to imperative callback
const callback = defineOverlay(OverlayComponent)
// Call the component and get the value of the resolve callback
const value = await callback({ title: 'callbackOverlay' })
// value === "callbackOverlay:confirmed"

You can also use renderOverlay to directly call the component and skip the defineOverlay method.

ts
import { renderOverlay } from '@overlastic/vue'
import OverlayComponent from './overlay.vue'

const value = await renderOverlay(OverlayComponent, {
  title: 'useOverlayDefine'
})
// value === "useOverlayDefine:confirmed"

Define Component

To use a component created with @overlastic/vue, it can be used not only with imperative methods, but also in <template>.

This is an optional option that is very useful when porting old components.

To use it in <template>, modal and event must be explicitly defined.

vue
<!-- Component.vue -->
<script setup>
import { defineEmits, defineProps } from 'vue-demi'
import { useOverlayDefine } from '@overlastic/vue'
const props = defineProps({
  title: String,
  // To use in Template, you need to define the field used by v-model (default corresponds to visible)
  visible: Boolean
})

// Define event types used in the component (default: reject, resolve)
defineEmits(['reject', 'resolve'])

const { visible, resolve, reject } = useOverlayDefine({
  // If using template rendering, duration can be omitted
})
</script>

After defining the parameters, the overlay component can be used in the template.

vue
<script setup>
import Overlay from './overlay.vue'
const visible = ref(false)

function resolve(value) {
  // ...
}
function reject(value) {
  // ...
}
</script>

<template>
  <Overlay v-model:visible="visible" title="Hairyf" @resolve="resolve" @reject="reject" />
</template>

If you want to replace them with other fields and event names, you can do so using the model and events config of useOverlayDefine.

ts
const props = defineProps({
  title: String,
  modalValue: Boolean
})

defineEmits(['nook', 'ok'])

const { visible, resolve, reject } = useOverlayDefine({
  events: { resolve: 'ok', reject: 'nook' },
  model: 'modalValue',
})

Injection Provider ✨ (v0.4.8)

In the case of using Provider, the overlays mode does not simply access the content injected into the current context. By supporting the following APIs, it allows the use of injected components to inherit the context:

html
<script setup>
import { OverlayProvider } from '@overlastic/react'
const visible = ref(false)

function resolve(value) {
  // ...
}
function reject(value) {
  // ...
}
</script>
<template>
  <OverlayProvider>
    <App />
  </OverlayProvider>
</template>

Using in a page:

html
<script setup>
import { useOverlay } from '@overlastic/vue'

const openDialog = useOverlay(CustomDialog)

</script>
<template>
  <button @click="openDialog({ /* props... */ })">
    Open Modal
  </button>
</template>

Typescript

You can ensure type safety by passing in the props and resolved parameters.

ts
// types.ts
export interface DialogProps {
  title?: string
}
export type Resolved = string

// component setup
const props = defineProps<DialogProps>()
const { resolve, reject } = useOverlayDefine<Resolved>()

// define overlay
const callback = defineOverlay<DialogProps, Resolved>(Component)

Of course, you can also use Vue's ExtractInferTypes to extract runtime props parameters.

ts
import type { ExtractInferTypes } from 'vue-demi'
// types.ts
export const dialogProps = {
  title: String
}
export type DialogProps = ExtractInferTypes<typeof overlayProps>
// ...
// define overlay
const callback = defineOverlay<DialogProps, Resolved>(Component)

MIT Licensed