@meistrari/tela-build 1.58.0 → 1.59.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.
@@ -72,21 +72,6 @@ onBeforeUnmount(() => {
72
72
  --at-apply: 'absolute bottom-0 left-0 right-0 z-2 mx-12px mb-12px';
73
73
  }
74
74
 
75
- [data-chat-body]:has([data-chat-prompt-input]) [data-reka-scroll-area-viewport]:has([data-chat-conversation]),
76
- [data-chat-body]:has([data-chat-prompt-input]) > [data-chat-conversation] {
77
- animation: none;
78
- mask: linear-gradient(
79
- to bottom,
80
- #000 calc(100% - var(--chat-input-height, 64px) - 40px),
81
- transparent calc(100% - var(--chat-input-height, 64px))
82
- );
83
- -webkit-mask: linear-gradient(
84
- to bottom,
85
- #000 calc(100% - var(--chat-input-height, 64px) - 40px),
86
- transparent calc(100% - var(--chat-input-height, 64px))
87
- );
88
- }
89
-
90
75
  [data-chat-body]:has([data-chat-prompt-input]) .chat-conversation-scrollbar {
91
76
  top: 8px !important;
92
77
  bottom: calc(var(--chat-input-height, 64px) + 16px) !important;
@@ -3,25 +3,19 @@ withDefaults(defineProps<{
3
3
  title?: string
4
4
  newConversationLabel?: string
5
5
  historyLabel?: string
6
- closeLabel?: string
7
6
  }>(), {
8
7
  newConversationLabel: 'New conversation',
9
8
  historyLabel: 'Conversation history',
10
- closeLabel: 'Close',
11
9
  })
12
10
 
13
11
  const emit = defineEmits<{
14
12
  (e: 'newConversation'): void
15
13
  (e: 'selectConversation', id: string): void
16
- (e: 'close'): void
17
14
  }>()
18
15
 
19
16
  const historyOpen = ref(false)
20
17
  const historySelection = ref('')
21
18
 
22
- const instance = getCurrentInstance()
23
- const hasCloseListener = computed(() => Boolean(instance?.vnode.props?.onClose))
24
-
25
19
  function selectConversation(id: unknown) {
26
20
  if (typeof id !== 'string' || !id)
27
21
  return
@@ -52,7 +46,7 @@ function selectConversation(id: unknown) {
52
46
  size="sm"
53
47
  color="secondary"
54
48
  :aria-label="newConversationLabel"
55
- @click="emit('newConversation')"
49
+ @click.stop.prevent="emit('newConversation')"
56
50
  />
57
51
  <TelaComboboxRoot
58
52
  v-if="$slots.history"
@@ -83,14 +77,6 @@ function selectConversation(id: unknown) {
83
77
  <slot v-if="historyOpen" name="history" />
84
78
  </TelaComboboxList>
85
79
  </TelaComboboxRoot>
86
- <TelaIconButton
87
- v-if="hasCloseListener"
88
- icon="i-ph-x"
89
- size="sm"
90
- color="secondary"
91
- :aria-label="closeLabel"
92
- @click="emit('close')"
93
- />
94
80
  </div>
95
81
  </div>
96
82
  </template>
@@ -35,7 +35,7 @@ const resolvedEmptyMessage = computed(() =>
35
35
  :placeholder="searchPlaceholder"
36
36
  />
37
37
 
38
- <div flex flex-col gap-2px p-4px max-h-280px overflow-y-auto>
38
+ <div flex flex-col gap-2px p-4px max-h-280px overflow-y-auto no-scrollbar>
39
39
  <template v-if="showSkeleton">
40
40
  <div
41
41
  v-for="row in skeletonRows"
@@ -163,10 +163,7 @@ const conversations = [
163
163
  <div class="relative w-full h-560px">
164
164
  <TelaChatFloatingWindow contained :open="isOpen" @update:open="isOpen = $event">
165
165
  <!-- The default launcher is TelaChatFloatingWindowTrigger; override it via the #launcher slot. -->
166
- <TelaChatWidgetHeader
167
- title="Release notes review"
168
- @close="isOpen = false"
169
- >
166
+ <TelaChatWidgetHeader title="Release notes review">
170
167
  <template #history>
171
168
  <TelaChatWidgetHistoryList :items="conversations" />
172
169
  </template>
@@ -1310,7 +1307,6 @@ type TextShimmerProps = {
1310
1307
  - **`TelaChatSidepanelWindow` goes last in a flex row.** It is in-flow (`position: sticky`), so the row reserves its width; never absolutely position it over the page.
1311
1308
  - **Never add extra scroll wrappers around `TelaChatConversation`.** Attrs land on the element that actually scrolls; wrapping it breaks the fog and `scrollToBottom()`.
1312
1309
  - **Only pass `title` to `TelaChatWidgetHeader` once the conversation has one.** The header hides its title when none is provided.
1313
- - **The header's close button renders only when a `close` listener is bound.** Bind `@close` in dismissible shells (floating window); omit it in the always-open sidepanel and no close button appears.
1314
1310
  - **Never change the model selector's `side`/`align` in a real chat UI.** The defaults (`top`/`end`) are correct wherever the prompt input sits at the bottom; `bottom`/`start` exists for constrained previews like the docs demos.
1315
1311
  - **Model images belong in the model selector's options list, never in its trigger.** Pass provider icons through `options` and they render in the dropdown; the closed trigger shows only the selected model's label (the component enforces this with `label-icon-visible: false`).
1316
1312
 
@@ -42,8 +42,10 @@ defineExpose({ scrollToBottom })
42
42
 
43
43
  const contentRef = ref<HTMLElement | null>(null)
44
44
 
45
- const { fogClass } = useScrollFog(contentRef, () => {
46
- const root = scrollAreaRef.value?.$el as HTMLElement | null | undefined
45
+ const fogTarget = computed(() => contentRef.value ?? containerRef.value)
46
+
47
+ const { fogClass } = useScrollFog(fogTarget, () => {
48
+ const root = (scrollAreaRef.value?.$el as HTMLElement | null | undefined) ?? containerRef.value
47
49
 
48
50
  return root?.clientHeight ?? Number.POSITIVE_INFINITY
49
51
  })
@@ -62,7 +64,42 @@ const { fogClass } = useScrollFog(contentRef, () => {
62
64
  <slot />
63
65
  </div>
64
66
  </TelaScrollArea>
65
- <div v-else ref="containerRef" data-chat-conversation v-bind="$attrs" flex-1 overflow-y-auto>
67
+ <div v-else ref="containerRef" data-chat-conversation v-bind="$attrs" flex-1 overflow-y-auto :class="[fogClass]">
66
68
  <slot />
67
69
  </div>
68
70
  </template>
71
+
72
+ <style>
73
+ /* Bottom-only fog: content fades out over the last `--chat-fog-size` pixels of the visible area. */
74
+ @property --chat-fog-size {
75
+ syntax: '<length>';
76
+ inherits: false;
77
+ initial-value: 28px;
78
+ }
79
+
80
+ .scroll-fog[data-chat-conversation],
81
+ .scroll-fog:has([data-chat-conversation]) [data-reka-scroll-area-viewport] {
82
+ --chat-fog-size: 28px;
83
+ mask: linear-gradient(
84
+ to bottom,
85
+ #000 calc(100% - var(--chat-fog-size)),
86
+ transparent
87
+ );
88
+ }
89
+
90
+ /* Where scroll-driven animations exist, the fog retracts over the last 28px of scroll. */
91
+ @supports (animation-timeline: scroll()) {
92
+ .scroll-fog[data-chat-conversation],
93
+ .scroll-fog:has([data-chat-conversation]) [data-reka-scroll-area-viewport] {
94
+ animation: fog-retract both linear;
95
+ animation-timeline: scroll(self);
96
+ animation-range: calc(100% - 28px) 100%;
97
+ }
98
+
99
+ @keyframes fog-retract {
100
+ to {
101
+ --chat-fog-size: 0px;
102
+ }
103
+ }
104
+ }
105
+ </style>
@@ -111,38 +111,7 @@ function focusEditor(event: Event) {
111
111
  </template>
112
112
 
113
113
  <style>
114
- .popover-enter-exit {
114
+ .widget-popover {
115
115
  transform-origin: var(--reka-popover-content-transform-origin);
116
-
117
- &[data-state="open"] {
118
- animation: slideDownAndFade 0.12s ease-out forwards;
119
- }
120
-
121
- &[data-state="closed"] {
122
- animation: slideUpAndFade 0.12s ease-out forwards;
123
- animation-delay: 0s;
124
- }
125
- }
126
-
127
- @keyframes slideDownAndFade {
128
- from {
129
- opacity: 0;
130
- transform: scale(0.97);
131
- }
132
- to {
133
- opacity: 1;
134
- transform: scale(1);
135
- }
136
- }
137
-
138
- @keyframes slideUpAndFade {
139
- from {
140
- opacity: 1;
141
- transform: translateY(0) scale(1);
142
- }
143
- to {
144
- opacity: 0;
145
- transform: scale(0.97);
146
- }
147
116
  }
148
117
  </style>
@@ -1,19 +1,10 @@
1
1
  <script setup lang="ts">
2
- import { computed } from 'vue'
3
-
4
- const props = withDefaults(defineProps<{
2
+ withDefaults(defineProps<{
5
3
  /** `contained` renders the bubble surface; `flat` renders bare content. */
6
4
  variant?: 'contained' | 'flat'
7
- /** Which side the bubble tail (tight corner) sits on. `contained` only. */
8
- align?: 'start' | 'end'
9
5
  }>(), {
10
6
  variant: 'contained',
11
- align: 'end',
12
7
  })
13
-
14
- const tailClass = computed(() => props.align === 'end'
15
- ? 'rounded-tl-12px rounded-tr-12px rounded-br-12px rounded-bl-12px'
16
- : 'rounded-tl-4px rounded-tr-16px rounded-br-16px rounded-bl-16px')
17
8
  </script>
18
9
 
19
10
  <template>
@@ -24,7 +15,7 @@ const tailClass = computed(() => props.align === 'end'
24
15
  gap-8px
25
16
  px-12px py-10px
26
17
  bg-muted text-primary
27
- :class="tailClass"
18
+ rounded-12px
28
19
  >
29
20
  <slot />
30
21
  </div>
@@ -31,7 +31,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
31
31
  <ComboboxPortal :disabled="props.disablePortal">
32
32
  <ComboboxContent
33
33
  v-bind="forwarded"
34
- :class="cn('ComboboxContent z-[9999] [box-shadow:0_4px_16px_0_rgba(85,91,98,0.14)] overflow-hidden outline-none rounded-[16px] bg border-0.5px border pointer-events-auto', props.class)"
34
+ :class="cn('ComboboxContent popover-enter-exit z-[9999] [box-shadow:0_4px_16px_0_rgba(85,91,98,0.14)] overflow-hidden outline-none rounded-[16px] bg border-0.5px border pointer-events-auto', props.class)"
35
35
  >
36
36
  <ComboboxViewport>
37
37
  <slot />
@@ -44,37 +44,5 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
44
44
  .ComboboxContent {
45
45
  min-width: var(--reka-combobox-trigger-width);
46
46
  transform-origin: var(--reka-combobox-content-transform-origin);
47
-
48
- &[data-state="open"] {
49
- animation: slideDownAndFade 0.12s ease-out forwards;
50
- }
51
-
52
- &[data-state="closed"] {
53
- animation: slideUpAndFade 0.12s ease-out forwards;
54
- animation-delay: 0s;
55
- }
56
-
57
- }
58
-
59
- @keyframes slideDownAndFade {
60
- from {
61
- opacity: 0;
62
- transform: scale(0.97);
63
- }
64
- to {
65
- opacity: 1;
66
- transform: scale(1);
67
- }
68
- }
69
-
70
- @keyframes slideUpAndFade {
71
- from {
72
- opacity: 1;
73
- transform: scale(1);
74
- }
75
- to {
76
- opacity: 0;
77
- transform: scale(0.97);
78
- }
79
47
  }
80
48
  </style>
@@ -113,7 +113,8 @@ const defaultLabel = computed(() => {
113
113
  rounded-xl
114
114
  bg-white
115
115
  shadow-lg
116
- class="will-change-[transform,opacity] data-[state=open]:data-[side=top]:animate-slideDownAndFade data-[state=open]:data-[side=right]:animate-slideLeftAndFade data-[state=open]:data-[side=bottom]:animate-slideUpAndFade data-[state=open]:data-[side=left]:animate-slideRightAndFade"
116
+ class="popover-enter-exit will-change-[transform,opacity]"
117
+ style="transform-origin: var(--reka-date-range-picker-content-transform-origin)"
117
118
  >
118
119
  <DateRangePickerArrow fill-white />
119
120
  <DateRangePickerCalendar
@@ -29,7 +29,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
29
29
  <DropdownMenuPortal>
30
30
  <DropdownMenuContent
31
31
  v-bind="forwarded"
32
- :class="cn('DropdownMenuContent z-50 min-w-60 overflow-hidden rounded-2xl border-[0.5px] border-gray-300 bg-white-1000 p-1 shadow-sm', props.class)"
32
+ :class="cn('DropdownMenuContent popover-enter-exit z-50 min-w-60 overflow-hidden rounded-2xl border-[0.5px] border-gray-300 bg-white-1000 p-1 shadow-sm', props.class)"
33
33
  >
34
34
  <slot />
35
35
  </DropdownMenuContent>
@@ -39,36 +39,5 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
39
39
  <style>
40
40
  .DropdownMenuContent {
41
41
  transform-origin: var(--radix-dropdown-menu-content-transform-origin);
42
-
43
- &[data-state="open"] {
44
- animation: slideDownAndFade 0.12s ease-out forwards;
45
- }
46
-
47
- &[data-state="closed"] {
48
- animation: slideUpAndFade 0.12s ease-out forwards;
49
- animation-delay: 0s;
50
- }
51
- }
52
-
53
- @keyframes slideDownAndFade {
54
- from {
55
- opacity: 0;
56
- transform: scale(0.97);
57
- }
58
- to {
59
- opacity: 1;
60
- transform: scale(1);
61
- }
62
- }
63
-
64
- @keyframes slideUpAndFade {
65
- from {
66
- opacity: 1;
67
- transform: scale(1);
68
- }
69
- to {
70
- opacity: 0;
71
- transform: scale(0.97);
72
- }
73
42
  }
74
43
  </style>
@@ -29,7 +29,7 @@ const forwardedProps = useForwardProps(delegatedProps)
29
29
  v-bind="forwardedProps"
30
30
  :class="
31
31
  cn(
32
- 'MenubarContent z-50 min-w-60 overflow-hidden rounded-2xl border-[0.5px] border-strong bg p-4px',
32
+ 'MenubarContent popover-enter-exit z-50 min-w-60 overflow-hidden rounded-2xl border-[0.5px] border-strong bg p-4px',
33
33
  '[box-shadow:0_4px_16px_0_rgba(85,91,98,0.14)]',
34
34
  props.class,
35
35
  )
@@ -43,36 +43,5 @@ const forwardedProps = useForwardProps(delegatedProps)
43
43
  <style>
44
44
  .MenubarContent {
45
45
  transform-origin: var(--reka-menubar-content-transform-origin);
46
-
47
- &[data-state="open"] {
48
- animation: slideDownAndFade 0.12s ease-out forwards;
49
- }
50
-
51
- &[data-state="closed"] {
52
- animation: slideUpAndFade 0.12s ease-out forwards;
53
- animation-delay: 0s;
54
- }
55
- }
56
-
57
- @keyframes slideDownAndFade {
58
- from {
59
- opacity: 0;
60
- transform: scale(0.97);
61
- }
62
- to {
63
- opacity: 1;
64
- transform: scale(1);
65
- }
66
- }
67
-
68
- @keyframes slideUpAndFade {
69
- from {
70
- opacity: 1;
71
- transform: scale(1);
72
- }
73
- to {
74
- opacity: 0;
75
- transform: scale(0.97);
76
- }
77
46
  }
78
47
  </style>
@@ -220,7 +220,7 @@ function handleItemSelect(option: any) {
220
220
  'flying-shadow',
221
221
  'b-0.5px b-gray-300',
222
222
  'overflow-hidden',
223
- 'will-change-[opacity,transform] data-[side=top]:animate-slideDownAndFade data-[side=right]:animate-slideLeftAndFade data-[side=bottom]:animate-slideUpAndFade data-[side=left]:animate-slideRightAndFade',
223
+ 'will-change-[opacity,transform]',
224
224
  )"
225
225
  :style="{
226
226
  width: compact ? 'fit-content' : 'auto',
@@ -222,10 +222,6 @@ const remainingItems = computed(() => {
222
222
 
223
223
  const isSelected = (value: string) => selectedValues.value.includes(value)
224
224
 
225
- const animationClass = `
226
- will-change-[opacity,transform] data-[side=top]:animate-slideDownAndFade data-[side=right]:animate-slideLeftAndFade data-[side=bottom]:animate-slideUpAndFade data-[side=left]:animate-slideRightAndFade
227
- `
228
-
229
225
  const buttonLabel = computed(() => props.buttonLabel ?? (selectedOptions.value.length === 0 ? t('common.add') : t('common.addAnother')))
230
226
 
231
227
  function toggleSelection(value: string) {
@@ -449,10 +445,9 @@ function handleSearchKeydown(e: KeyboardEvent) {
449
445
 
450
446
  <SelectPortal>
451
447
  <SelectContent
452
- class="SelectContent bg-white rounded-10px"
448
+ class="SelectContent popover-enter-exit bg-white rounded-10px"
453
449
  flying-shadow
454
450
  b="0.5px border" overflow-hidden
455
- :class="[animationClass]"
456
451
  :side-offset="4"
457
452
  relative
458
453
  position="popper"
@@ -617,35 +612,5 @@ function handleSearchKeydown(e: KeyboardEvent) {
617
612
  <style>
618
613
  .SelectContent {
619
614
  transform-origin: var(--reka-select-content-transform-origin);
620
-
621
- &[data-state="open"] {
622
- animation: slideDownAndFade 0.12s ease-out;
623
- }
624
-
625
- &[data-state="closed"] {
626
- animation: slideUpAndFade 0.12s ease-out;
627
- }
628
- }
629
-
630
- @keyframes slideDownAndFade {
631
- from {
632
- opacity: 0;
633
- transform: scale(0.97);
634
- }
635
- to {
636
- opacity: 1;
637
- transform: scale(1);
638
- }
639
- }
640
-
641
- @keyframes slideUpAndFade {
642
- from {
643
- opacity: 1;
644
- transform: scale(1);
645
- }
646
- to {
647
- opacity: 0;
648
- transform: scale(0.97);
649
- }
650
615
  }
651
616
  </style>
@@ -36,7 +36,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
36
36
  <SelectContent
37
37
  v-bind="{ ...forwarded, ...$attrs }"
38
38
  :class="cn(
39
- 'SelectContent relative z-999 max-h-80 overflow-hidden rounded-[10px] border-[0.5px] border-gray-300 bg-white-1000',
39
+ 'SelectContent popover-enter-exit relative z-999 max-h-80 overflow-hidden rounded-[10px] border-[0.5px] border-gray-300 bg-white-1000',
40
40
  props.class,
41
41
  )"
42
42
  :side-offset="4"
@@ -52,7 +52,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
52
52
  v-else
53
53
  v-bind="{ ...forwarded, ...$attrs }"
54
54
  :class="cn(
55
- 'SelectContent relative z-999 max-h-80 overflow-hidden rounded-[16px] border-[0.5px] border-gray-200 bg-white-1000',
55
+ 'SelectContent popover-enter-exit relative z-999 max-h-80 overflow-hidden rounded-[16px] border-[0.5px] border-gray-200 bg-white-1000',
56
56
  props.class,
57
57
  )"
58
58
  :side-offset="4"
@@ -69,35 +69,5 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
69
69
  .SelectContent {
70
70
  min-width: var(--reka-select-trigger-width);
71
71
  transform-origin: var(--reka-select-content-transform-origin);
72
-
73
- &[data-state="open"] {
74
- animation: slideDownAndFade 0.12s ease-out;
75
- }
76
-
77
- &[data-state="closed"] {
78
- animation: slideUpAndFade 0.12s ease-out;
79
- }
80
- }
81
-
82
- @keyframes slideDownAndFade {
83
- from {
84
- opacity: 0;
85
- transform: scale(0.97);
86
- }
87
- to {
88
- opacity: 1;
89
- transform: scale(1);
90
- }
91
- }
92
-
93
- @keyframes slideUpAndFade {
94
- from {
95
- opacity: 1;
96
- transform: scale(1);
97
- }
98
- to {
99
- opacity: 0;
100
- transform: scale(0.97);
101
- }
102
72
  }
103
73
  </style>
@@ -265,9 +265,8 @@ The overlapping dot effect is achieved using CSS mask:
265
265
  }
266
266
  ```
267
267
 
268
- ### Animation Keyframes
269
- - **slideDownAndFade**: Entry animation with scale and translate
270
- - **slideUpAndFade**: Exit animation with scale and translate
268
+ ### Animation
269
+ - Uses the global `popover-enter-exit` class (`css/animations.css`) for enter/exit scale + fade
271
270
  - Transform origin set to popover content origin
272
271
 
273
272
  ## Integration with Form Systems
@@ -489,9 +489,9 @@ updateAllCreatedTags()
489
489
  as="button"
490
490
  :disabled="props.disabled"
491
491
  :class="cn(
492
- 'group w-fit flex items-center gap-[6px] px-[12px] py-[7px] rounded-[10px] bg-background border-0.5px border',
492
+ 'group w-fit select-none flex items-center gap-[6px] px-[12px] py-[7px] rounded-[10px] bg-background border-0.5px border',
493
493
  'transition ease-in-out duration-80 hover:border-strong hover:bg-subtle data-[state=open]:border-strong data-[state=open]:bg-subtle',
494
- 'active:bg-gray-100 active:border-gray-400/60 [box-shadow:0_1px_6px_0_rgba(103,127,148,0.05)]',
494
+ 'active:bg-muted active:border-gray-400/60 [box-shadow:0_1px_6px_0_rgba(103,127,148,0.05)]',
495
495
  props.disabled && 'opacity-50 cursor-not-allowed hover:bg-background',
496
496
  props.class,
497
497
  )"
@@ -513,7 +513,7 @@ updateAllCreatedTags()
513
513
  </span>
514
514
  </PopoverTrigger>
515
515
  <PopoverPortal>
516
- <PopoverContent class="TagsSelectContent z-[99999]" :side-offset="8" w-220px pt-12px px-16px bg-background border-0.5px border-border shadow-lg rounded-12px overflow-hidden>
516
+ <PopoverContent class="TagsSelectContent popover-enter-exit z-[99999]" :side-offset="8" w-220px pt-12px px-16px bg-background border-0.5px border-border shadow-lg rounded-12px overflow-hidden>
517
517
  <div
518
518
  class="[transition:height_0.25s_ease-out]"
519
519
  :style="computedHeightContent ? { height: computedHeightContent } : {}"
@@ -665,36 +665,5 @@ updateAllCreatedTags()
665
665
 
666
666
  .TagsSelectContent {
667
667
  transform-origin: var(--reka-popover-content-transform-origin);
668
-
669
- &[data-state="open"] {
670
- animation: slideDownAndFade 0.12s ease-out forwards;
671
- }
672
-
673
- &[data-state="closed"] {
674
- animation: slideUpAndFade 0.12s ease-out forwards;
675
- animation-delay: 0s;
676
- }
677
- }
678
-
679
- @keyframes slideDownAndFade {
680
- from {
681
- opacity: 0;
682
- transform: scale(0.97);
683
- }
684
- to {
685
- opacity: 1;
686
- transform: scale(1);
687
- }
688
- }
689
-
690
- @keyframes slideUpAndFade {
691
- from {
692
- opacity: 1;
693
- transform: translateY(0) scale(1);
694
- }
695
- to {
696
- opacity: 0;
697
- transform: scale(0.97);
698
- }
699
668
  }
700
669
  </style>
@@ -0,0 +1,36 @@
1
+ /*
2
+ * Shared enter/exit animation for anchored overlay content (popover, combobox,
3
+ * select menu, dropdown, menubar). Add `popover-enter-exit` to the content
4
+ * element and set its `transform-origin` from the component's
5
+ * `--reka-*-content-transform-origin` variable so the scale animates from the
6
+ * anchor side.
7
+ */
8
+ .popover-enter-exit[data-state='open'] {
9
+ animation: slideDownAndFade 0.18s cubic-bezier(0.25, 0.46, 0.45, 0.94);
10
+ }
11
+
12
+ .popover-enter-exit[data-state='closed'] {
13
+ animation: slideUpAndFade 0.16s cubic-bezier(0.25, 0.46, 0.45, 0.94);
14
+ }
15
+
16
+ @keyframes slideDownAndFade {
17
+ from {
18
+ opacity: 0;
19
+ transform: scale(0.97);
20
+ }
21
+ to {
22
+ opacity: 1;
23
+ transform: scale(1);
24
+ }
25
+ }
26
+
27
+ @keyframes slideUpAndFade {
28
+ from {
29
+ opacity: 1;
30
+ transform: scale(1);
31
+ }
32
+ to {
33
+ opacity: 0;
34
+ transform: scale(0.97);
35
+ }
36
+ }
package/nuxt.config.ts CHANGED
@@ -90,6 +90,7 @@ export default defineNuxtConfig({
90
90
  '@fontsource-variable/geist-mono',
91
91
  join(currentDir, './css/reset.css'),
92
92
  join(currentDir, './css/text.css'),
93
+ join(currentDir, './css/animations.css'),
93
94
  ],
94
95
 
95
96
  vite: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/tela-build",
3
- "version": "1.58.0",
3
+ "version": "1.59.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "app.config.ts",