Skip to content

Commit 844b1b6

Browse files
committed
feat(collapsible): style soft and surface variants
1 parent 0be2a4a commit 844b1b6

File tree

13 files changed

+178
-42
lines changed

13 files changed

+178
-42
lines changed

.vitepress/custom/doc/Sidebar.vue

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
CollapsibleRoot,
88
CollapsibleTrigger,
99
CollapsibleContent,
10-
CollapsibleIndicator,
1110
} from '#components'
1211
import DocSidebarItem from './SidebarItem.vue'
1312
@@ -25,12 +24,7 @@ defineProps<{sidebar: DefaultTheme.SidebarItem[]}>()
2524
size="1"
2625
default-open
2726
>
28-
<CollapsibleTrigger class="w-full px-4">
29-
<span class="font-semibold">{{ item.text }}</span>
30-
<template #right>
31-
<CollapsibleIndicator />
32-
</template>
33-
</CollapsibleTrigger>
27+
<CollapsibleTrigger class="px-4">{{ item.text }}</CollapsibleTrigger>
3428
<CollapsibleContent>
3529
<DocSidebarItem
3630
v-for="subitem in item.items"

.vitepress/meta/CollapsibleRoot.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
{
6868
"name": "variant",
6969
"description": "",
70-
"type": "\"solid\" | \"soft\" | \"surface\" | \"outline\" | \"ghost\"",
70+
"type": "\"soft\" | \"surface\" | \"ghost\"",
7171
"required": false,
7272
"inherit": null
7373
}

.vitepress/meta/CollapsibleTrigger.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@
1414
"type": "boolean",
1515
"required": false,
1616
"inherit": "reka-ui"
17+
},
18+
{
19+
"name": "indicator",
20+
"description": "",
21+
"type": "\"none\" | \"left\" | \"right\"",
22+
"required": false,
23+
"inherit": null
1724
}
1825
],
1926
"events": [],
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
title: Collapsible
3+
description: A component that toggles the visibility of a content panel on user interaction.
4+
status: alpha
5+
source: https://github.com/typlog/ui/tree/main/src/components/collapsible
6+
reka: https://reka-ui.com/docs/components/collapsible
7+
---
8+
9+
<Example name="collapsible/Overview.vue" variant="hide" />
10+
11+
## API Reference
12+
13+
### CollapsibleRoot
14+
15+
<PropsTable name="CollapsibleRoot" />
16+
17+
### CollapsibleTrigger
18+
19+
<PropsTable name="CollapsibleTrigger" />
20+
21+
### CollapsibleContent
22+
23+
<PropsTable name="CollapsibleContent" />
24+
25+
## Examples
26+
27+
### Variant
28+
29+
<Example name="collapsible/Variant.vue" />
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<script setup lang="ts">
2+
import {
3+
CollapsibleRoot,
4+
CollapsibleTrigger,
5+
CollapsibleContent,
6+
} from '#components'
7+
</script>
8+
9+
<template>
10+
<div class="flex flex-col gap-4">
11+
<CollapsibleRoot>
12+
<CollapsibleTrigger>
13+
What is @typlog/ui?
14+
</CollapsibleTrigger>
15+
<CollapsibleContent>
16+
<p><code>@typlog/ui</code> extends <code>reka-ui</code> with pre-styled components and uses Radix Colors for consistent theming.</p>
17+
</CollapsibleContent>
18+
</CollapsibleRoot>
19+
</div>
20+
</template>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<script setup lang="ts">
2+
import {
3+
CollapsibleRoot,
4+
CollapsibleTrigger,
5+
CollapsibleContent,
6+
} from '#components'
7+
</script>
8+
9+
<template>
10+
<div class="flex flex-col gap-4">
11+
<CollapsibleRoot variant="ghost">
12+
<CollapsibleTrigger>
13+
What is @typlog/ui?
14+
</CollapsibleTrigger>
15+
<CollapsibleContent>
16+
<p><code>@typlog/ui</code> extends <code>reka-ui</code> with pre-styled components and uses Radix Colors for consistent theming.</p>
17+
</CollapsibleContent>
18+
</CollapsibleRoot>
19+
20+
<CollapsibleRoot variant="soft">
21+
<CollapsibleTrigger>
22+
What is @typlog/ui?
23+
</CollapsibleTrigger>
24+
<CollapsibleContent>
25+
<p><code>@typlog/ui</code> extends <code>reka-ui</code> with pre-styled components and uses Radix Colors for consistent theming.</p>
26+
</CollapsibleContent>
27+
</CollapsibleRoot>
28+
29+
<CollapsibleRoot variant="surface">
30+
<CollapsibleTrigger>
31+
What is @typlog/ui?
32+
</CollapsibleTrigger>
33+
<CollapsibleContent>
34+
<p><code>@typlog/ui</code> extends <code>reka-ui</code> with pre-styled components and uses Radix Colors for consistent theming.</p>
35+
</CollapsibleContent>
36+
</CollapsibleRoot>
37+
</div>
38+
</template>

src/components/collapsible/CollapsibleContent.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,17 @@ const forwardedProps = useForwardProps(props)
4040
}
4141
.ui-CollapsibleContent {
4242
overflow: hidden;
43+
font-size: var(--collapsible-font-size);
4344
font-weight: var(--font-weight-regular);
45+
padding-block: var(--collapsible-padding-y);
4446
}
4547
.ui-CollapsibleContent:where([data-state="open"]) {
4648
animation: collapsible-down 0.2s ease-out;
4749
}
4850
.ui-CollapsibleContent:where([data-state="closed"]) {
4951
animation: collapsible-up 0.2s ease-out;
5052
}
53+
:where(.ui-CollapsibleRoot:not(.r-variant-ghost)) .ui-CollapsibleContent {
54+
padding-inline: var(--collapsible-padding-x);
55+
}
5156
</style>

src/components/collapsible/CollapsibleIndicator.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@
2424
color: var(--gray-10);
2525
}
2626
27-
:where(.ui-CollapsibleRoot[data-state="open"]) .ui-CollapsibleIndicator {
27+
.ui-CollapsibleIndicator:where([data-side="left"]) {
28+
order: -1;
29+
}
30+
31+
:where([data-state="open"]) .ui-CollapsibleIndicator {
2832
transform: rotate(90deg);
2933
}
3034
</style>

src/components/collapsible/CollapsibleRoot.vue

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type { ColorType, RadiusType } from '../types'
88
export interface CollapsibleRootProps extends RekaCollapsibleRootProps {
99
color?: ColorType
1010
radius?: RadiusType
11-
variant?: 'solid' | 'soft' | 'surface' | 'outline' | 'ghost'
11+
variant?: 'ghost' | 'soft' | 'surface'
1212
size?: '1' | '2' | '3' | '4'
1313
}
1414
</script>
@@ -43,26 +43,46 @@ const resetClass = buildPropsClass(props, ['variant', 'size'])
4343

4444
<style>
4545
.ui-CollapsibleRoot:where(.r-size-1) {
46-
--collapsible-trigger-font-size: var(--font-size-2);
46+
--collapsible-font-size: var(--font-size-2);
4747
--collapsible-trigger-gap: calc(var(--space-1) / 2);
4848
--collapsible-indicator-icon-size: var(--font-size-2);
49+
--collapsible-padding-y: var(--space-1);
50+
--collapsible-padding-x: var(--space-2);
51+
--collapsible-radius: max(var(--radius-1), var(--radius-full))
4952
}
5053
5154
.ui-CollapsibleRoot:where(.r-size-2) {
52-
--collapsible-trigger-font-size: var(--font-size-3);
55+
--collapsible-font-size: var(--font-size-3);
5356
--collapsible-trigger-gap: var(--space-1);
5457
--collapsible-indicator-icon-size: var(--font-size-3);
58+
--collapsible-padding-y: var(--space-2);
59+
--collapsible-padding-x: var(--space-3);
60+
--collapsible-radius: max(var(--radius-2), var(--radius-full))
5561
}
5662
5763
.ui-CollapsibleRoot:where(.r-size-3) {
58-
--collapsible-trigger-font-size: var(--font-size-5);
64+
--collapsible-font-size: var(--font-size-5);
5965
--collapsible-trigger-gap: calc(var(--space-2) * 3 / 4);
6066
--collapsible-indicator-icon-size: var(--font-size-5);
67+
--collapsible-padding-y: var(--space-2);
68+
--collapsible-padding-x: var(--space-4);
69+
--collapsible-radius: max(var(--radius-3), var(--radius-full))
6170
}
6271
6372
.ui-CollapsibleRoot:where(.r-size-4) {
64-
--collapsible-trigger-font-size: var(--font-size-7);
73+
--collapsible-font-size: var(--font-size-7);
6574
--collapsible-trigger-gap: var(--space-2);
6675
--collapsible-indicator-icon-size: var(--font-size-7);
76+
--collapsible-padding-y: var(--space-3);
77+
--collapsible-padding-x: var(--space-5);
78+
--collapsible-radius: max(var(--radius-4), var(--radius-full))
79+
}
80+
81+
.ui-CollapsibleRoot:where(.r-variant-surface) {
82+
box-shadow: inset 0 0 0 1px var(--gray-a4);
83+
border-radius: var(--collapsible-radius);
84+
}
85+
.ui-CollapsibleRoot:where(.r-variant-surface):where([data-state="open"]) {
86+
box-shadow: inset 0 0 0 1px var(--gray-a5);
6787
}
6888
</style>
Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,72 @@
11
<script lang="ts">
2-
import type { CollapsibleTriggerProps } from 'reka-ui'
2+
import type { CollapsibleTriggerProps as RekaCollapsibleTriggerProps } from 'reka-ui'
3+
4+
export interface CollapsibleTriggerProps extends RekaCollapsibleTriggerProps {
5+
indicator?: 'none' | 'left' | 'right'
6+
}
37
</script>
48

59
<script setup lang="ts">
6-
import { CollapsibleTrigger, useForwardProps } from 'reka-ui'
10+
import { CollapsibleTrigger } from 'reka-ui'
11+
import CollapsibleIndicator from './CollapsibleIndicator.vue'
12+
import { useForwardPropsWithout } from '../util'
713
8-
const props = defineProps<CollapsibleTriggerProps>()
9-
const forwarded = useForwardProps(props)
14+
const props = withDefaults(defineProps<CollapsibleTriggerProps>(), {
15+
indicator: 'right',
16+
})
17+
const forwarded = useForwardPropsWithout(props, ['indicator'])
1018
</script>
1119

1220
<template>
1321
<CollapsibleTrigger
1422
class="ui-CollapsibleTrigger"
1523
v-bind="forwarded"
1624
>
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+
<span class="ui-CollapsibleTriggerText">
2526
<slot></slot>
2627
</span>
27-
<span
28-
v-if="$slots.right"
29-
class="ui-CollapsibleTriggerSlot"
30-
data-side="right"
31-
>
32-
<slot name="right"></slot>
33-
</span>
28+
<CollapsibleIndicator
29+
v-if="indicator !== 'none'"
30+
:data-side="indicator"
31+
/>
3432
</CollapsibleTrigger>
3533
</template>
3634

3735
<style>
3836
.ui-CollapsibleTrigger {
3937
display: inline-flex;
4038
align-items: center;
39+
justify-content: space-between;
40+
text-align: initial;
41+
width: 100%;
4142
gap: var(--collapsible-trigger-gap);
42-
font-size: var(--collapsible-trigger-font-size);
43+
font-size: var(--collapsible-font-size);
44+
font-weight: var(--font-weight-medium);
4345
}
44-
.ui-CollapsibleTriggerInner {
46+
.ui-CollapsibleTriggerText {
4547
flex-grow: 1;
4648
text-align: initial;
4749
}
48-
.ui-CollapsibleTriggerSlot {
49-
display: inline-flex;
50-
align-items: center;
50+
:where(.ui-CollapsibleRoot:not(.r-variant-ghost)) .ui-CollapsibleTrigger {
51+
padding-block: var(--collapsible-padding-y);
52+
padding-inline: var(--collapsible-padding-x);
53+
}
54+
55+
:where(.ui-CollapsibleRoot.r-variant-soft) .ui-CollapsibleTrigger {
56+
background: var(--accent-a2);
57+
border-radius: var(--collapsible-radius);
58+
}
59+
:where(.ui-CollapsibleRoot.r-variant-surface) .ui-CollapsibleTrigger {
60+
border-top-left-radius: var(--collapsible-radius);
61+
border-top-right-radius: var(--collapsible-radius);
62+
background: var(--accent-a2);
63+
}
64+
:where(.ui-CollapsibleRoot.r-variant-soft) .ui-CollapsibleTrigger:where(:hover) {
65+
background: var(--accent-a3);
66+
}
67+
:where(.ui-CollapsibleRoot.r-variant-surface) .ui-CollapsibleTrigger:where([data-state="open"]),
68+
:where(.ui-CollapsibleRoot.r-variant-soft) .ui-CollapsibleTrigger:where([data-state="open"]) {
69+
background: var(--accent-a3);
70+
color: var(--accent-a11);
5171
}
5272
</style>

0 commit comments

Comments
 (0)