@youcan/celeste 0.10.4 → 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.
Files changed (69) hide show
  1. package/ai/component-registry.json +30 -2
  2. package/ai/component-registry.md +5 -1
  3. package/ai/icons.md +1 -1
  4. package/ai/tokens.md +12 -2
  5. package/dist/celeste.css +193 -89
  6. package/dist/cjs/chunks/dist2.cjs +6 -0
  7. package/dist/cjs/chunks/fancy-button.cjs +1 -1
  8. package/dist/cjs/chunks/scroll-bar.cjs +1 -0
  9. package/dist/cjs/chunks/segmented-control-item.cjs +1 -1
  10. package/dist/cjs/chunks/segmented-control.cjs +18 -3
  11. package/dist/cjs/chunks/tab-menu-item.cjs +6 -2
  12. package/dist/cjs/chunks/tab-menu-list.cjs +53 -9
  13. package/dist/cjs/chunks/text-input-affix.cjs +1 -1
  14. package/dist/cjs/index.cjs +2 -0
  15. package/dist/cjs/use-tab-observer.cjs +42 -0
  16. package/dist/components/segmented-control/segmented-control.d.ts +2 -2
  17. package/dist/components/tab-menu/tab-menu-list.d.ts +14 -5
  18. package/dist/composables/index.d.ts +1 -0
  19. package/dist/composables/use-tab-observer.d.ts +14 -0
  20. package/dist/es/chunks/BubbleSelect.js +1 -1
  21. package/dist/es/chunks/CollapsibleRoot.js +1 -1
  22. package/dist/es/chunks/ComboboxInput.js +1 -1
  23. package/dist/es/chunks/ComboboxRoot.js +1 -1
  24. package/dist/es/chunks/DialogRoot.js +1 -1
  25. package/dist/es/chunks/DropdownMenuRoot.js +1 -1
  26. package/dist/es/chunks/MenuRoot.js +1 -1
  27. package/dist/es/chunks/MenuSub.js +1 -1
  28. package/dist/es/chunks/PaginationRoot.js +1 -1
  29. package/dist/es/chunks/PinInputRoot.js +1 -1
  30. package/dist/es/chunks/PopoverRoot.js +1 -1
  31. package/dist/es/chunks/ProgressIndicator.js +1 -1
  32. package/dist/es/chunks/RadioGroupRoot.js +1 -1
  33. package/dist/es/chunks/RovingFocusGroup.js +1 -1
  34. package/dist/es/chunks/SelectItemAlignedPosition.js +1 -1
  35. package/dist/es/chunks/TabsRoot.js +1 -1
  36. package/dist/es/chunks/ToggleGroupRoot.js +1 -1
  37. package/dist/es/chunks/TooltipRoot.js +1 -1
  38. package/dist/es/chunks/bar-chart.js +1 -1
  39. package/dist/es/chunks/calendar.js +1 -1
  40. package/dist/es/chunks/checkbox.js +1 -1
  41. package/dist/es/chunks/counter-input.js +1 -1
  42. package/dist/es/chunks/dist2.js +1 -1
  43. package/dist/es/chunks/dropdown-menu-sub.js +1 -1
  44. package/dist/es/chunks/fancy-button.js +1 -1
  45. package/dist/es/chunks/radio-group-item.js +1 -1
  46. package/dist/es/chunks/range-calendar.js +1 -1
  47. package/dist/es/chunks/scroll-area.js +1 -1
  48. package/dist/es/chunks/scroll-bar.js +2 -1
  49. package/dist/es/chunks/segmented-control-item.js +2 -2
  50. package/dist/es/chunks/segmented-control.js +20 -4
  51. package/dist/es/chunks/sidebar-provider.js +1 -1
  52. package/dist/es/chunks/slider.js +1 -1
  53. package/dist/es/chunks/switch.js +1 -1
  54. package/dist/es/chunks/tab-menu-item.js +6 -2
  55. package/dist/es/chunks/tab-menu-list.js +56 -10
  56. package/dist/es/chunks/text-input-affix.js +1 -1
  57. package/dist/es/index.js +2 -1
  58. package/dist/es/use-tab-observer.js +41 -0
  59. package/package.json +3 -3
  60. package/src/components/button/fancy-button.vue +14 -4
  61. package/src/components/segmented-control/segmented-control-item.vue +3 -3
  62. package/src/components/segmented-control/segmented-control.vue +35 -0
  63. package/src/components/switch/switch.vue +19 -18
  64. package/src/components/tab-menu/stories/tab-menu.stories.ts +39 -0
  65. package/src/components/tab-menu/tab-menu-item.vue +27 -28
  66. package/src/components/tab-menu/tab-menu-list.vue +85 -3
  67. package/src/components/text-input/text-input-affix.vue +1 -0
  68. package/src/composables/index.ts +1 -0
  69. package/src/composables/use-tab-observer.ts +51 -0
@@ -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
- <slot name="postfix" />
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: all var(--animation-fast) var(--animation-function);
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-size: var(--font-size-10);
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='horizontal'][data-state='active'] {
68
+ &[data-orientation='vertical'] {
80
69
  background-color: var(--color-bg-white-0);
81
70
 
82
- &::after {
83
- background-color: var(--color-primary-base);
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;
@@ -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
- const props = defineProps<TabsListProps & { class?: HTMLAttributes['class'] }>();
9
- const delegatedProps = useDelegatedProps(props, 'class');
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>
@@ -24,6 +24,7 @@ const delegatedProps = useDelegatedProps(props, 'class');
24
24
  <style scoped lang="scss">
25
25
  .celeste-text-input-affix {
26
26
  display: flex;
27
+ flex-shrink: 0;
27
28
  align-items: center;
28
29
  color: var(--celeste-text-input-affix-color);
29
30
 
@@ -2,3 +2,4 @@ export * from './use-chart-motion';
2
2
  export * from './use-delegated-props';
3
3
  export * from './use-locale';
4
4
  export * from './use-sidebar';
5
+ export * from './use-tab-observer';
@@ -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
+ }