@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.
Files changed (66) 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 +1 -1
  5. package/dist/celeste.css +189 -86
  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/index.cjs +2 -0
  14. package/dist/cjs/use-tab-observer.cjs +42 -0
  15. package/dist/components/segmented-control/segmented-control.d.ts +2 -2
  16. package/dist/components/tab-menu/tab-menu-list.d.ts +14 -5
  17. package/dist/composables/index.d.ts +1 -0
  18. package/dist/composables/use-tab-observer.d.ts +14 -0
  19. package/dist/es/chunks/BubbleSelect.js +1 -1
  20. package/dist/es/chunks/CollapsibleRoot.js +1 -1
  21. package/dist/es/chunks/ComboboxInput.js +1 -1
  22. package/dist/es/chunks/ComboboxRoot.js +1 -1
  23. package/dist/es/chunks/DialogRoot.js +1 -1
  24. package/dist/es/chunks/DropdownMenuRoot.js +1 -1
  25. package/dist/es/chunks/MenuRoot.js +1 -1
  26. package/dist/es/chunks/MenuSub.js +1 -1
  27. package/dist/es/chunks/PaginationRoot.js +1 -1
  28. package/dist/es/chunks/PinInputRoot.js +1 -1
  29. package/dist/es/chunks/PopoverRoot.js +1 -1
  30. package/dist/es/chunks/ProgressIndicator.js +1 -1
  31. package/dist/es/chunks/RadioGroupRoot.js +1 -1
  32. package/dist/es/chunks/RovingFocusGroup.js +1 -1
  33. package/dist/es/chunks/SelectItemAlignedPosition.js +1 -1
  34. package/dist/es/chunks/TabsRoot.js +1 -1
  35. package/dist/es/chunks/ToggleGroupRoot.js +1 -1
  36. package/dist/es/chunks/TooltipRoot.js +1 -1
  37. package/dist/es/chunks/bar-chart.js +1 -1
  38. package/dist/es/chunks/calendar.js +1 -1
  39. package/dist/es/chunks/checkbox.js +1 -1
  40. package/dist/es/chunks/counter-input.js +1 -1
  41. package/dist/es/chunks/dist2.js +1 -1
  42. package/dist/es/chunks/dropdown-menu-sub.js +1 -1
  43. package/dist/es/chunks/fancy-button.js +1 -1
  44. package/dist/es/chunks/radio-group-item.js +1 -1
  45. package/dist/es/chunks/range-calendar.js +1 -1
  46. package/dist/es/chunks/scroll-area.js +1 -1
  47. package/dist/es/chunks/scroll-bar.js +2 -1
  48. package/dist/es/chunks/segmented-control-item.js +2 -2
  49. package/dist/es/chunks/segmented-control.js +20 -4
  50. package/dist/es/chunks/sidebar-provider.js +1 -1
  51. package/dist/es/chunks/slider.js +1 -1
  52. package/dist/es/chunks/switch.js +1 -1
  53. package/dist/es/chunks/tab-menu-item.js +6 -2
  54. package/dist/es/chunks/tab-menu-list.js +56 -10
  55. package/dist/es/index.js +2 -1
  56. package/dist/es/use-tab-observer.js +41 -0
  57. package/package.json +3 -3
  58. package/src/components/button/fancy-button.vue +14 -4
  59. package/src/components/segmented-control/segmented-control-item.vue +3 -3
  60. package/src/components/segmented-control/segmented-control.vue +35 -0
  61. package/src/components/switch/switch.vue +19 -18
  62. package/src/components/tab-menu/stories/tab-menu.stories.ts +39 -0
  63. package/src/components/tab-menu/tab-menu-item.vue +27 -28
  64. package/src/components/tab-menu/tab-menu-list.vue +85 -3
  65. package/src/composables/index.ts +1 -0
  66. 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
- 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>
@@ -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
+ }