Vue.jsを使っていてモーダルを実装する際にアクセシビリティ等々考慮したりすると実装が難しかったりするので何かしらライブラリを利用したいと思ったときにVue Final ModalがVue3にも対応していてサクッと実装できて便利だったのでメモ📝
使い方
以下の公式ガイド通りですが使い方をメモ📝
install
$ npm install vue-final-modal
使い方
デフォルトのデザイン付きのModalを使う場合には以下の公式サンプル通りに以下のCSSを読み込ませて、
import 'vue-final-modal/style.css'
VueFinalModal
を使ってあげれば大丈夫でした。
<script setup lang="ts"> import { VueFinalModal } from 'vue-final-modal' defineProps<{ title?: string }>() const emit = defineEmits<{ (e: 'confirm'): void }>() </script> <template> <VueFinalModal class="flex justify-center items-center" content-class="flex flex-col max-w-xl mx-4 p-4 bg-white dark:bg-gray-900 border dark:border-gray-700 rounded-lg space-y-2" > <h1 class="text-xl"> {{ title }} </h1> <slot /> <button class="mt-1 ml-auto px-2 border rounded-lg" @click="emit('confirm')"> Confirm </button> </VueFinalModal> </template>
自分は以下のような感じでComponent内でstyleをimportして、外部コンポーネントが直接VueFinalModalに依存するのが嫌だったのでWrapするComponentを用意して利用できるようにしました。
<template> <VueFinalModal class="common-modal" @closed="() => $emit('close')"> <div class="common-modal__body"> <slot /> </div> </VueFinalModal> </template> <script setup lang="ts"> import "vue-final-modal/style.css"; import { VueFinalModal } from "vue-final-modal"; defineEmits(["close"]); </script> <!-- NOTE: VueFinalModalがScoped CSSでstyleできないようなのでscopedを外している --> <!-- https://github.com/vue-final/vue-final-modal/issues/312 --> <style lang="scss"> @use "@css/variables" as *; .common-modal { display: flex; justify-content: center; align-items: center; &__body { background-color: $white-color; } } </style>
以下のissueにある通りVue Final ModalがVue 3のteleportを利用しておりscoped CSSを利用するとモーダルにスタイルが当たらないようだったのでscoped
を外すようにしています。
おそらくteleportでコンポーネント外にモーダルで表示する要素が移動してscopedの範囲外になってしまうためと思われる🤔(defaultだとbody直下に移動してしまうっぽい)