chore(Collapsible): new component

This commit is contained in:
Benjamin Canac
2024-03-08 12:44:43 +01:00
parent 622d582426
commit 361e47b03c
5 changed files with 92 additions and 1 deletions

View File

@@ -5,7 +5,7 @@ useHead({
}
})
const components = ['button', 'tooltip']
const components = ['button', 'collapsible', 'tooltip']
</script>
<template>

View File

@@ -0,0 +1,11 @@
<template>
<div class="flex gap-1.5">
<UCollapsible>
<UButton label="Open" />
<template #content>
<div class="bg-red-500 h-12" />
</template>
</UCollapsible>
</div>
</template>

View File

@@ -0,0 +1,74 @@
<script lang="ts">
import { tv } from 'tailwind-variants'
import type { CollapsibleRootProps, CollapsibleRootEmits } from 'radix-vue'
import appConfig from '#build/app.config'
import theme from '#build/ui/collapsible'
const collapsible = tv({ extend: tv(theme), ...(appConfig.ui?.collapsible || {}) })
export interface CollapsibleProps extends Omit<CollapsibleRootProps, 'as' | 'asChild'> {
content?: string
class?: any
ui?: Partial<typeof collapsible.slots>
}
export interface CollapsibleEmits extends CollapsibleRootEmits {}
export interface CollapsibleSlots {
default(): any
content(): any
}
</script>
<script setup lang="ts">
import { computed } from 'vue'
import { CollapsibleRoot, CollapsibleTrigger, CollapsibleContent, useForwardPropsEmits } from 'radix-vue'
import { reactivePick } from '@vueuse/core'
defineOptions({ inheritAttrs: false })
const props = defineProps<CollapsibleProps>()
const emits = defineEmits<CollapsibleEmits>()
const slots = defineSlots<CollapsibleSlots>()
const forwardRoot = useForwardPropsEmits(reactivePick(props, 'defaultOpen', 'open', 'disabled'), emits)
// FIXME: Cannot extend multiple times
// const ui = computed(() => tv({ extend: collapsible, slots: props.ui })())
// eslint-disable-next-line vue/no-dupe-keys
const ui = computed(() => collapsible())
</script>
<template>
<CollapsibleRoot v-bind="forwardRoot">
<CollapsibleTrigger as-child>
<slot />
</CollapsibleTrigger>
<CollapsibleContent v-bind="$attrs" :class="ui.content({ class: props.class })">
<slot name="content">
{{ content }}
</slot>
</CollapsibleContent>
</CollapsibleRoot>
</template>
<style>
@keyframes collapsibleSlideDown {
from {
height: 0;
}
to {
height: var(--radix-collapsible-content-height);
}
}
@keyframes collapsibleSlideUp {
from {
height: var(--radix-collapsible-content-height);
}
to {
height: 0;
}
}
</style>

5
src/theme/collapsible.ts Normal file
View File

@@ -0,0 +1,5 @@
export default {
slots: {
content: 'data-[state=open]:animate-[collapsibleSlideDown_200ms_ease-out] data-[state=closed]:animate-[collapsibleSlideUp_200ms_ease-out] overflow-hidden'
}
}

View File

@@ -1,4 +1,5 @@
export { default as button } from './button'
export { default as collapsible } from './collapsible'
export { default as container } from './container'
export { default as icons } from './icons'
export { default as tooltip } from './tooltip'