vueuse / motion

๐Ÿคน Vue Composables putting your components in motion
https://motion.vueuse.org
MIT License
2.3k stars 80 forks source link

[feat-req] Add height preset #37

Open jd-solanki opened 2 years ago

jd-solanki commented 2 years ago

Hi,

I was checking the preset docs page of this package. I guess, adding a height preset will be great for people who want to create a collapse component.

This is useful in cases like: FAQ, QnA, Custom Collapse, etc.

Regards.

Tahul commented 2 years ago

Hello :)

Thanks for the suggestion!

Could you provide examples of usage?

I would love to review a PR on that!

Let me know if anything is needed!

jd-solanki commented 2 years ago

Hi,

Thanks for the response. Height preset will allow creating components like collapse easily.

Generally, when I want to create collapse I use v-show which doesn't trigger any animation. I am curious if vueuse/motion can provide something which we can combine with v-show or we can replace v-show with to create an animated collapse.

The reason I didn't do it myself is I don't know much about animation and more specifically I don't have much experience in vue animation via JS. Also, animating height is a bad idea to achieve 60fps smooth animation so experts might know how to achieve smooth animation for things like collapse.

Example of BSV: https://bootstrap-vue.org/docs/components/collapse

Tahul commented 2 years ago

I am really sorry for the late answer.

I am looking forward to implement something like you mentioned (I understand the will to have a similar approach as v-show but animated).

That will be made possible by <Motion> component in v2 (#81 )

kissu commented 11 months ago

Hey! ๐Ÿ‘‹๐Ÿป So, how would one make a collapse as of today?

With this kind of variant?

{
  initial: {
    opacity: 0,
    height: 0
  },
  enter: {
    opacity: 1,
    height: "auto"
  }
}

Right now, height: auto is not defined. Am I missing something basic? ๐Ÿ˜„

kissu commented 10 months ago

@handhikadj I know that sine other do but I don't want to bring the big guns/have something external. In the end, I found a CSS solution anyway so it's better. ๐Ÿ˜

SelfhostedPro commented 9 months ago

@kissu, could you post what your solution was so that others have an idea in the meantime?

kissu commented 9 months ago

@SelfhostedPro I pretty much used a blend between the 2 techniques described here. Really depends on your use-case but fixing it with CSS-only is probably the best way.

This one may also be quite useful depending on the browsers you need to support.

amiranagram commented 7 months ago

I achieved this with useElementSize from core.

<template>
    <div
        ref="containerRef"
        :style="{ height }"
        :aria-hidden="expanded ? undefined : 'true'"
        :inert="expanded ? undefined : ''"
        class="relative z-50 overflow-hidden bg-neutral-950 pt-2 transition-all duration-300 will-change-[height]"
    >
        ...
    </div>
</template>

<script setup lang="ts">
import { useElementSize } from "@vueuse/core"

const { expanded } = useNavigation()

const containerRef = ref<HTMLElement>()
const content = ref<string>()
const { height: targetHeight } = useElementSize(content, undefined, {
    box: "border-box",
})
const height = computed(() => (expanded.value ? `${targetHeight.value}px` : '0.5rem'))

onMounted(() => {
    content.value = containerRef.value?.children[0]
})
</script>