diff options
Diffstat (limited to 'src/components/SCollapsible.vue')
| -rw-r--r-- | src/components/SCollapsible.vue | 101 |
1 files changed, 45 insertions, 56 deletions
diff --git a/src/components/SCollapsible.vue b/src/components/SCollapsible.vue index 5b49c8c..39b4283 100644 --- a/src/components/SCollapsible.vue +++ b/src/components/SCollapsible.vue @@ -11,62 +11,51 @@ </div> </template> -<script lang="ts"> -import {defineComponent, PropType} from 'vue'; +<script setup lang="ts"> +import {ref, computed, watch} from 'vue'; -export default defineComponent({ - props: { - modelValue: {type: Boolean, default: false}, // For using v-model on the component - }, - data(){ - return { - open: false, - }; - }, - computed: { - styles(): Record<string,string> { - return { - overflow: this.open ? 'visible' : 'hidden', - }; - }, - contentStyles(): Record<string,string> { - return { - overflow: 'hidden', - opacity: this.open ? '1' : '0', - transitionProperty: 'max-height, opacity', - transitionDuration: '300ms', - transitionTimingFunction: 'ease-in-out', - }; - }, - }, - methods: { - onClick(evt: Event){ - this.open = !this.open; - this.$emit('update:modelValue', this.open); - if (this.open){ - this.$emit('open'); - } - }, - onEnter(el: HTMLDivElement){ - el.style.maxHeight = el.scrollHeight + 'px'; - }, - onAfterEnter(el: HTMLDivElement){ - el.style.maxHeight = 'none'; - // Allows the content to grow after the transition ends, as the scrollHeight sometimes is too short - }, - onBeforeLeave(el: HTMLDivElement){ - el.style.maxHeight = el.scrollHeight + 'px'; - el.offsetWidth; // Triggers reflow - }, - onLeave(el: HTMLDivElement){ - el.style.maxHeight = '0'; - }, - }, - watch: { - modelValue(newVal, oldVal){ - this.open = newVal; - }, - }, - emits: ['update:modelValue', 'open', ], +// 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> |
