Skip to content

Commit b5325bf

Browse files
committed
feat: update Collapsible components
1 parent 7b77f32 commit b5325bf

File tree

7 files changed

+257
-11
lines changed

7 files changed

+257
-11
lines changed

.vitepress/components/PropsTable.vue

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
CollapsibleRoot,
2525
CollapsibleTrigger,
2626
CollapsibleContent,
27+
CollapsibleIndicator,
2728
} from '#components'
2829
import VPropsTable from './_partials/VPropsTable.vue'
2930
@@ -43,9 +44,18 @@ const inheritProps = computed(() => {
4344

4445
<template>
4546
<div class="not-prose">
46-
<VPropsTable :items="selfProps" />
47-
<CollapsibleRoot v-if="inheritProps.length">
48-
<CollapsibleTrigger>Inherit from Reka UI</CollapsibleTrigger>
47+
<VPropsTable v-if="selfProps.length" :items="selfProps" />
48+
<CollapsibleRoot
49+
v-if="inheritProps.length"
50+
size="1"
51+
class="pt-4"
52+
>
53+
<CollapsibleTrigger class="font-medium">
54+
Inherit from Reka UI
55+
<template #right>
56+
<CollapsibleIndicator />
57+
</template>
58+
</CollapsibleTrigger>
4959
<CollapsibleContent>
5060
<VPropsTable :items="inheritProps" />
5161
</CollapsibleContent>

.vitepress/custom/doc/Sidebar.vue

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
CollapsibleRoot,
88
CollapsibleTrigger,
99
CollapsibleContent,
10-
ChevronIcon,
10+
CollapsibleIndicator,
1111
} from '#components'
1212
import DocSidebarItem from './SidebarItem.vue'
1313
@@ -22,11 +22,14 @@ defineProps<{sidebar: DefaultTheme.SidebarItem[]}>()
2222
<CollapsibleRoot
2323
v-if="item.items?.length"
2424
class="mb-6"
25+
size="1"
2526
default-open
2627
>
27-
<CollapsibleTrigger class="flex items-center justify-between w-full px-4">
28+
<CollapsibleTrigger class="w-full px-4">
2829
<span class="font-semibold">{{ item.text }}</span>
29-
<ChevronIcon />
30+
<template #right>
31+
<CollapsibleIndicator />
32+
</template>
3033
</CollapsibleTrigger>
3134
<CollapsibleContent>
3235
<DocSidebarItem

src/components/collapsible/CollapsibleContent.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
import type { CollapsibleContentProps } from 'reka-ui'
33
import { CollapsibleContent, useForwardProps } from 'reka-ui'
44
5-
const props = defineProps<CollapsibleContentProps>()
6-
const forwardedProps = useForwardProps(props)
7-
85
defineOptions({
96
inheritAttrs: false,
107
})
8+
9+
const props = defineProps<CollapsibleContentProps>()
10+
const forwardedProps = useForwardProps(props)
1111
</script>
1212

1313
<template>
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<script lang="ts">
2+
export interface CollapsibleIndicatorProps {
3+
variant?: 'chevron' | 'plus'
4+
}
5+
</script>
6+
7+
<script setup lang="ts">
8+
withDefaults(defineProps<CollapsibleIndicatorProps>(), {
9+
variant: 'chevron',
10+
})
11+
</script>
12+
13+
<template>
14+
<div class="ui-CollapsibleIndicator">
15+
<svg
16+
v-if="variant == 'chevron'"
17+
class="ui-CollapsibleIndicator-chevron"
18+
xmlns="http://www.w3.org/2000/svg"
19+
width="1em"
20+
height="1em"
21+
viewBox="0 0 24 24"
22+
fill="none"
23+
stroke="currentColor"
24+
stroke-width="2"
25+
stroke-linecap="round"
26+
stroke-linejoin="round"
27+
>
28+
<path d="m9 18 6-6-6-6" />
29+
</svg>
30+
<div v-if="variant == 'plus'" class="ui-CollapsibleIndicator-plus">
31+
<span class="ui-CollapsibleIndicator-plus-1"></span>
32+
<span class="ui-CollapsibleIndicator-plus-2"></span>
33+
</div>
34+
</div>
35+
</template>
36+
37+
<style>
38+
.ui-CollapsibleIndicator {
39+
display: inline-flex;
40+
align-items: center;
41+
--collapsible-indicator-color: var(--gray-10);
42+
}
43+
44+
.ui-CollapsibleIndicator-chevron {
45+
transition: transform 0.2s ease;
46+
font-size: var(--collapsible-indicator-icon-size);
47+
color: var(--collapsible-indicator-color);
48+
}
49+
50+
:where(.ui-CollapsibleRoot[data-state="open"]) .ui-CollapsibleIndicator-chevron {
51+
transform: rotate(90deg);
52+
}
53+
54+
.ui-CollapsibleIndicator-plus {
55+
position: relative;
56+
width: var(--collapsible-indicator-icon-size);
57+
height: var(--collapsible-indicator-icon-size);
58+
cursor: pointer;
59+
display: inline-block;
60+
}
61+
62+
.ui-CollapsibleIndicator-plus-1,
63+
.ui-CollapsibleIndicator-plus-2 {
64+
position: absolute;
65+
background-color: var(--collapsible-indicator-color);
66+
border-radius: 2px;
67+
transition: transform 0.3s, opacity 0.3s;
68+
}
69+
70+
.ui-CollapsibleIndicator-plus-1 {
71+
top: 50%;
72+
left: 0;
73+
width: 100%;
74+
height: var(--collapsible-indicator-line-width);
75+
transform: translateY(-50%) rotate(0deg);
76+
}
77+
78+
.ui-CollapsibleIndicator-plus-2 {
79+
top: 0;
80+
left: 50%;
81+
width: var(--collapsible-indicator-line-width);
82+
height: 100%;
83+
transform: translateX(-50%) rotate(0deg);
84+
}
85+
86+
:where(.ui-CollapsibleRoot[data-state="open"]) .ui-CollapsibleIndicator-plus-1 {
87+
transform: translateY(-50%) rotate(180deg);
88+
}
89+
90+
:where(.ui-CollapsibleRoot[data-state="open"]) .ui-CollapsibleIndicator-plus-2 {
91+
transform: translateX(-50%) rotate(90deg);
92+
opacity: 0;
93+
height: 0;
94+
}
95+
</style>
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<script lang="ts">
2+
import type {
3+
CollapsibleRootProps as RekaCollapsibleRootProps,
4+
CollapsibleRootEmits,
5+
} from 'reka-ui'
6+
import type { ColorType, RadiusType } from '../types'
7+
8+
export interface CollapsibleRootProps extends RekaCollapsibleRootProps {
9+
color?: ColorType
10+
radius?: RadiusType
11+
variant?: 'solid' | 'soft' | 'surface' | 'outline' | 'ghost'
12+
size?: '1' | '2' | '3' | '4'
13+
}
14+
</script>
15+
16+
<script setup lang="ts">
17+
import { CollapsibleRoot } from 'reka-ui'
18+
import { useForwardPropsEmitsWithout, buildPropsClass } from '../util'
19+
20+
const props = withDefaults(defineProps<CollapsibleRootProps>(), {
21+
variant: 'ghost',
22+
size: '2',
23+
})
24+
const emits = defineEmits<CollapsibleRootEmits>()
25+
26+
const forwarded = useForwardPropsEmitsWithout(props, emits, ['color', 'radius', 'variant', 'size'])
27+
const resetClass = buildPropsClass(props, ['variant', 'size'])
28+
</script>
29+
30+
<template>
31+
<CollapsibleRoot
32+
class="ui-CollapsibleRoot"
33+
:class="resetClass"
34+
v-bind="forwarded"
35+
:data-accent-color="color"
36+
:data-radius="radius"
37+
>
38+
<template #default="{ open }">
39+
<slot :open="open"></slot>
40+
</template>
41+
</CollapsibleRoot>
42+
</template>
43+
44+
<style>
45+
.ui-CollapsibleRoot:where(.r-size-1) {
46+
--collapsible-trigger-font-size: var(--font-size-2);
47+
--collapsible-trigger-gap: calc(var(--space-1) / 2);
48+
--collapsible-indicator-icon-size: var(--font-size-2);
49+
--collapsible-indicator-line-width: 1px;
50+
}
51+
52+
.ui-CollapsibleRoot:where(.r-size-2) {
53+
--collapsible-trigger-font-size: var(--font-size-3);
54+
--collapsible-trigger-gap: var(--space-1);
55+
--collapsible-indicator-icon-size: var(--font-size-3);
56+
--collapsible-indicator-line-width: 1px;
57+
}
58+
59+
.ui-CollapsibleRoot:where(.r-size-3) {
60+
--collapsible-trigger-font-size: var(--font-size-5);
61+
--collapsible-trigger-gap: calc(var(--space-2) * 3 / 4);
62+
--collapsible-indicator-icon-size: var(--font-size-5);
63+
--collapsible-indicator-line-width: 2px;
64+
}
65+
66+
.ui-CollapsibleRoot:where(.r-size-4) {
67+
--collapsible-trigger-font-size: var(--font-size-7);
68+
--collapsible-trigger-gap: var(--space-2);
69+
--collapsible-indicator-icon-size: var(--font-size-7);
70+
--collapsible-indicator-line-width: 2px;
71+
}
72+
</style>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<script lang="ts">
2+
import type { CollapsibleTriggerProps } from 'reka-ui'
3+
</script>
4+
5+
<script setup lang="ts">
6+
import { CollapsibleTrigger, useForwardProps } from 'reka-ui'
7+
8+
const props = defineProps<CollapsibleTriggerProps>()
9+
const forwarded = useForwardProps(props)
10+
</script>
11+
12+
<template>
13+
<CollapsibleTrigger
14+
class="ui-CollapsibleTrigger"
15+
v-bind="forwarded"
16+
>
17+
<span
18+
v-if="$slots.left"
19+
class="ui-CollapsibleTriggerSlot"
20+
data-side="left"
21+
>
22+
<slot name="left"></slot>
23+
</span>
24+
<span class="ui-CollapsibleTriggerInner">
25+
<slot></slot>
26+
</span>
27+
<span
28+
v-if="$slots.right"
29+
class="ui-CollapsibleTriggerSlot"
30+
data-side="right"
31+
>
32+
<slot name="right"></slot>
33+
</span>
34+
</CollapsibleTrigger>
35+
</template>
36+
37+
<style>
38+
.ui-CollapsibleTrigger {
39+
display: inline-flex;
40+
align-items: center;
41+
gap: var(--collapsible-trigger-gap);
42+
font-size: var(--collapsible-trigger-font-size);
43+
}
44+
.ui-CollapsibleTriggerInner {
45+
flex-grow: 1;
46+
text-align: initial;
47+
}
48+
.ui-CollapsibleTriggerSlot {
49+
display: inline-flex;
50+
align-items: center;
51+
}
52+
</style>
Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
11
export {
2-
CollapsibleRoot,
3-
CollapsibleTrigger,
2+
type CollapsibleTriggerProps,
3+
type CollapsibleContentProps,
44
} from 'reka-ui'
55

6+
export {
7+
default as CollapsibleRoot,
8+
type CollapsibleRootProps,
9+
} from './CollapsibleRoot.vue'
10+
11+
export {
12+
default as CollapsibleTrigger,
13+
} from './CollapsibleTrigger.vue'
14+
615
export {
716
default as CollapsibleContent,
817
} from './CollapsibleContent.vue'
18+
19+
export {
20+
default as CollapsibleIndicator,
21+
type CollapsibleIndicatorProps,
22+
} from './CollapsibleIndicator.vue'

0 commit comments

Comments
 (0)