mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-02-05 06:38:00 +01:00
chore(Collapsible): new component
This commit is contained in:
@@ -5,7 +5,7 @@ useHead({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const components = ['button', 'tooltip']
|
const components = ['button', 'collapsible', 'tooltip']
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
11
playground/pages/collapsible.vue
Normal file
11
playground/pages/collapsible.vue
Normal 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>
|
||||||
74
src/runtime/components/Collapsible.vue
Normal file
74
src/runtime/components/Collapsible.vue
Normal 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
5
src/theme/collapsible.ts
Normal 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'
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
export { default as button } from './button'
|
export { default as button } from './button'
|
||||||
|
export { default as collapsible } from './collapsible'
|
||||||
export { default as container } from './container'
|
export { default as container } from './container'
|
||||||
export { default as icons } from './icons'
|
export { default as icons } from './icons'
|
||||||
export { default as tooltip } from './tooltip'
|
export { default as tooltip } from './tooltip'
|
||||||
Reference in New Issue
Block a user