Skip to content

Commit c004f5e

Browse files
committed
feat: add surface, soft variants for TabsList
1 parent 78c5855 commit c004f5e

File tree

10 files changed

+238
-26
lines changed

10 files changed

+238
-26
lines changed

.vitepress/components/PropsTable.vue

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ const inheritProps = computed(() => {
4444

4545
<template>
4646
<div class="not-prose">
47-
<VPropsTable v-if="selfProps.length" :items="selfProps" />
48-
<CollapsibleRoot
49-
v-if="inheritProps.length"
50-
size="1"
51-
class="pt-4"
52-
>
47+
<VPropsTable
48+
v-if="selfProps.length"
49+
class="mb-4"
50+
:items="selfProps"
51+
/>
52+
<CollapsibleRoot v-if="inheritProps.length" size="1">
5353
<CollapsibleTrigger class="font-medium">
5454
Props inherited from Reka UI
5555
<template #right>

.vitepress/config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ export default defineConfig({
7777
{ text: 'Select', link: '/components/select' },
7878
],
7979
},
80+
{
81+
text: 'Controls',
82+
items: [
83+
{ text: 'Tabs', link: '/components/tabs' },
84+
],
85+
},
8086
{
8187
text: 'Overlays',
8288
items: [

.vitepress/custom/Doc.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { ColorType } from '#components'
44
55
const STATUS_COLOR_MAP: Record<string, ColorType> = {
66
alpha: 'orange',
7-
beta: 'indigo',
7+
beta: 'bronze',
88
stable: 'green',
99
}
1010
</script>

docs/content/components/checkbox-group.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
title: Checkbox Group
3+
description: Groups multiple checkboxes and emits a list of selected values.
34
status: alpha
45
source: https://github.com/typlog/ui/tree/main/src/components/checkbox
56
reka: https://reka-ui.com/docs/components/checkbox-group

docs/content/components/tabs.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
title: Tabs
3+
description: Set of content sections to be displayed one at a time.
4+
status: stable
5+
source: https://github.com/typlog/ui/tree/main/src/components/tabs
6+
reka: https://reka-ui.com/docs/components/tabs
7+
radix: https://www.radix-ui.com/themes/docs/components/tabs
8+
---
9+
10+
<Example name="tabs/Overview.vue" />
11+
12+
## API Reference
13+
14+
### TabsRoot
15+
16+
<PropsTable name="TabsRoot" />
17+
18+
### TabsList
19+
20+
<PropsTable name="TabsList" />
21+
22+
### TabsTrigger
23+
24+
<PropsTable name="TabsTrigger" />
25+
26+
### TabsContent
27+
28+
<PropsTable name="TabsContent" />
29+
30+
## Examples
31+
32+
### Variant
33+
34+
<Example name="tabs/Variant.vue" />

docs/examples/tabs/Overview.vue

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<script setup lang="ts">
2+
import {
3+
TabsRoot,
4+
TabsList,
5+
TabsTrigger,
6+
TabsContent,
7+
} from '#components'
8+
</script>
9+
10+
<template>
11+
<TabsRoot default-value="account">
12+
<TabsList>
13+
<TabsTrigger value="account">Account</TabsTrigger>
14+
<TabsTrigger value="documents">Documents</TabsTrigger>
15+
<TabsTrigger value="settings">Settings</TabsTrigger>
16+
</TabsList>
17+
18+
<div class="p-4">
19+
<TabsContent value="account">
20+
<p>Make changes to your account.</p>
21+
</TabsContent>
22+
23+
<TabsContent value="documents">
24+
<p>Access and update your documents.</p>
25+
</TabsContent>
26+
27+
<TabsContent value="settings">
28+
<p>Edit your profile or update contact information.</p>
29+
</TabsContent>
30+
</div>
31+
</TabsRoot>
32+
</template>

docs/examples/tabs/Variant.vue

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<script setup lang="ts">
2+
import {
3+
TabsRoot,
4+
TabsList,
5+
TabsTrigger,
6+
TabsContent,
7+
} from '#components'
8+
</script>
9+
10+
<template>
11+
<div class="flex flex-col gap-4">
12+
<TabsRoot default-value="account">
13+
<TabsList variant="surface">
14+
<TabsTrigger value="account">Account</TabsTrigger>
15+
<TabsTrigger value="documents">Documents</TabsTrigger>
16+
<TabsTrigger value="settings">Settings</TabsTrigger>
17+
</TabsList>
18+
19+
<div class="p-4">
20+
<TabsContent value="account">
21+
<p>Make changes to your account.</p>
22+
</TabsContent>
23+
<TabsContent value="documents">
24+
<p>Access and update your documents.</p>
25+
</TabsContent>
26+
<TabsContent value="settings">
27+
<p>Edit your profile or update contact information.</p>
28+
</TabsContent>
29+
</div>
30+
</TabsRoot>
31+
32+
<TabsRoot default-value="account">
33+
<TabsList variant="soft">
34+
<TabsTrigger value="account">Account</TabsTrigger>
35+
<TabsTrigger value="documents">Documents</TabsTrigger>
36+
<TabsTrigger value="settings">Settings</TabsTrigger>
37+
</TabsList>
38+
39+
<div class="p-4">
40+
<TabsContent value="account">
41+
<p>Make changes to your account.</p>
42+
</TabsContent>
43+
<TabsContent value="documents">
44+
<p>Access and update your documents.</p>
45+
</TabsContent>
46+
<TabsContent value="settings">
47+
<p>Edit your profile or update contact information.</p>
48+
</TabsContent>
49+
</div>
50+
</TabsRoot>
51+
52+
<TabsRoot default-value="account">
53+
<TabsList variant="outline">
54+
<TabsTrigger value="account">Account</TabsTrigger>
55+
<TabsTrigger value="documents">Documents</TabsTrigger>
56+
<TabsTrigger value="settings">Settings</TabsTrigger>
57+
</TabsList>
58+
59+
<div class="p-4">
60+
<TabsContent value="account">
61+
<p>Make changes to your account.</p>
62+
</TabsContent>
63+
<TabsContent value="documents">
64+
<p>Access and update your documents.</p>
65+
</TabsContent>
66+
<TabsContent value="settings">
67+
<p>Edit your profile or update contact information.</p>
68+
</TabsContent>
69+
</div>
70+
</TabsRoot>
71+
</div>
72+
</template>

src/components/tabs/TabsList.vue

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,49 +33,96 @@ const resetClass = buildPropsClass(props, ['variant', 'size', 'highContrast'])
3333

3434
<style>
3535
.ui-TabList {
36-
position: relative;
37-
display: flex;
3836
justify-content: flex-start;
37+
position: relative;
3938
overflow-x: auto;
4039
white-space: nowrap;
4140
font-style: normal;
4241
scrollbar-width: none;
42+
}
43+
.ui-TabList::-webkit-scrollbar {
44+
display: none;
45+
}
46+
47+
.ui-TabList:where(.r-variant-outline, .r-variant-soft) {
48+
display: flex;
4349
box-shadow: inset 0 -1px 0 0 var(--gray-a5);
4450
}
51+
52+
.ui-TabList:where(.r-variant-surface) {
53+
position: relative;
54+
display: inline-flex;
55+
align-items: center;
56+
justify-content: center;
57+
vertical-align: top;
58+
flex-shrink: 0;
59+
box-shadow: var(--shadow-2);
60+
border-radius: var(--tab-radius);
61+
}
62+
4563
.ui-TabsIndicator {
4664
position: absolute;
4765
left: 0;
48-
bottom: 0;
49-
height: 2px;
5066
transition-property: width, transform;
51-
transition-duration: 300ms;
67+
transform: translateX(var(--reka-tabs-indicator-position));
5268
width: var(--reka-tabs-indicator-size);
69+
}
70+
71+
.ui-TabList:where(.r-variant-outline) :where(.ui-TabsIndicator) {
72+
bottom: 0;
73+
height: 2px;
5374
background-color: var(--accent-indicator);
54-
transform: translateX(var(--reka-tabs-indicator-position));
75+
transition-duration: 300ms;
5576
}
56-
.ui-TabList::-webkit-scrollbar {
57-
display: none;
77+
78+
.ui-TabList:where(.r-variant-surface) :where(.ui-TabsIndicator) {
79+
top: 0;
80+
height: var(--tab-inner-height);
81+
background-color: var(--accent-a3);
82+
transition-duration: 100ms;
5883
}
84+
85+
.ui-TabList:where(.r-variant-soft) :where(.ui-TabsIndicator) {
86+
top: calc((var(--tab-height) - var(--tab-inner-height)) / 2);
87+
height: var(--tab-inner-height);
88+
background-color: var(--accent-a3);
89+
border-radius: var(--tab-item-radius);
90+
transition-duration: 100ms;
91+
}
92+
5993
.ui-TabList:where(.r-size-1) {
6094
font-size: var(--font-size-1);
6195
line-height: var(--line-height-1);
6296
letter-spacing: var(--letter-spacing-1);
6397
--tab-height: var(--space-6);
6498
--tab-padding-x: var(--space-1);
99+
--tab-radius: max(var(--radius-2), var(--radius-full));
100+
--tab-item-radius: var(--radius-1);
65101
--tab-inner-padding-x: var(--space-1);
66102
--tab-inner-height: var(--space-5);
67-
--tab-inner-border-radius: var(--radius-1);
68103
}
69104
.ui-TabList:where(.r-size-2) {
70105
font-size: var(--font-size-2);
71106
line-height: var(--line-height-2);
72107
letter-spacing: var(--letter-spacing-2);
73108
--tab-height: var(--space-7);
74109
--tab-padding-x: var(--space-2);
110+
--tab-radius: max(var(--radius-3), var(--radius-full));
111+
--tab-item-radius: var(--radius-2);
75112
--tab-inner-padding-x: var(--space-2);
76113
--tab-inner-height: calc(var(--space-6) - var(--space-1));
77-
--tab-inner-border-radius: var(--radius-2);
78114
}
115+
116+
.ui-TabList:where(.r-variant-surface) {
117+
--tab-item-radius: 0;
118+
--tab-inner-height: var(--tab-height);
119+
}
120+
121+
.ui-TabList:where(.r-variant-soft) {
122+
padding-left: var(--tab-padding-x);
123+
padding-right: var(--tab-padding-x);
124+
}
125+
79126
:where(.ui-TabList.r-high-contrast) .ui-TabsIndicator {
80127
background-color: var(--accent-12);
81128
}

src/components/tabs/TabsTrigger.vue

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ const forwarded = useForwardProps(props)
3535
user-select: none;
3636
box-sizing: border-box;
3737
height: var(--tab-height);
38-
padding-left: var(--tab-padding-x);
39-
padding-right: var(--tab-padding-x);
4038
color: var(--gray-a11);
4139
outline: none;
4240
}
@@ -55,7 +53,7 @@ const forwarded = useForwardProps(props)
5553
height: var(--tab-inner-height);
5654
padding-left: var(--tab-inner-padding-x);
5755
padding-right: var(--tab-inner-padding-x);
58-
border-radius: var(--tab-inner-border-radius);
56+
border-radius: var(--tab-item-radius);
5957
}
6058
6159
.ui-TabTriggerInner {
@@ -81,21 +79,43 @@ const forwarded = useForwardProps(props)
8179
}
8280
8381
@media (hover: hover) {
84-
.ui-TabTrigger:where(:hover) {
82+
.ui-TabList:where(.r-variant-outline) :where(.ui-TabTrigger:hover) {
8583
color: var(--gray-12);
8684
}
87-
.ui-TabTrigger:where(:not(:disabled):hover) :where(.ui-TabTriggerInner) {
85+
.ui-TabList:where(.r-variant-surface, .r-variant-soft) :where(.ui-TabTrigger:hover) {
86+
color: var(--accent-a11);
87+
}
88+
.ui-TabList:where(.r-variant-outline) :where(.ui-TabTrigger:not(:disabled):hover) :where(.ui-TabTriggerInner) {
8889
background-color: var(--gray-a3);
8990
}
9091
.ui-TabTrigger:where(:focus-visible:hover) :where(.ui-TabTriggerInner) {
9192
background-color: var(--accent-a3);
9293
}
9394
}
94-
.ui-TabTrigger:where([data-state='active']) {
95-
color: var(--gray-12);
96-
}
95+
9796
.ui-TabTrigger:where(:focus-visible) :where(.ui-TabTriggerInner) {
9897
outline: 2px solid var(--focus-8);
9998
outline-offset: -2px;
10099
}
100+
101+
.ui-TabList:where(.r-variant-outline) :where(.ui-TabTrigger) {
102+
padding-left: var(--tab-padding-x);
103+
padding-right: var(--tab-padding-x);
104+
}
105+
106+
.ui-TabList:where(.r-variant-outline) :where(.ui-TabTrigger[data-state='active']) {
107+
color: var(--gray-12);
108+
}
109+
110+
.ui-TabList:where(.r-variant-soft) :where(.ui-TabTrigger + .ui-TabTrigger) {
111+
margin-left: calc(var(--tab-padding-x) / 2)
112+
}
113+
114+
.ui-TabList:where(.r-variant-surface) :where(.ui-TabTrigger + .ui-TabTrigger) {
115+
box-shadow: inset 1px 0 0 var(--gray-a3);
116+
}
117+
118+
.ui-TabList:where(.r-variant-surface, .r-variant-soft) :where(.ui-TabTrigger[data-state='active']) {
119+
color: var(--accent-a11);
120+
}
101121
</style>

src/components/toggle/ToggleGroupItem.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ const forwarded = useForwardProps(props)
6363
}
6464
}
6565
:where(.ui-ToggleGroupRoot.r-variant-surface, .r-variant-outline) .ui-ToggleGroupItem + .ui-ToggleGroupItem {
66-
box-shadow: -1px 0 0 0 var(--gray-a4);
66+
box-shadow: inset 1px 0 0 0 var(--gray-a4);
6767
}
6868
6969
.ui-ToggleGroupRoot:where(.r-variant-solid, .r-variant-surface, .r-variant-outoine, .r-variant-ghost) :where(.ui-ToggleGroupItem:focus-visible) {

0 commit comments

Comments
 (0)