src/views/AboutView.vue
import { useConfirmDialog } from "@/composables/useConfirmDialog";
import ConfirmDialog from "@/components/ConfirmDialog.vue";
const { confirm } = useConfirmDialog({
title: "HOME画面に移動してよろしいですか?",
text: "OKボタンを押すと画面遷移します",
});
const handleDialog = async () => {
if (await confirm()) {
console.log("okがクリックされました");
} else {
console.log("cancelがクリックされました");
}
};
<button @click="handleDialog">Aboutダイアログ表示</button>
<ConfirmDialog></ConfirmDialog>
以上です。シンプルに記述できますね。
必要なファイルは2ファイル 「src/composables/useConfirmDialog.ts」 「src/components/ConfirmDialog.vue」 だけです。
src/composables/useConfirmDialog.ts
import { ref } from "vue";
type DialogText = {
title?: string;
text?: string;
ok?: string;
cancel?: string;
};
const isOpen = ref<boolean>(false);
const dialogText = ref<DialogText>({
title: "○○します。よろしいですか?",
text: "確認して以下のボタンをクリックしてください。",
ok: "OK",
cancel: "キャンセル",
});
let _resolve: (value: boolean | PromiseLike<boolean>) => void;
export function useConfirmDialog(props: DialogText = {}) {
if (props.title) dialogText.value.title = props.title;
if (props.text) dialogText.value.text = props.text;
if (props.ok) dialogText.value.ok = props.ok;
if (props.cancel) dialogText.value.cancel = props.cancel;
const confirm = () => {
isOpen.value = true;
return new Promise<boolean>((resolve) => {
_resolve = resolve;
});
};
const ok = () => {
isOpen.value = false;
_resolve(true);
};
const cancel = () => {
isOpen.value = false;
_resolve(false);
};
const close = () => {
isOpen.value = false;
};
return {
confirm,
ok,
cancel,
close,
isOpen,
dialogText,
};
}
src/components/ConfirmDialog.vue
<template>
<div
v-if="isOpen"
class="confirm-dialog confirm-dialog-show"
id="confirm-dialog149993"
style="margin-top: -86px"
>
<div class="confirm-dialog-title">
{{ dialogText.title }}
</div>
<div class="confirm-dialog-content">
<p class="confirm-dialog-message">
{{ dialogText.text }}
</p>
</div>
<div class="confirm-dialog-action">
<button @click="ok" class="btn-ok">{{ dialogText.ok }}</button>
<button @click="cancel" class="btn-cancel">
{{ dialogText.cancel }}
</button>
</div>
</div>
<div v-if="isOpen" @click="close" class="confirm-dialog-overlay"></div>
</template>
<script lang="ts" setup>
import { useConfirmDialog } from "@/composables/useConfirmDialog";
const { isOpen, ok, cancel, close, dialogText } = useConfirmDialog();
</script>
<style scoped>
.confirm-dialog {
color: #1b1919;
position: fixed;
z-index: 1061;
border-radius: 2px;
width: 400px;
margin-left: -200px;
background-color: #fff;
-webkit-box-shadow: 0 11px 15px -7px rgba(0, 0, 0, 0.2),
0 24px 38px 3px rgba(0, 0, 0, 0.14), 0 9px 46px 8px rgba(0, 0, 0, 0.12);
box-shadow: 0 11px 15px -7px rgba(0, 0, 0, 0.2),
0 24px 38px 3px rgba(0, 0, 0, 0.14), 0 9px 46px 8px rgba(0, 0, 0, 0.12);
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
left: 50%;
top: 50%;
font-size: 16px;
}
.confirm-dialog.confirm-dialog-show {
-webkit-animation: bounceIn 0.35s ease;
-o-animation: bounceIn 0.35s ease;
animation: bounceIn 0.35s ease;
}
.confirm-dialog .confirm-dialog-title {
text-align: center;
padding: 24px 30px 20px 30px;
font-size: 18px;
line-height: 1.4;
font-weight: bold;
color: #1b1919;
}
.confirm-dialog .confirm-dialog-title + .confirm-dialog-content {
padding-top: 0;
}
.confirm-dialog .confirm-dialog-content {
text-align: justify;
padding: 30px 30px 5px 30px;
}
.confirm-dialog .confirm-dialog-content .confirm-dialog-message {
font-size: 14px;
line-height: 1.4;
text-align: center;
margin: 0;
padding: 0;
color: #635a56;
}
.confirm-dialog .confirm-dialog-content .confirm-dialog-prompt input {
width: 100%;
height: 36px;
display: inline-block;
padding: 6px 0;
-webkit-box-shadow: none;
box-shadow: none;
border: none;
outline: none;
font-size: 16px;
color: #1b1919;
border-bottom: 1px solid #d9d6d4;
}
.confirm-dialog .confirm-dialog-action {
display: flex;
flex-direction: column;
margin: 10px 30px;
}
.confirm-dialog .confirm-dialog-action [class*="btn-"] {
font-size: 14px;
margin: 7px 0;
cursor: pointer;
color: #1b1919;
height: 36px;
min-width: 88px;
text-align: center;
display: inline-block;
border: 1px solid #dedede;
border-radius: 12px;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0.12);
-webkit-transition: all 0.45s cubic-bezier(0.23, 1, 0.32, 1);
-o-transition: all 0.45s cubic-bezier(0.23, 1, 0.32, 1);
transition: all 0.45s cubic-bezier(0.23, 1, 0.32, 1);
}
.confirm-dialog .confirm-dialog-action .btn-ok {
background-color: black;
border-color: black;
color: #fff;
}
.confirm-dialog .confirm-dialog-action .btn-ok:active {
background-color: #444;
}
.confirm-dialog .confirm-dialog-action .btn-cancel {
background-color: #ececec;
color: #635a56;
}
.confirm-dialog .confirm-dialog-action .btn-cancel:active {
background-color: #dcdcdc;
}
@media all and (max-width: 540px) {
.confirm-dialog {
width: auto;
margin-left: 0;
margin-right: 0;
left: 15px;
right: 15px;
}
}
.confirm-dialog-overlay {
position: fixed;
background-color: #000;
z-index: 1060;
height: 100%;
width: 100%;
left: 0;
right: 0;
top: 0;
bottom: 0;
opacity: 0.4;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
-webkit-transition: opacity 0.45s cubic-bezier(0.23, 1, 0.32, 1);
-o-transition: opacity 0.45s cubic-bezier(0.23, 1, 0.32, 1);
transition: opacity 0.45s cubic-bezier(0.23, 1, 0.32, 1);
}
</style>