From 2f7153fbfee2e3131eed68b390b37297ee1aff65 Mon Sep 17 00:00:00 2001 From: Dennis Postma <dennis@directonline.io> Date: Mon, 10 Jun 2024 01:42:57 +0200 Subject: [PATCH] Added resizing logics to modal + option to disable this --- public/assets/icons/resize-icon.svg | 4 ++ src/components/screens/Login.vue | 1 + src/components/utilities/Modal.vue | 84 +++++++++++++++++++++++++++-- 3 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 public/assets/icons/resize-icon.svg diff --git a/public/assets/icons/resize-icon.svg b/public/assets/icons/resize-icon.svg new file mode 100644 index 0000000..abbecc7 --- /dev/null +++ b/public/assets/icons/resize-icon.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools --> +<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M21 15L15 21M21 8L8 21" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> +</svg> \ No newline at end of file diff --git a/src/components/screens/Login.vue b/src/components/screens/Login.vue index 3f5cf59..8a4eed7 100644 --- a/src/components/screens/Login.vue +++ b/src/components/screens/Login.vue @@ -122,6 +122,7 @@ async function registerFunc() { flex-direction: column; background-color: rgba($white, 0.5); border-radius: 3px; + border: $light-gray 1px solid; min-width: 400px; margin: 0 auto; diff --git a/src/components/utilities/Modal.vue b/src/components/utilities/Modal.vue index 5e539f9..c1f80c1 100644 --- a/src/components/utilities/Modal.vue +++ b/src/components/utilities/Modal.vue @@ -1,6 +1,6 @@ <template> <Teleport to="body"> - <div class="modal-container" :style="{ top: y + 'px', left: x + 'px' }" v-if="isModalOpenRef"> + <div class="modal-container" v-if="isModalOpenRef" :style="{ top: y + 'px', left: x + 'px', width: width + 'px', height: height + 'px' }"> <div class="modal-header" @mousedown="startDrag"> <slot name="modalHeader" /> <div class="buttons"> @@ -10,6 +10,7 @@ </div> <div class="modal-body"> <slot name="modalBody" /> + <img v-if="isResizable" src="/assets/icons/resize-icon.svg" alt="resize" class="resize" @mousedown="startResize" /> </div> <div v-if="$slots.modalFooter" class="modal-footer"> <slot name="modalFooter" /> @@ -29,6 +30,18 @@ const properties = defineProps({ closable: { type: Boolean, default: true + }, + isResizable: { + type: Boolean, + default: true + }, + modalWidth: { + type: Number, + default: 500 + }, + modalHeight: { + type: Number, + default: 280 } }) @@ -46,6 +59,35 @@ function close() { emit('modal:close') } +// (re)size logics +const width = ref(properties.modalWidth) +const height = ref(properties.modalHeight) +let minWidth = ref(200) +let minHeight = ref(100) +let isResizing = ref(false) + +let startWidth = 0 +let startHeight = 0 + +const startResize = (event: MouseEvent) => { + isResizing.value = true + startWidth = width.value - event.clientX + startHeight = height.value - event.clientY + event.preventDefault() +} + +const resizeModal = (event: MouseEvent) => { + if (!isResizing.value) return + let newWidth = startWidth + event.clientX + let newHeight = startHeight + event.clientY + width.value = newWidth > minWidth.value ? newWidth : minWidth.value + height.value = newHeight > minHeight.value ? newHeight : minHeight.value +} + +const stopResize = () => { + isResizing.value = false +} + // make modal draggable let startX = 0 let startY = 0 @@ -85,13 +127,41 @@ const stopDrag = () => { onMounted(() => { addEventListener('mousemove', drag) addEventListener('mouseup', stopDrag) + addEventListener('mousemove', resizeModal) + addEventListener('mouseup', stopResize) + addEventListener('resize', handleResize) }) onUnmounted(() => { removeEventListener('mousemove', drag) removeEventListener('mouseup', stopDrag) + removeEventListener('mousemove', resizeModal) + removeEventListener('mouseup', stopResize) + removeEventListener('resize', handleResize) }) + +// Make sure modal doesn't go off screen +watch( + () => x.value, (value) => { + if (value < 0) { x.value = 0 } else if (value + width.value > window.innerWidth) { x.value = window.innerWidth - width.value } + } +) +watch( + () => y.value, (value) => { + if (value < 0) { y.value = 0 } else if (value + height.value > window.innerHeight) { y.value = window.innerHeight - height.value } + } +) + +// also on window resize function +function handleResize() { + if (x.value + width.value > window.innerWidth) { + x.value = window.innerWidth - width.value + } + if (y.value + height.value > window.innerHeight) { + y.value = window.innerHeight - height.value + } +} </script> <style lang="scss"> @@ -102,8 +172,6 @@ onUnmounted(() => { top: 0; left: 0; max-width: 1000px; - min-width: 500px; - min-height: 280px; background-color: rgba($dark-gray, 0.8); border: 2px solid $dark-cyan; z-index: 999; @@ -158,6 +226,16 @@ onUnmounted(() => { padding: 15px; flex-grow: 1; + .resize { + filter: invert(60%); + position: absolute; + bottom: 0; + right: 0; + width: 20px; + height: 20px; + cursor: nwse-resize; + } + .submit { display: inline-block; button {