@youcan/celeste 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ai/component-registry.json +30 -2
- package/ai/component-registry.md +5 -1
- package/ai/icons.md +1 -1
- package/ai/tokens.md +1 -1
- package/dist/celeste.css +189 -86
- package/dist/cjs/chunks/dist2.cjs +6 -0
- package/dist/cjs/chunks/fancy-button.cjs +1 -1
- package/dist/cjs/chunks/scroll-bar.cjs +1 -0
- package/dist/cjs/chunks/segmented-control-item.cjs +1 -1
- package/dist/cjs/chunks/segmented-control.cjs +18 -3
- package/dist/cjs/chunks/tab-menu-item.cjs +6 -2
- package/dist/cjs/chunks/tab-menu-list.cjs +53 -9
- package/dist/cjs/index.cjs +2 -0
- package/dist/cjs/use-tab-observer.cjs +42 -0
- package/dist/components/segmented-control/segmented-control.d.ts +2 -2
- package/dist/components/tab-menu/tab-menu-list.d.ts +14 -5
- package/dist/composables/index.d.ts +1 -0
- package/dist/composables/use-tab-observer.d.ts +14 -0
- package/dist/es/chunks/BubbleSelect.js +1 -1
- package/dist/es/chunks/CollapsibleRoot.js +1 -1
- package/dist/es/chunks/ComboboxInput.js +1 -1
- package/dist/es/chunks/ComboboxRoot.js +1 -1
- package/dist/es/chunks/DialogRoot.js +1 -1
- package/dist/es/chunks/DropdownMenuRoot.js +1 -1
- package/dist/es/chunks/MenuRoot.js +1 -1
- package/dist/es/chunks/MenuSub.js +1 -1
- package/dist/es/chunks/PaginationRoot.js +1 -1
- package/dist/es/chunks/PinInputRoot.js +1 -1
- package/dist/es/chunks/PopoverRoot.js +1 -1
- package/dist/es/chunks/ProgressIndicator.js +1 -1
- package/dist/es/chunks/RadioGroupRoot.js +1 -1
- package/dist/es/chunks/RovingFocusGroup.js +1 -1
- package/dist/es/chunks/SelectItemAlignedPosition.js +1 -1
- package/dist/es/chunks/TabsRoot.js +1 -1
- package/dist/es/chunks/ToggleGroupRoot.js +1 -1
- package/dist/es/chunks/TooltipRoot.js +1 -1
- package/dist/es/chunks/bar-chart.js +1 -1
- package/dist/es/chunks/calendar.js +1 -1
- package/dist/es/chunks/checkbox.js +1 -1
- package/dist/es/chunks/counter-input.js +1 -1
- package/dist/es/chunks/dist2.js +1 -1
- package/dist/es/chunks/dropdown-menu-sub.js +1 -1
- package/dist/es/chunks/fancy-button.js +1 -1
- package/dist/es/chunks/radio-group-item.js +1 -1
- package/dist/es/chunks/range-calendar.js +1 -1
- package/dist/es/chunks/scroll-area.js +1 -1
- package/dist/es/chunks/scroll-bar.js +2 -1
- package/dist/es/chunks/segmented-control-item.js +2 -2
- package/dist/es/chunks/segmented-control.js +20 -4
- package/dist/es/chunks/sidebar-provider.js +1 -1
- package/dist/es/chunks/slider.js +1 -1
- package/dist/es/chunks/switch.js +1 -1
- package/dist/es/chunks/tab-menu-item.js +6 -2
- package/dist/es/chunks/tab-menu-list.js +56 -10
- package/dist/es/index.js +2 -1
- package/dist/es/use-tab-observer.js +41 -0
- package/package.json +3 -3
- package/src/components/button/fancy-button.vue +14 -4
- package/src/components/segmented-control/segmented-control-item.vue +3 -3
- package/src/components/segmented-control/segmented-control.vue +35 -0
- package/src/components/switch/switch.vue +19 -18
- package/src/components/tab-menu/stories/tab-menu.stories.ts +39 -0
- package/src/components/tab-menu/tab-menu-item.vue +27 -28
- package/src/components/tab-menu/tab-menu-list.vue +85 -3
- package/src/composables/index.ts +1 -0
- package/src/composables/use-tab-observer.ts +51 -0
|
@@ -4,20 +4,50 @@ import type { HTMLAttributes } from 'vue';
|
|
|
4
4
|
import clsx from 'clsx';
|
|
5
5
|
import { TabsList } from 'reka-ui';
|
|
6
6
|
import { useDelegatedProps } from '@/composables/use-delegated-props';
|
|
7
|
+
import { useTabObserver } from '@/composables/use-tab-observer';
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
export interface TabMenuListProps extends TabsListProps {
|
|
10
|
+
class?: HTMLAttributes['class'];
|
|
11
|
+
bordered?: boolean;
|
|
12
|
+
scrollable?: boolean;
|
|
13
|
+
fill?: boolean;
|
|
14
|
+
align?: 'start' | 'center';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const props = withDefaults(defineProps<TabMenuListProps>(), {
|
|
18
|
+
bordered: true,
|
|
19
|
+
scrollable: false,
|
|
20
|
+
fill: false,
|
|
21
|
+
align: 'start',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const delegatedProps = useDelegatedProps(props, ['class', 'bordered', 'scrollable', 'fill', 'align']);
|
|
25
|
+
|
|
26
|
+
const { listRef, indicator, ready } = useTabObserver('[data-state="active"]');
|
|
10
27
|
</script>
|
|
11
28
|
|
|
12
29
|
<template>
|
|
13
30
|
<TabsList
|
|
31
|
+
ref="listRef"
|
|
14
32
|
v-bind="delegatedProps"
|
|
33
|
+
:data-bordered="bordered"
|
|
34
|
+
:data-scrollable="scrollable"
|
|
35
|
+
:data-fill="fill"
|
|
36
|
+
:data-align="align"
|
|
15
37
|
:class="clsx(
|
|
16
38
|
'celeste-tab-menu-list',
|
|
17
39
|
props.class,
|
|
18
40
|
)"
|
|
19
41
|
>
|
|
20
42
|
<slot />
|
|
43
|
+
<div
|
|
44
|
+
class="celeste-tab-menu-indicator"
|
|
45
|
+
:data-ready="ready"
|
|
46
|
+
:style="{
|
|
47
|
+
width: `${indicator.width}px`,
|
|
48
|
+
transform: `translate3d(${indicator.left}px, 0, 0)`,
|
|
49
|
+
}"
|
|
50
|
+
/>
|
|
21
51
|
</TabsList>
|
|
22
52
|
</template>
|
|
23
53
|
|
|
@@ -31,14 +61,66 @@ const delegatedProps = useDelegatedProps(props, 'class');
|
|
|
31
61
|
gap: var(--spacing-8);
|
|
32
62
|
|
|
33
63
|
&[data-orientation='horizontal'] {
|
|
64
|
+
position: relative;
|
|
34
65
|
flex-direction: row;
|
|
35
66
|
padding: var(--spacing-0);
|
|
36
|
-
border-block: 1px solid var(--color-stroke-soft-200);
|
|
37
67
|
gap: 24px;
|
|
68
|
+
|
|
69
|
+
&[data-bordered='true'] {
|
|
70
|
+
border-block: 1px solid var(--color-stroke-soft-200);
|
|
71
|
+
}
|
|
38
72
|
}
|
|
39
73
|
|
|
40
74
|
&[data-orientation='vertical'] {
|
|
41
75
|
flex-direction: column;
|
|
42
76
|
}
|
|
77
|
+
|
|
78
|
+
&[data-scrollable='true'] {
|
|
79
|
+
overflow-x: auto;
|
|
80
|
+
scrollbar-width: none;
|
|
81
|
+
|
|
82
|
+
&::-webkit-scrollbar {
|
|
83
|
+
display: none;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
&[data-fill='true'] :deep(.celeste-tab-menu-item) {
|
|
88
|
+
flex: 1 1 0;
|
|
89
|
+
width: auto;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
&[data-align='center'] :deep(.celeste-tab-menu-item) {
|
|
93
|
+
justify-content: center;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
&[data-align='center'] :deep(.celeste-tab-menu-item-label) {
|
|
97
|
+
flex: 0 1 auto;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.celeste-tab-menu-indicator {
|
|
102
|
+
position: absolute;
|
|
103
|
+
bottom: -1px;
|
|
104
|
+
left: 0;
|
|
105
|
+
height: 2px;
|
|
106
|
+
transition-property: transform, width;
|
|
107
|
+
transition-duration: 0s;
|
|
108
|
+
transition-timing-function: cubic-bezier(0.65, 0, 0.35, 1);
|
|
109
|
+
opacity: 0;
|
|
110
|
+
background-color: var(--color-primary-base);
|
|
111
|
+
pointer-events: none;
|
|
112
|
+
|
|
113
|
+
.celeste-tab-menu-list[data-scrollable='true'] > & {
|
|
114
|
+
bottom: 0;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
&[data-ready='true'] {
|
|
118
|
+
transition-duration: var(--animation-normal);
|
|
119
|
+
opacity: 1;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.celeste-tab-menu-list[data-orientation='vertical'] > & {
|
|
123
|
+
display: none;
|
|
124
|
+
}
|
|
43
125
|
}
|
|
44
126
|
</style>
|
package/src/composables/index.ts
CHANGED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { MaybeElement } from '@vueuse/core';
|
|
2
|
+
import type { Ref } from 'vue';
|
|
3
|
+
import { unrefElement, useMutationObserver, useResizeObserver } from '@vueuse/core';
|
|
4
|
+
import { ref, shallowRef } from 'vue';
|
|
5
|
+
|
|
6
|
+
export interface TabIndicator {
|
|
7
|
+
left: number;
|
|
8
|
+
top: number;
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface TabObserver {
|
|
14
|
+
listRef: Ref<MaybeElement>;
|
|
15
|
+
indicator: Ref<TabIndicator>;
|
|
16
|
+
ready: Ref<boolean>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function useTabObserver(activeSelector: string): TabObserver {
|
|
20
|
+
const listRef = shallowRef<MaybeElement>(null);
|
|
21
|
+
const indicator = ref<TabIndicator>({ left: 0, top: 0, width: 0, height: 0 });
|
|
22
|
+
const ready = ref(false);
|
|
23
|
+
|
|
24
|
+
function update(): void {
|
|
25
|
+
const active = unrefElement(listRef)?.querySelector<HTMLElement>(activeSelector);
|
|
26
|
+
if (!active) {
|
|
27
|
+
ready.value = false;
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
indicator.value = {
|
|
32
|
+
left: active.offsetLeft,
|
|
33
|
+
top: active.offsetTop,
|
|
34
|
+
width: active.offsetWidth,
|
|
35
|
+
height: active.offsetHeight,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
if (!ready.value)
|
|
39
|
+
requestAnimationFrame(() => requestAnimationFrame(() => ready.value = true));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
useResizeObserver(listRef, update);
|
|
43
|
+
useMutationObserver(listRef, update, {
|
|
44
|
+
childList: true,
|
|
45
|
+
subtree: true,
|
|
46
|
+
attributes: true,
|
|
47
|
+
attributeFilter: ['data-state'],
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return { listRef, indicator, ready };
|
|
51
|
+
}
|