aboutsummaryrefslogtreecommitdiff
path: root/src/ui/c-modal
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/c-modal')
-rw-r--r--src/ui/c-modal/c-modal.demo.vue15
-rw-r--r--src/ui/c-modal/c-modal.theme.ts11
-rw-r--r--src/ui/c-modal/c-modal.vue74
3 files changed, 100 insertions, 0 deletions
diff --git a/src/ui/c-modal/c-modal.demo.vue b/src/ui/c-modal/c-modal.demo.vue
new file mode 100644
index 0000000..c4349f6
--- /dev/null
+++ b/src/ui/c-modal/c-modal.demo.vue
@@ -0,0 +1,15 @@
+<script lang="ts" setup>
+const modal1 = ref();
+</script>
+
+<template>
+ <div>
+ <c-button @click="() => modal1?.open()">
+ Open Modal
+ </c-button>
+
+ <c-modal ref="modal1">
+ Content
+ </c-modal>
+ </div>
+</template>
diff --git a/src/ui/c-modal/c-modal.theme.ts b/src/ui/c-modal/c-modal.theme.ts
new file mode 100644
index 0000000..0681417
--- /dev/null
+++ b/src/ui/c-modal/c-modal.theme.ts
@@ -0,0 +1,11 @@
+import { defineThemes } from '../theme/theme.models';
+import { appThemes } from '../theme/themes';
+
+export const { useTheme } = defineThemes({
+ dark: {
+ background: appThemes.dark.background,
+ },
+ light: {
+ background: appThemes.light.background,
+ },
+});
diff --git a/src/ui/c-modal/c-modal.vue b/src/ui/c-modal/c-modal.vue
new file mode 100644
index 0000000..af92f01
--- /dev/null
+++ b/src/ui/c-modal/c-modal.vue
@@ -0,0 +1,74 @@
+<script setup lang="ts">
+import { useTheme } from './c-modal.theme';
+
+const props = withDefaults(defineProps<{ open?: boolean; centered?: boolean }>(), {
+ open: false,
+ centered: true,
+});
+const emit = defineEmits(['update:open']);
+const isOpen = useVModel(props, 'open', emit, { passive: true });
+
+const { centered } = toRefs(props);
+
+function close() {
+ isOpen.value = false;
+}
+
+function open() {
+ isOpen.value = true;
+}
+
+function toggle() {
+ isOpen.value = !isOpen.value;
+}
+
+defineExpose({
+ close,
+ open,
+ toggle,
+ isOpen,
+});
+
+defineOptions({
+ inheritAttrs: false,
+});
+
+const theme = useTheme();
+const modal = ref();
+
+onClickOutside(modal, () => {
+ if (isOpen.value) {
+ close();
+ }
+});
+</script>
+
+<template>
+ <transition>
+ <div v-if="isOpen" class="c-modal--overlay" fixed left-0 top-0 z-10 h-full w-full flex justify-center px-2 :class="{ 'items-center': centered }">
+ <div ref="modal" class="c-modal--container" v-bind="$attrs" max-w-xl w-full flex-grow rounded-md pa-24px>
+ <slot />
+ </div>
+ </div>
+ </transition>
+</template>
+
+<style scoped lang="less">
+.c-modal--overlay {
+ background-color: rgba(0, 0, 0, 0.5);
+}
+
+.c-modal--container {
+ background-color: v-bind('theme.background');
+}
+
+.v-enter-active,
+.v-leave-active {
+ transition: opacity 0.3s ease-in-out;
+}
+
+.v-enter-from,
+.v-leave-to {
+ opacity: 0;
+}
+</style>