@youcan/celeste 0.11.0 → 0.13.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 +311 -218
- package/dist/cjs/chunks/ConfigProvider.cjs +58 -1
- package/dist/cjs/chunks/calendar.cjs +73 -67
- package/dist/cjs/chunks/combobox-root.cjs +12 -5
- package/dist/cjs/chunks/digit-input.cjs +13 -7
- package/dist/cjs/chunks/dist2.cjs +6 -0
- package/dist/cjs/chunks/dropdown-menu.cjs +10 -4
- package/dist/cjs/chunks/fancy-button.cjs +1 -1
- package/dist/cjs/chunks/radio-group.cjs +9 -3
- package/dist/cjs/chunks/range-calendar.cjs +73 -67
- package/dist/cjs/chunks/scroll-area.cjs +18 -12
- package/dist/cjs/chunks/scroll-bar.cjs +2 -0
- package/dist/cjs/chunks/segmented-control-item.cjs +1 -1
- package/dist/cjs/chunks/segmented-control.cjs +25 -4
- package/dist/cjs/chunks/select.cjs +9 -3
- package/dist/cjs/chunks/slider.cjs +16 -10
- package/dist/cjs/chunks/tab-menu-item.cjs +6 -2
- package/dist/cjs/chunks/tab-menu-list.cjs +53 -9
- package/dist/cjs/chunks/tab-menu.cjs +12 -5
- package/dist/cjs/chunks/text-input.cjs +1 -1
- package/dist/cjs/command-root.cjs +9 -3
- package/dist/cjs/index.cjs +4 -0
- package/dist/cjs/use-direction.cjs +31 -0
- package/dist/cjs/use-tab-observer.cjs +42 -0
- package/dist/components/combobox/combobox-root.d.ts +2 -2
- package/dist/components/dropdown-menu/dropdown-menu.d.ts +2 -2
- package/dist/components/radio-group/radio-group.d.ts +2 -2
- package/dist/components/scroll-area/scroll-area.d.ts +2 -2
- package/dist/components/segmented-control/segmented-control.d.ts +2 -2
- package/dist/components/select/select.d.ts +2 -2
- package/dist/components/tab-menu/tab-menu-list.d.ts +14 -5
- package/dist/components/tab-menu/tab-menu.d.ts +2 -2
- package/dist/composables/index.d.ts +2 -0
- package/dist/composables/use-direction.d.ts +3 -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/ConfigProvider.js +53 -2
- package/dist/es/chunks/DialogRoot.js +1 -1
- package/dist/es/chunks/DropdownMenuRoot.js +1 -1
- package/dist/es/chunks/FocusScope.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/Teleport.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 +74 -68
- package/dist/es/chunks/checkbox.js +1 -1
- package/dist/es/chunks/combobox-root.js +13 -6
- package/dist/es/chunks/counter-input.js +1 -1
- package/dist/es/chunks/digit-input.js +14 -8
- package/dist/es/chunks/dist2.js +1 -1
- package/dist/es/chunks/dropdown-menu-sub.js +1 -1
- package/dist/es/chunks/dropdown-menu.js +11 -5
- package/dist/es/chunks/fancy-button.js +1 -1
- package/dist/es/chunks/radio-group-item.js +1 -1
- package/dist/es/chunks/radio-group.js +10 -4
- package/dist/es/chunks/range-calendar.js +74 -68
- package/dist/es/chunks/scroll-area.js +19 -13
- package/dist/es/chunks/scroll-bar.js +3 -1
- package/dist/es/chunks/segmented-control-item.js +2 -2
- package/dist/es/chunks/segmented-control.js +27 -5
- package/dist/es/chunks/select.js +10 -4
- package/dist/es/chunks/sidebar-provider.js +1 -1
- package/dist/es/chunks/slider.js +17 -11
- 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/chunks/tab-menu.js +13 -6
- package/dist/es/chunks/text-input.js +1 -1
- package/dist/es/chunks/useDirection.js +1 -1
- package/dist/es/chunks/useId.js +1 -1
- package/dist/es/chunks/useLocale.js +1 -1
- package/dist/es/chunks/useNonce.js +1 -1
- package/dist/es/command-root.js +10 -4
- package/dist/es/index.js +3 -1
- package/dist/es/use-direction.js +30 -0
- 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/calendar/calendar.vue +66 -60
- package/src/components/combobox/combobox-root.vue +9 -4
- package/src/components/command/command-root.vue +13 -8
- package/src/components/digit-input/digit-input.vue +13 -8
- package/src/components/dropdown-menu/dropdown-menu.vue +12 -7
- package/src/components/radio-group/radio-group.vue +12 -7
- package/src/components/range-calendar/range-calendar.vue +67 -61
- package/src/components/scroll-area/scroll-area.vue +17 -18
- package/src/components/segmented-control/segmented-control-item.vue +3 -3
- package/src/components/segmented-control/segmented-control.vue +48 -8
- package/src/components/select/select.vue +12 -7
- package/src/components/slider/slider.vue +19 -14
- 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/components/tab-menu/tab-menu.vue +12 -4
- package/src/components/text-input/text-input.vue +11 -29
- package/src/composables/index.ts +2 -0
- package/src/composables/use-direction.ts +40 -0
- package/src/composables/use-tab-observer.ts +50 -0
|
@@ -4,6 +4,7 @@ import type { HTMLAttributes } from 'vue';
|
|
|
4
4
|
import { DateFormatter, getLocalTimeZone, isEqualDay } from '@internationalized/date';
|
|
5
5
|
import clsx from 'clsx';
|
|
6
6
|
import {
|
|
7
|
+
ConfigProvider,
|
|
7
8
|
RangeCalendarCell,
|
|
8
9
|
RangeCalendarCellTrigger,
|
|
9
10
|
RangeCalendarGrid,
|
|
@@ -18,6 +19,7 @@ import {
|
|
|
18
19
|
} from 'reka-ui';
|
|
19
20
|
import { computed } from 'vue';
|
|
20
21
|
import { useDelegatedProps } from '@/composables/use-delegated-props';
|
|
22
|
+
import { useDirection } from '@/composables/use-direction';
|
|
21
23
|
|
|
22
24
|
export interface RangeCalendarProps extends RangeCalendarRootProps {
|
|
23
25
|
class?: HTMLAttributes['class'];
|
|
@@ -36,6 +38,8 @@ const emits = defineEmits<RangeCalendarRootEmits>();
|
|
|
36
38
|
const delegatedProps = useDelegatedProps(props, ['class', 'markedDates']);
|
|
37
39
|
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
38
40
|
|
|
41
|
+
const direction = useDirection();
|
|
42
|
+
|
|
39
43
|
const monthFormatter = computed(
|
|
40
44
|
() => new DateFormatter(props.locale ?? 'en-US', { month: 'long', year: 'numeric' }),
|
|
41
45
|
);
|
|
@@ -54,70 +58,72 @@ function weekdayLabel(day: string): string {
|
|
|
54
58
|
</script>
|
|
55
59
|
|
|
56
60
|
<template>
|
|
57
|
-
<
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
<div
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
<
|
|
70
|
-
<
|
|
71
|
-
<
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
<
|
|
77
|
-
<
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
<
|
|
84
|
-
<
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
<
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
<RangeCalendarCell
|
|
101
|
-
v-for="weekDate in weekDates"
|
|
102
|
-
:key="weekDate.toString()"
|
|
103
|
-
:date="weekDate"
|
|
104
|
-
class="celeste-range-calendar-cell"
|
|
61
|
+
<ConfigProvider :dir="props.dir ?? direction">
|
|
62
|
+
<RangeCalendarRoot
|
|
63
|
+
v-slot="{ weekDays, grid }"
|
|
64
|
+
v-bind="forwarded"
|
|
65
|
+
:class="clsx('celeste-range-calendar', props.class)"
|
|
66
|
+
>
|
|
67
|
+
<div class="celeste-range-calendar-months">
|
|
68
|
+
<div
|
|
69
|
+
v-for="month in grid"
|
|
70
|
+
:key="month.value.toString()"
|
|
71
|
+
class="celeste-range-calendar-month"
|
|
72
|
+
>
|
|
73
|
+
<div class="celeste-range-calendar-header">
|
|
74
|
+
<RangeCalendarPrev as-child>
|
|
75
|
+
<button type="button" class="celeste-range-calendar-nav">
|
|
76
|
+
<i class="i-celeste-arrow-left-s-line" />
|
|
77
|
+
</button>
|
|
78
|
+
</RangeCalendarPrev>
|
|
79
|
+
<span class="celeste-range-calendar-heading">{{ formatMonth(month.value) }}</span>
|
|
80
|
+
<RangeCalendarNext as-child>
|
|
81
|
+
<button type="button" class="celeste-range-calendar-nav">
|
|
82
|
+
<i class="i-celeste-arrow-right-s-line" />
|
|
83
|
+
</button>
|
|
84
|
+
</RangeCalendarNext>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<RangeCalendarGrid class="celeste-range-calendar-grid">
|
|
88
|
+
<RangeCalendarGridHead>
|
|
89
|
+
<RangeCalendarGridRow class="celeste-range-calendar-week">
|
|
90
|
+
<RangeCalendarHeadCell
|
|
91
|
+
v-for="day in weekDays"
|
|
92
|
+
:key="day"
|
|
93
|
+
class="celeste-range-calendar-weekday"
|
|
94
|
+
>
|
|
95
|
+
{{ weekdayLabel(day) }}
|
|
96
|
+
</RangeCalendarHeadCell>
|
|
97
|
+
</RangeCalendarGridRow>
|
|
98
|
+
</RangeCalendarGridHead>
|
|
99
|
+
<RangeCalendarGridBody class="celeste-range-calendar-body">
|
|
100
|
+
<RangeCalendarGridRow
|
|
101
|
+
v-for="(weekDates, index) in month.rows"
|
|
102
|
+
:key="`week-${index}`"
|
|
103
|
+
class="celeste-range-calendar-week"
|
|
105
104
|
>
|
|
106
|
-
<
|
|
107
|
-
|
|
108
|
-
:
|
|
109
|
-
|
|
110
|
-
|
|
105
|
+
<RangeCalendarCell
|
|
106
|
+
v-for="weekDate in weekDates"
|
|
107
|
+
:key="weekDate.toString()"
|
|
108
|
+
:date="weekDate"
|
|
109
|
+
class="celeste-range-calendar-cell"
|
|
111
110
|
>
|
|
112
|
-
<
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
111
|
+
<RangeCalendarCellTrigger
|
|
112
|
+
:day="weekDate"
|
|
113
|
+
:month="month.value"
|
|
114
|
+
class="celeste-range-calendar-day"
|
|
115
|
+
:data-marked="isMarked(weekDate) ? '' : undefined"
|
|
116
|
+
>
|
|
117
|
+
<span class="celeste-range-calendar-day-number">{{ weekDate.day }}</span>
|
|
118
|
+
</RangeCalendarCellTrigger>
|
|
119
|
+
</RangeCalendarCell>
|
|
120
|
+
</RangeCalendarGridRow>
|
|
121
|
+
</RangeCalendarGridBody>
|
|
122
|
+
</RangeCalendarGrid>
|
|
123
|
+
</div>
|
|
118
124
|
</div>
|
|
119
|
-
</
|
|
120
|
-
</
|
|
125
|
+
</RangeCalendarRoot>
|
|
126
|
+
</ConfigProvider>
|
|
121
127
|
</template>
|
|
122
128
|
|
|
123
129
|
<style scoped lang="scss">
|
|
@@ -2,32 +2,31 @@
|
|
|
2
2
|
import type { ScrollAreaRootProps } from 'reka-ui';
|
|
3
3
|
import type { HTMLAttributes } from 'vue';
|
|
4
4
|
import clsx from 'clsx';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
ScrollAreaRoot,
|
|
8
|
-
|
|
9
|
-
ScrollAreaViewport,
|
|
10
|
-
} from 'reka-ui';
|
|
11
|
-
import { useDelegatedProps } from '@/composables';
|
|
5
|
+
import { ConfigProvider, ScrollAreaCorner, ScrollAreaRoot, ScrollAreaViewport } from 'reka-ui';
|
|
6
|
+
import { useDelegatedProps, useDirection } from '@/composables';
|
|
12
7
|
import ScrollBar from './scroll-bar.vue';
|
|
13
8
|
|
|
14
9
|
const props = defineProps<ScrollAreaRootProps & { class?: HTMLAttributes['class'] }>();
|
|
15
10
|
|
|
16
11
|
const delegatedProps = useDelegatedProps(props, 'class');
|
|
12
|
+
|
|
13
|
+
const direction = useDirection();
|
|
17
14
|
</script>
|
|
18
15
|
|
|
19
16
|
<template>
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
17
|
+
<ConfigProvider :dir="props.dir ?? direction">
|
|
18
|
+
<ScrollAreaRoot
|
|
19
|
+
v-bind="delegatedProps"
|
|
20
|
+
:class="clsx('celeste-scroll-area', props.class)"
|
|
21
|
+
>
|
|
22
|
+
<ScrollAreaViewport class="celeste-scroll-area-viewport">
|
|
23
|
+
<slot />
|
|
24
|
+
</ScrollAreaViewport>
|
|
25
|
+
<ScrollBar />
|
|
26
|
+
<ScrollBar orientation="horizontal" />
|
|
27
|
+
<ScrollAreaCorner />
|
|
28
|
+
</ScrollAreaRoot>
|
|
29
|
+
</ConfigProvider>
|
|
31
30
|
</template>
|
|
32
31
|
|
|
33
32
|
<style scoped lang="scss">
|
|
@@ -30,12 +30,14 @@ function onKeydown(e: KeyboardEvent) {
|
|
|
30
30
|
<style scoped>
|
|
31
31
|
.celeste-segmented-control-item {
|
|
32
32
|
display: flex;
|
|
33
|
+
position: relative;
|
|
34
|
+
z-index: 1;
|
|
33
35
|
align-items: center;
|
|
34
36
|
gap: var(--spacing-6);
|
|
35
37
|
justify-content: center;
|
|
36
38
|
width: 100%;
|
|
37
39
|
padding: var(--spacing-4);
|
|
38
|
-
transition:
|
|
40
|
+
transition: color var(--animation-normal) ease-out;
|
|
39
41
|
border: none;
|
|
40
42
|
border-radius: var(--radius-6);
|
|
41
43
|
background-color: transparent;
|
|
@@ -44,8 +46,6 @@ function onKeydown(e: KeyboardEvent) {
|
|
|
44
46
|
cursor: pointer;
|
|
45
47
|
|
|
46
48
|
&[data-state='on'] {
|
|
47
|
-
background-color: var(--color-bg-white-0);
|
|
48
|
-
box-shadow: var(--shadow-toggle-switch);
|
|
49
49
|
color: var(--color-text-strong-950);
|
|
50
50
|
pointer-events: none;
|
|
51
51
|
}
|
|
@@ -2,30 +2,50 @@
|
|
|
2
2
|
import type { ToggleGroupRootEmits, ToggleGroupRootProps } from 'reka-ui';
|
|
3
3
|
import type { HTMLAttributes } from 'vue';
|
|
4
4
|
import clsx from 'clsx';
|
|
5
|
-
import { ToggleGroupRoot as SegmentedControlRoot, useForwardPropsEmits } from 'reka-ui';
|
|
5
|
+
import { ConfigProvider, ToggleGroupRoot as SegmentedControlRoot, useForwardPropsEmits } from 'reka-ui';
|
|
6
6
|
import { useDelegatedProps } from '@/composables/use-delegated-props';
|
|
7
|
+
import { useDirection } from '@/composables/use-direction';
|
|
8
|
+
import { useTabObserver } from '@/composables/use-tab-observer';
|
|
7
9
|
|
|
8
10
|
const props = defineProps<Omit<ToggleGroupRootProps, 'type'> & { class?: HTMLAttributes['class'] }>();
|
|
9
11
|
const emits = defineEmits<ToggleGroupRootEmits>();
|
|
10
12
|
|
|
11
13
|
const delegatedProps = useDelegatedProps(props, 'class');
|
|
12
14
|
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
15
|
+
|
|
16
|
+
const direction = useDirection();
|
|
17
|
+
|
|
18
|
+
const { listRef, indicator, ready } = useTabObserver('[data-state="on"]');
|
|
13
19
|
</script>
|
|
14
20
|
|
|
15
21
|
<template>
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
<ConfigProvider :dir="props.dir ?? direction">
|
|
23
|
+
<SegmentedControlRoot
|
|
24
|
+
ref="listRef"
|
|
25
|
+
:class="clsx('celeste-segmented-control', props.class)"
|
|
26
|
+
v-bind="forwarded"
|
|
27
|
+
type="single"
|
|
28
|
+
>
|
|
29
|
+
<slot />
|
|
30
|
+
<div
|
|
31
|
+
:hidden="!ready"
|
|
32
|
+
class="celeste-segmented-control-indicator"
|
|
33
|
+
:style="{
|
|
34
|
+
width: `${indicator.width}px`,
|
|
35
|
+
height: `${indicator.height}px`,
|
|
36
|
+
transform: `translate3d(${indicator.left}px, ${indicator.top}px, 0)`,
|
|
37
|
+
}"
|
|
38
|
+
/>
|
|
39
|
+
</SegmentedControlRoot>
|
|
40
|
+
</ConfigProvider>
|
|
23
41
|
</template>
|
|
24
42
|
|
|
25
43
|
<style scoped>
|
|
26
44
|
.celeste-segmented-control {
|
|
27
45
|
display: flex;
|
|
46
|
+
position: relative;
|
|
28
47
|
gap: var(--spacing-4);
|
|
48
|
+
isolation: isolate;
|
|
29
49
|
align-items: center;
|
|
30
50
|
width: 100%;
|
|
31
51
|
padding: var(--spacing-4);
|
|
@@ -36,4 +56,24 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
|
36
56
|
flex-direction: column;
|
|
37
57
|
}
|
|
38
58
|
}
|
|
59
|
+
|
|
60
|
+
.celeste-segmented-control-indicator {
|
|
61
|
+
position: absolute;
|
|
62
|
+
z-index: -1;
|
|
63
|
+
top: 0;
|
|
64
|
+
left: 0;
|
|
65
|
+
transition-property: transform, width, height;
|
|
66
|
+
transition-duration: var(--animation-normal);
|
|
67
|
+
transition-timing-function: cubic-bezier(0.65, 0, 0.35, 1);
|
|
68
|
+
border-radius: var(--radius-6);
|
|
69
|
+
background-color: var(--color-bg-white-0);
|
|
70
|
+
box-shadow: var(--shadow-toggle-switch);
|
|
71
|
+
pointer-events: none;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@media (prefers-reduced-motion: reduce) {
|
|
75
|
+
.celeste-segmented-control-indicator {
|
|
76
|
+
transition-duration: 0s;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
39
79
|
</style>
|
|
@@ -2,21 +2,26 @@
|
|
|
2
2
|
import type { SelectRootEmits, SelectRootProps } from 'reka-ui';
|
|
3
3
|
import type { HTMLAttributes } from 'vue';
|
|
4
4
|
import clsx from 'clsx';
|
|
5
|
-
import { SelectRoot, useForwardPropsEmits } from 'reka-ui';
|
|
5
|
+
import { ConfigProvider, SelectRoot, useForwardPropsEmits } from 'reka-ui';
|
|
6
6
|
import { useDelegatedProps } from '@/composables/use-delegated-props';
|
|
7
|
+
import { useDirection } from '@/composables/use-direction';
|
|
7
8
|
|
|
8
9
|
const props = defineProps<SelectRootProps & { class?: HTMLAttributes['class'] }>();
|
|
9
10
|
const emits = defineEmits<SelectRootEmits>();
|
|
10
11
|
|
|
11
12
|
const delegatedProps = useDelegatedProps(props, 'class');
|
|
12
13
|
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
14
|
+
|
|
15
|
+
const direction = useDirection();
|
|
13
16
|
</script>
|
|
14
17
|
|
|
15
18
|
<template>
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
<ConfigProvider :dir="props.dir ?? direction">
|
|
20
|
+
<SelectRoot
|
|
21
|
+
v-bind="forwarded"
|
|
22
|
+
:class="clsx('celeste-select', props.class)"
|
|
23
|
+
>
|
|
24
|
+
<slot />
|
|
25
|
+
</SelectRoot>
|
|
26
|
+
</ConfigProvider>
|
|
22
27
|
</template>
|
|
@@ -2,31 +2,36 @@
|
|
|
2
2
|
import type { SliderRootEmits, SliderRootProps } from 'reka-ui';
|
|
3
3
|
import type { HTMLAttributes } from 'vue';
|
|
4
4
|
import clsx from 'clsx';
|
|
5
|
-
import { SliderRange, SliderRoot, SliderThumb, SliderTrack, useForwardPropsEmits } from 'reka-ui';
|
|
5
|
+
import { ConfigProvider, SliderRange, SliderRoot, SliderThumb, SliderTrack, useForwardPropsEmits } from 'reka-ui';
|
|
6
6
|
import { useDelegatedProps } from '@/composables/use-delegated-props';
|
|
7
|
+
import { useDirection } from '@/composables/use-direction';
|
|
7
8
|
|
|
8
9
|
const props = defineProps<Omit<SliderRootProps, 'orientation'> & { class?: HTMLAttributes['class'] }>();
|
|
9
10
|
const emits = defineEmits<SliderRootEmits>();
|
|
10
11
|
|
|
11
12
|
const delegatedProps = useDelegatedProps(props, 'class');
|
|
12
13
|
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
14
|
+
|
|
15
|
+
const direction = useDirection();
|
|
13
16
|
</script>
|
|
14
17
|
|
|
15
18
|
<template>
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
<
|
|
22
|
-
|
|
19
|
+
<ConfigProvider :dir="props.dir ?? direction">
|
|
20
|
+
<SliderRoot
|
|
21
|
+
v-bind="forwarded"
|
|
22
|
+
:class="clsx('celeste-slider', props.class)"
|
|
23
|
+
>
|
|
24
|
+
<SliderTrack class="celeste-slider-track">
|
|
25
|
+
<SliderRange class="celeste-slider-range" />
|
|
26
|
+
</SliderTrack>
|
|
23
27
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
<SliderThumb
|
|
29
|
+
v-for="(_, key) in modelValue"
|
|
30
|
+
:key="key"
|
|
31
|
+
class="celeste-slider-thumb"
|
|
32
|
+
/>
|
|
33
|
+
</SliderRoot>
|
|
34
|
+
</ConfigProvider>
|
|
30
35
|
</template>
|
|
31
36
|
|
|
32
37
|
<style lang="scss">
|
|
@@ -25,39 +25,39 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
|
25
25
|
.celeste-switch {
|
|
26
26
|
--width: 26px;
|
|
27
27
|
--height: 16px;
|
|
28
|
+
--thumb-size: 12px;
|
|
29
|
+
--thumb-inset: 1px;
|
|
30
|
+
--travel: calc(var(--width) - var(--thumb-size) - var(--thumb-inset) * 2 - 2px);
|
|
28
31
|
--bg-color: var(--color-bg-soft-200);
|
|
29
|
-
--animation-function: cubic-bezier(0.18, 0.89, 0.43, 1.19);
|
|
30
32
|
|
|
31
33
|
position: relative;
|
|
34
|
+
box-sizing: border-box;
|
|
32
35
|
width: var(--width);
|
|
33
36
|
height: var(--height);
|
|
34
|
-
transition: background var(--animation-fast) ease-out;
|
|
37
|
+
transition: background-color var(--animation-fast) ease-out;
|
|
35
38
|
border: 1px solid transparent;
|
|
36
39
|
border-radius: var(--radius-full);
|
|
37
40
|
background-color: var(--bg-color);
|
|
38
41
|
cursor: pointer;
|
|
39
42
|
|
|
40
43
|
.celeste-switch-thumb {
|
|
41
|
-
--thumb-size: 12px;
|
|
42
44
|
--thumb-hole: 4px;
|
|
45
|
+
--direction: 1;
|
|
43
46
|
|
|
44
47
|
position: absolute;
|
|
45
48
|
box-sizing: border-box;
|
|
46
49
|
width: var(--thumb-size);
|
|
47
50
|
height: var(--thumb-size);
|
|
48
|
-
transform: translateY(-50%);
|
|
49
|
-
transition
|
|
50
|
-
transition-duration: var(--animation-fast);
|
|
51
|
-
transition-timing-function: var(--animation-function), ease-out, ease-out;
|
|
51
|
+
transform: translateY(-50%) scale(var(--thumb-scale, 1));
|
|
52
|
+
transition: transform var(--animation-fast) ease-out;
|
|
52
53
|
border-radius: var(--radius-full);
|
|
53
54
|
background-color: var(--color-static-white);
|
|
54
55
|
box-shadow: var(--shadow-toggle-switch);
|
|
55
56
|
inset-block-start: 50%;
|
|
56
|
-
inset-inline-start:
|
|
57
|
-
will-change: transform;
|
|
57
|
+
inset-inline-start: var(--thumb-inset);
|
|
58
58
|
|
|
59
59
|
&[data-state='checked'] {
|
|
60
|
-
|
|
60
|
+
transform: translateY(-50%) translateX(calc(var(--travel) * var(--direction))) scale(var(--thumb-scale, 1));
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
&::before {
|
|
@@ -66,11 +66,15 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
|
66
66
|
width: var(--thumb-hole);
|
|
67
67
|
height: var(--thumb-hole);
|
|
68
68
|
margin: auto;
|
|
69
|
-
transition: background var(--animation-fast) ease-out;
|
|
69
|
+
transition: background-color var(--animation-fast) ease-out;
|
|
70
70
|
border-radius: var(--radius-full);
|
|
71
71
|
background-color: var(--bg-color);
|
|
72
72
|
inset: var(--spacing-0);
|
|
73
73
|
}
|
|
74
|
+
|
|
75
|
+
:dir(rtl) & {
|
|
76
|
+
--direction: -1;
|
|
77
|
+
}
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
&[aria-checked='true'] {
|
|
@@ -79,25 +83,22 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
|
79
83
|
|
|
80
84
|
&:disabled {
|
|
81
85
|
--bg-color: var(--color-bg-white-0);
|
|
86
|
+
--thumb-inset: var(--spacing-2);
|
|
87
|
+
--travel: calc(var(--width) - var(--thumb-size) - var(--thumb-inset) - 2px);
|
|
82
88
|
|
|
83
89
|
border-color: var(--color-stroke-soft-200);
|
|
84
90
|
background-color: var(--bg-color);
|
|
85
91
|
pointer-events: none;
|
|
86
92
|
|
|
87
93
|
.celeste-switch-thumb {
|
|
88
|
-
inset-inline-start: var(--spacing-2);
|
|
89
94
|
border-color: var(--color-bg-soft-200);
|
|
90
95
|
background-color: var(--color-bg-soft-200);
|
|
91
96
|
box-shadow: none;
|
|
92
|
-
|
|
93
|
-
&[data-state='checked'] {
|
|
94
|
-
inset-inline-start: calc(100% - var(--thumb-size));
|
|
95
|
-
}
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
99
|
|
|
99
|
-
&:active:not(:disabled)
|
|
100
|
-
--thumb-
|
|
100
|
+
&:active:not(:disabled) {
|
|
101
|
+
--thumb-scale: 0.833;
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
&:hover:not(:active, :disabled) {
|
|
@@ -237,3 +237,42 @@ export const IconsOnly: Story = {
|
|
|
237
237
|
`,
|
|
238
238
|
}),
|
|
239
239
|
};
|
|
240
|
+
|
|
241
|
+
export const FilledAndScrollable: Story = {
|
|
242
|
+
args: {
|
|
243
|
+
orientation: 'horizontal',
|
|
244
|
+
defaultValue: 'orders',
|
|
245
|
+
},
|
|
246
|
+
render: args => ({
|
|
247
|
+
components: { TabMenu, TabMenuList, TabMenuItem, TabMenuContent, HintText },
|
|
248
|
+
setup() {
|
|
249
|
+
return { args };
|
|
250
|
+
},
|
|
251
|
+
template: `
|
|
252
|
+
<div style="display: flex; flex-direction: column; gap: 32px; width: 480px; margin: 0 auto;">
|
|
253
|
+
<TabMenu v-bind="args">
|
|
254
|
+
<TabMenuList fill align="center">
|
|
255
|
+
<TabMenuItem value="orders">Orders</TabMenuItem>
|
|
256
|
+
<TabMenuItem value="products">Products</TabMenuItem>
|
|
257
|
+
<TabMenuItem value="customers">Customers</TabMenuItem>
|
|
258
|
+
</TabMenuList>
|
|
259
|
+
<TabMenuContent value="orders"><div style="padding: 16px;"><HintText text="fill + align center" /></div></TabMenuContent>
|
|
260
|
+
<TabMenuContent value="products"><div style="padding: 16px;"><HintText text="fill + align center" /></div></TabMenuContent>
|
|
261
|
+
<TabMenuContent value="customers"><div style="padding: 16px;"><HintText text="fill + align center" /></div></TabMenuContent>
|
|
262
|
+
</TabMenu>
|
|
263
|
+
|
|
264
|
+
<TabMenu v-bind="args">
|
|
265
|
+
<TabMenuList scrollable :bordered="false">
|
|
266
|
+
<TabMenuItem value="orders">Orders</TabMenuItem>
|
|
267
|
+
<TabMenuItem value="products">Products</TabMenuItem>
|
|
268
|
+
<TabMenuItem value="customers">Customers</TabMenuItem>
|
|
269
|
+
<TabMenuItem value="discounts">Discounts</TabMenuItem>
|
|
270
|
+
<TabMenuItem value="analytics">Analytics</TabMenuItem>
|
|
271
|
+
<TabMenuItem value="marketing">Marketing</TabMenuItem>
|
|
272
|
+
</TabMenuList>
|
|
273
|
+
<TabMenuContent value="orders"><div style="padding: 16px;"><HintText text="scrollable, no border" /></div></TabMenuContent>
|
|
274
|
+
</TabMenu>
|
|
275
|
+
</div>
|
|
276
|
+
`,
|
|
277
|
+
}),
|
|
278
|
+
};
|
|
@@ -23,7 +23,9 @@ const forwardedProps = useForwardProps(delegatedProps);
|
|
|
23
23
|
<span v-if="$slots.default" class="celeste-tab-menu-item-label">
|
|
24
24
|
<slot />
|
|
25
25
|
</span>
|
|
26
|
-
<
|
|
26
|
+
<span v-if="$slots.postfix" class="celeste-tab-menu-item-postfix">
|
|
27
|
+
<slot name="postfix" />
|
|
28
|
+
</span>
|
|
27
29
|
</TabsTrigger>
|
|
28
30
|
</template>
|
|
29
31
|
|
|
@@ -36,17 +38,20 @@ const forwardedProps = useForwardProps(delegatedProps);
|
|
|
36
38
|
justify-content: flex-start;
|
|
37
39
|
width: 100%;
|
|
38
40
|
padding: var(--spacing-8);
|
|
39
|
-
transition:
|
|
41
|
+
transition:
|
|
42
|
+
background-color var(--animation-fast) var(--animation-function),
|
|
43
|
+
color var(--animation-fast) var(--animation-function);
|
|
40
44
|
border: none;
|
|
41
45
|
border-radius: var(--radius-8);
|
|
42
46
|
color: var(--color-text-sub-600);
|
|
43
|
-
font
|
|
47
|
+
font: var(--label-sm);
|
|
44
48
|
cursor: pointer;
|
|
45
49
|
gap: var(--spacing-6);
|
|
46
50
|
|
|
47
51
|
&:deep(i) {
|
|
48
52
|
width: 20px;
|
|
49
53
|
height: 20px;
|
|
54
|
+
transition: color var(--animation-fast) var(--animation-function);
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
&:focus {
|
|
@@ -54,33 +59,32 @@ const forwardedProps = useForwardProps(delegatedProps);
|
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
&[data-orientation='horizontal'] {
|
|
57
|
-
position: relative;
|
|
58
62
|
width: fit-content;
|
|
59
63
|
padding-block: var(--spacing-14);
|
|
60
64
|
padding-inline: var(--spacing-0);
|
|
61
|
-
|
|
62
|
-
&::after {
|
|
63
|
-
content: '';
|
|
64
|
-
display: block;
|
|
65
|
-
position: absolute;
|
|
66
|
-
inset-inline: 0;
|
|
67
|
-
inset-block-end: 0;
|
|
68
|
-
width: 100%;
|
|
69
|
-
height: 2px;
|
|
70
|
-
transition: all var(--animation-fast) var(--animation-function);
|
|
71
|
-
background-color: transparent;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
&[data-orientation='vertical'][data-state='active'] {
|
|
76
|
-
background-color: var(--color-bg-weak-50);
|
|
65
|
+
background-color: var(--color-bg-white-0);
|
|
77
66
|
}
|
|
78
67
|
|
|
79
|
-
&[data-orientation='
|
|
68
|
+
&[data-orientation='vertical'] {
|
|
80
69
|
background-color: var(--color-bg-white-0);
|
|
81
70
|
|
|
82
|
-
|
|
83
|
-
|
|
71
|
+
&:hover,
|
|
72
|
+
&[data-state='active'] {
|
|
73
|
+
background-color: var(--color-bg-weak-50);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.celeste-tab-menu-item-postfix {
|
|
77
|
+
display: inline-flex;
|
|
78
|
+
transform: scale(0.75);
|
|
79
|
+
transition:
|
|
80
|
+
transform var(--animation-fast) var(--animation-function),
|
|
81
|
+
opacity var(--animation-fast) var(--animation-function);
|
|
82
|
+
opacity: 0;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
&[data-state='active'] .celeste-tab-menu-item-postfix {
|
|
86
|
+
transform: scale(1);
|
|
87
|
+
opacity: 1;
|
|
84
88
|
}
|
|
85
89
|
}
|
|
86
90
|
|
|
@@ -94,14 +98,9 @@ const forwardedProps = useForwardProps(delegatedProps);
|
|
|
94
98
|
}
|
|
95
99
|
}
|
|
96
100
|
|
|
97
|
-
&[data-state='inactive'] {
|
|
98
|
-
background-color: var(--color-bg-white-0);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
101
|
.celeste-tab-menu-item-label {
|
|
102
102
|
flex: 1;
|
|
103
103
|
overflow: hidden;
|
|
104
|
-
font-size: var(--font-size-2);
|
|
105
104
|
text-align: start;
|
|
106
105
|
text-overflow: ellipsis;
|
|
107
106
|
white-space: nowrap;
|