diff options
| author | Terry Truong <terry06890@gmail.com> | 2023-01-04 23:55:10 +1100 |
|---|---|---|
| committer | Terry Truong <terry06890@gmail.com> | 2023-01-04 23:55:10 +1100 |
| commit | f93a728091e52ae5144a51fb6203fde8cdf02558 (patch) | |
| tree | 3de78eda743a8064212dda25dcc690371d9413f7 /src/components/SCollapsible.vue | |
| parent | 969a5351529971180748ef1a6c41b22da87b5af1 (diff) | |
Add event info modal
Add InfoModal.vue, SCollapsible.vue, and icons.
Update Timeline.vue, App.vue, lib.ts, and store.ts to display modal.
For testing, send/use dummy EventInfo from server (still waiting on image downloads).
Diffstat (limited to 'src/components/SCollapsible.vue')
| -rw-r--r-- | src/components/SCollapsible.vue | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/src/components/SCollapsible.vue b/src/components/SCollapsible.vue new file mode 100644 index 0000000..39b4283 --- /dev/null +++ b/src/components/SCollapsible.vue @@ -0,0 +1,61 @@ +<template> +<div :style="styles"> + <div class="hover:cursor-pointer" @click="onClick"> + <slot name="summary" :open="open">(Summary)</slot> + </div> + <transition @enter="onEnter" @after-enter="onAfterEnter" @leave="onLeave" @before-leave="onBeforeLeave"> + <div v-show="open" :style="contentStyles" class="max-h-0" ref="content"> + <slot name="content">(Content)</slot> + </div> + </transition> +</div> +</template> + +<script setup lang="ts"> +import {ref, computed, watch} from 'vue'; + +// Props + events +const props = defineProps({ + modelValue: {type: Boolean, default: false}, // For using v-model on the component +}); +const emit = defineEmits(['update:modelValue', 'open']); + +// For open status +const open = ref(false); +watch(() => props.modelValue, (newVal) => {open.value = newVal}) +function onClick(){ + open.value = !open.value; + emit('update:modelValue', open.value); + if (open.value){ + emit('open'); + } +} + +// Styles +const styles = computed(() => ({ + overflow: open.value ? 'visible' : 'hidden', +})); +const contentStyles = computed(() => ({ + overflow: 'hidden', + opacity: open.value ? '1' : '0', + transitionProperty: 'max-height, opacity', + transitionDuration: '300ms', + transitionTimingFunction: 'ease-in-out', +})); + +// Open/close transitions +function onEnter(el: HTMLDivElement){ + el.style.maxHeight = el.scrollHeight + 'px'; +} +function onAfterEnter(el: HTMLDivElement){ + el.style.maxHeight = 'none'; + // Allows the content to grow after the transition ends, as the scrollHeight sometimes is too short +} +function onBeforeLeave(el: HTMLDivElement){ + el.style.maxHeight = el.scrollHeight + 'px'; + el.offsetWidth; // Triggers reflow +} +function onLeave(el: HTMLDivElement){ + el.style.maxHeight = '0'; +} +</script> |
