@heyramzi/ui 7.0.0 → 8.1.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 (259) hide show
  1. package/COMPONENTS.md +28 -17
  2. package/README.md +6 -2
  3. package/package.json +25 -15
  4. package/scripts/sync-shadcn.mjs +17 -13
  5. package/scripts/sync-transitions.mjs +11 -11
  6. package/src/agents/agent-avatar.svelte +67 -114
  7. package/src/agents/agent-cast.svelte +31 -7
  8. package/src/agents/demo.svelte +55 -8
  9. package/src/agents/helpers.ts +58 -0
  10. package/src/agents/page-state.ts +70 -0
  11. package/src/agents/types.ts +3 -1
  12. package/src/ai/ai-button/AiButton.svelte +86 -0
  13. package/src/ai/ai-button/index.ts +4 -0
  14. package/src/ai/confirmation/Confirmation.svelte +8 -8
  15. package/src/ai/confirmation/confirmation-context.svelte.ts +2 -2
  16. package/src/ai/generation-progress/GenerationProgress.svelte +354 -0
  17. package/src/ai/generation-progress/index.ts +7 -0
  18. package/src/ai/index.ts +16 -6
  19. package/src/ai/prompt-input/PromptInput.svelte +19 -1
  20. package/src/ai/prompt-input/PromptInputSubmit.svelte +9 -3
  21. package/src/ai/reasoning/Reasoning.svelte +11 -8
  22. package/src/ambient.d.ts +4 -0
  23. package/src/animations/README.md +14 -14
  24. package/src/animations/index.css +3 -14
  25. package/src/animations/upstream-coverage.test.ts +1 -1
  26. package/src/components/copy/clipboard.test.ts +206 -0
  27. package/src/components/copy/clipboard.ts +49 -0
  28. package/src/components/copy/copied.svelte.ts +39 -0
  29. package/src/components/copy/copy-button.svelte +175 -0
  30. package/src/components/copy/copy-button.test.ts +110 -0
  31. package/src/components/copy/index.ts +3 -0
  32. package/src/components/data-table/data-table.test.ts +134 -0
  33. package/src/components/data-table/data-table.ts +77 -0
  34. package/src/components/data-table/index.ts +20 -0
  35. package/src/components/data-table/infinite-scroll.svelte +69 -0
  36. package/src/components/data-table/pagination.svelte +62 -0
  37. package/src/components/data-table/row-arrow.svelte +28 -0
  38. package/src/components/data-table/row-context-menu.svelte +106 -0
  39. package/src/components/data-table/row-context-menu.test.ts +18 -0
  40. package/src/components/data-table/sortable-head.svelte +56 -0
  41. package/src/components/data-table/table-skeleton.svelte +83 -0
  42. package/src/components/hold-to-confirm/hold-to-confirm.svelte +232 -0
  43. package/src/components/hold-to-confirm/index.ts +1 -0
  44. package/src/components/icon/icon.svelte +23 -0
  45. package/src/components/icon/index.ts +1 -0
  46. package/src/components/language-flag/index.ts +1 -0
  47. package/src/components/language-flag/language-flag.svelte +60 -0
  48. package/src/components/list-page/detail-empty.svelte +50 -0
  49. package/src/components/list-page/detail-header.svelte +107 -0
  50. package/src/components/list-page/detail-panel.svelte +90 -0
  51. package/src/components/list-page/detail-row.svelte +36 -0
  52. package/src/components/list-page/detail-stack.svelte +33 -0
  53. package/src/components/list-page/empty-state.svelte +91 -0
  54. package/src/components/list-page/filter-item.svelte +49 -0
  55. package/src/components/list-page/filter-popover.svelte +88 -0
  56. package/src/components/list-page/filter-section.ts +12 -0
  57. package/src/components/list-page/grouped-list.svelte +116 -0
  58. package/src/components/list-page/index.ts +28 -0
  59. package/src/components/list-page/list-page-shell.svelte +195 -0
  60. package/src/components/list-page/list-table.ts +19 -0
  61. package/src/components/list-page/master-detail.svelte +206 -0
  62. package/src/components/list-page/master-detail.test.ts +37 -0
  63. package/src/components/list-page/notice-bar.svelte +68 -0
  64. package/src/components/list-page/prev-next.svelte +104 -0
  65. package/src/components/list-page/queue-rail.ts +25 -0
  66. package/src/components/list-page/rail-body.svelte +29 -0
  67. package/src/components/list-page/rail-empty.svelte +51 -0
  68. package/src/components/list-page/rail-head.svelte +49 -0
  69. package/src/components/list-page/rail-row.svelte +163 -0
  70. package/src/components/list-page/section-host.ts +24 -0
  71. package/src/components/list-page/section-label.svelte +39 -0
  72. package/src/components/list-page/step.test.ts +21 -0
  73. package/src/components/list-page/step.ts +10 -0
  74. package/src/components/list-page/toolbar-search.svelte +63 -0
  75. package/src/components/list-page/toolbar-trigger.ts +23 -0
  76. package/src/components/list-page/types.ts +1 -0
  77. package/src/components/locale-switch/index.ts +1 -0
  78. package/src/components/locale-switch/locale-switch.svelte +59 -0
  79. package/src/components/mark/index.ts +1 -0
  80. package/src/components/mark/mark.svelte +70 -0
  81. package/src/components/open-in/index.ts +6 -0
  82. package/src/components/open-in/open-in.svelte +106 -0
  83. package/src/components/picker/index.ts +4 -0
  84. package/src/components/picker/mark-picker.svelte +84 -0
  85. package/src/components/picker/picker.svelte +143 -0
  86. package/src/components/picker/trigger.ts +42 -0
  87. package/src/components/picker/types.ts +26 -0
  88. package/src/components/segmented/animated-tabs.svelte +175 -0
  89. package/src/components/segmented/collapse.test.ts +49 -0
  90. package/src/components/segmented/collapse.ts +39 -0
  91. package/src/components/segmented/index.ts +41 -0
  92. package/src/components/segmented/section-runs.svelte +79 -0
  93. package/src/components/segmented/segment.svelte +106 -0
  94. package/src/components/segmented/segmented-filter.svelte +125 -0
  95. package/src/components/segmented/segmented-nav.svelte +82 -0
  96. package/src/components/segmented/segmented-overflow.svelte +85 -0
  97. package/src/components/segmented/segmented-track.svelte +181 -0
  98. package/src/components/segmented/segmented.test.ts +20 -0
  99. package/src/components/segmented/segmented.ts +80 -0
  100. package/src/components/star-rating-input/index.ts +9 -0
  101. package/src/components/star-rating-input/star-rating-input.svelte +256 -0
  102. package/src/components/svg/index.ts +1 -0
  103. package/src/components/svg/svg.svelte +9 -0
  104. package/src/effects/border-beam/BorderBeam.svelte +1 -1
  105. package/src/effects/image-comparison/ImageComparison.css +42 -8
  106. package/src/effects/image-comparison/ImageComparison.svelte +138 -21
  107. package/src/effects/image-comparison/compare.test.ts +17 -0
  108. package/src/effects/image-comparison/compare.ts +5 -0
  109. package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte +338 -0
  110. package/src/effects/magic-card/MagicCard.css +47 -0
  111. package/src/effects/magic-card/MagicCard.svelte +57 -0
  112. package/src/effects/marquee/Marquee.css +27 -1
  113. package/src/effects/marquee/Marquee.svelte +67 -3
  114. package/src/effects/reveal/index.ts +2 -1
  115. package/src/effects/reveal/observe.test.ts +60 -0
  116. package/src/effects/reveal/observe.ts +33 -1
  117. package/src/effects/reveal/types.ts +7 -0
  118. package/src/effects/theme-toggle/ThemeToggle.css +199 -6
  119. package/src/effects/theme-toggle/ThemeToggle.svelte +51 -26
  120. package/src/gallery.test.ts +52 -0
  121. package/src/index.ts +5 -1
  122. package/src/lib/panel.ts +7 -1
  123. package/src/lib/theme-transition.ts +37 -11
  124. package/src/lib/tone.ts +48 -0
  125. package/src/shadcn/accordion/accordion-trigger.svelte +15 -6
  126. package/src/shadcn/alert/alert.svelte +3 -1
  127. package/src/shadcn/badge/badge.svelte +8 -7
  128. package/src/shadcn/breadcrumb/breadcrumb-ellipsis.svelte +2 -2
  129. package/src/shadcn/breadcrumb/breadcrumb-separator.svelte +2 -2
  130. package/src/shadcn/calendar/calendar-month-select.svelte +2 -2
  131. package/src/shadcn/calendar/calendar-next-button.svelte +2 -2
  132. package/src/shadcn/calendar/calendar-prev-button.svelte +2 -2
  133. package/src/shadcn/calendar/calendar-year-select.svelte +2 -2
  134. package/src/shadcn/calendar/calendar.svelte +6 -0
  135. package/src/shadcn/code-block/code-block-copy-button.svelte +6 -55
  136. package/src/shadcn/command/index.ts +3 -0
  137. package/src/shadcn/field/index.ts +3 -0
  138. package/src/shadcn/field/simple-field.svelte +71 -0
  139. package/src/shadcn/field/simple-field.test.ts +47 -0
  140. package/src/shadcn/message-scroller/message-scroller-button.svelte +2 -2
  141. package/src/shadcn/radio-group/radio-group-item.svelte +3 -2
  142. package/src/shadcn/sheet/sheet-content.svelte +1 -0
  143. package/src/shadcn/sheet/sheet.css +48 -0
  144. package/src/shadcn/sonner/sonner.svelte +7 -10
  145. package/src/shadcn/toggle-group/toggle-group.svelte +10 -3
  146. package/src/shadcn/trace/trace-collapsible-trigger.svelte +2 -2
  147. package/src/ai/composer/Composer.css +0 -108
  148. package/src/ai/composer/Composer.svelte +0 -111
  149. package/src/ai/composer/index.ts +0 -10
  150. package/src/animations/accordion.css +0 -58
  151. package/src/animations/icon-swap.css +0 -43
  152. package/src/animations/notification-badge.css +0 -81
  153. package/src/animations/panel.css +0 -86
  154. package/src/animations/reasoning-stream.css +0 -49
  155. package/src/animations/skeleton-reveal.css +0 -97
  156. package/src/animations/streaming-text.css +0 -31
  157. package/src/animations/tabs-sliding.css +0 -83
  158. package/src/animations/texts-reveal.css +0 -70
  159. package/src/animations/tooltip.css +0 -72
  160. package/src/animations/view-transition-reveal.ts +0 -74
  161. package/src/lib/utils.ts +0 -45
  162. package/src/showcase/AiSection.svelte +0 -150
  163. package/src/showcase/AnimationsSection.svelte +0 -1658
  164. package/src/showcase/EffectsSection.svelte +0 -152
  165. package/src/showcase/ShadcnSection.svelte +0 -27
  166. package/src/showcase/ShowcaseImport.svelte +0 -126
  167. package/src/showcase/ShowcaseList.svelte +0 -132
  168. package/src/showcase/ShowcaseNav.svelte +0 -247
  169. package/src/showcase/ShowcaseSection.svelte +0 -112
  170. package/src/showcase/ShowcaseShell.svelte +0 -55
  171. package/src/showcase/ShowcaseStage.svelte +0 -342
  172. package/src/showcase/ShowcaseVariant.svelte +0 -109
  173. package/src/showcase/assets/image-reveal/art-1.jpg +0 -0
  174. package/src/showcase/assets/image-reveal/art-2.jpg +0 -0
  175. package/src/showcase/assets/image-reveal/art-3.jpg +0 -0
  176. package/src/showcase/check.svg +0 -1
  177. package/src/showcase/chevron-arms.svg +0 -2
  178. package/src/showcase/chevron-down.svg +0 -1
  179. package/src/showcase/copy.svg +0 -2
  180. package/src/showcase/demos/ai/confirmation.svelte +0 -59
  181. package/src/showcase/demos/ai/loading-state.svelte +0 -19
  182. package/src/showcase/demos/ai/prompt-input.svelte +0 -57
  183. package/src/showcase/demos/ai/reasoning.svelte +0 -19
  184. package/src/showcase/demos/ai/thinking-dots.svelte +0 -15
  185. package/src/showcase/demos/ai/voice-waveform.svelte +0 -24
  186. package/src/showcase/demos/effects/animated-beam.svelte +0 -50
  187. package/src/showcase/demos/effects/animated-group.svelte +0 -47
  188. package/src/showcase/demos/effects/border-beam-default.svelte +0 -20
  189. package/src/showcase/demos/effects/border-beam-line.svelte +0 -20
  190. package/src/showcase/demos/effects/border-beam-mono.svelte +0 -20
  191. package/src/showcase/demos/effects/border-beam-sunset.svelte +0 -20
  192. package/src/showcase/demos/effects/image-comparison.svelte +0 -25
  193. package/src/showcase/demos/effects/image-reveal.svelte +0 -49
  194. package/src/showcase/demos/effects/in-view.svelte +0 -41
  195. package/src/showcase/demos/effects/integrations-hub.svelte +0 -82
  196. package/src/showcase/demos/effects/magnetic.svelte +0 -31
  197. package/src/showcase/demos/effects/marquee.svelte +0 -33
  198. package/src/showcase/demos/effects/progressive-blur.svelte +0 -47
  199. package/src/showcase/demos/effects/spotlight.svelte +0 -40
  200. package/src/showcase/demos/effects/text-effect.svelte +0 -55
  201. package/src/showcase/demos/shadcn/accordion.svelte +0 -45
  202. package/src/showcase/demos/shadcn/alert-dialog.svelte +0 -23
  203. package/src/showcase/demos/shadcn/alert.svelte +0 -30
  204. package/src/showcase/demos/shadcn/attachment.svelte +0 -71
  205. package/src/showcase/demos/shadcn/avatar.svelte +0 -30
  206. package/src/showcase/demos/shadcn/badge.svelte +0 -26
  207. package/src/showcase/demos/shadcn/breadcrumb.svelte +0 -34
  208. package/src/showcase/demos/shadcn/bubble.svelte +0 -36
  209. package/src/showcase/demos/shadcn/button.svelte +0 -11
  210. package/src/showcase/demos/shadcn/calendar.svelte +0 -8
  211. package/src/showcase/demos/shadcn/card.svelte +0 -39
  212. package/src/showcase/demos/shadcn/checkbox.svelte +0 -39
  213. package/src/showcase/demos/shadcn/code-block.svelte +0 -80
  214. package/src/showcase/demos/shadcn/collapsible.svelte +0 -20
  215. package/src/showcase/demos/shadcn/command.svelte +0 -48
  216. package/src/showcase/demos/shadcn/context-menu.svelte +0 -54
  217. package/src/showcase/demos/shadcn/demo-harness.svelte +0 -12
  218. package/src/showcase/demos/shadcn/demos.test.ts +0 -20
  219. package/src/showcase/demos/shadcn/dialog.svelte +0 -38
  220. package/src/showcase/demos/shadcn/dropdown-menu.svelte +0 -59
  221. package/src/showcase/demos/shadcn/empty.svelte +0 -29
  222. package/src/showcase/demos/shadcn/field.svelte +0 -115
  223. package/src/showcase/demos/shadcn/hover-card.svelte +0 -32
  224. package/src/showcase/demos/shadcn/index.ts +0 -382
  225. package/src/showcase/demos/shadcn/input-otp.svelte +0 -19
  226. package/src/showcase/demos/shadcn/input.svelte +0 -5
  227. package/src/showcase/demos/shadcn/label.svelte +0 -11
  228. package/src/showcase/demos/shadcn/marker.svelte +0 -30
  229. package/src/showcase/demos/shadcn/message-scroller.svelte +0 -44
  230. package/src/showcase/demos/shadcn/message.svelte +0 -75
  231. package/src/showcase/demos/shadcn/popover.svelte +0 -36
  232. package/src/showcase/demos/shadcn/progress.svelte +0 -13
  233. package/src/showcase/demos/shadcn/radio-group.svelte +0 -19
  234. package/src/showcase/demos/shadcn/scroll-area.svelte +0 -18
  235. package/src/showcase/demos/shadcn/select.svelte +0 -29
  236. package/src/showcase/demos/shadcn/separator.svelte +0 -12
  237. package/src/showcase/demos/shadcn/sheet.svelte +0 -48
  238. package/src/showcase/demos/shadcn/skeleton.svelte +0 -11
  239. package/src/showcase/demos/shadcn/slider.svelte +0 -7
  240. package/src/showcase/demos/shadcn/sonner.svelte +0 -18
  241. package/src/showcase/demos/shadcn/spinner.svelte +0 -11
  242. package/src/showcase/demos/shadcn/switch.svelte +0 -9
  243. package/src/showcase/demos/shadcn/table.svelte +0 -76
  244. package/src/showcase/demos/shadcn/tabs.svelte +0 -62
  245. package/src/showcase/demos/shadcn/textarea.svelte +0 -5
  246. package/src/showcase/demos/shadcn/toggle-group.svelte +0 -18
  247. package/src/showcase/demos/shadcn/toggle.svelte +0 -14
  248. package/src/showcase/demos/shadcn/tooltip.svelte +0 -13
  249. package/src/showcase/demos/shadcn/trace.svelte +0 -51
  250. package/src/showcase/heart.svg +0 -1
  251. package/src/showcase/index.ts +0 -38
  252. package/src/showcase/kit.test.ts +0 -72
  253. package/src/showcase/kit.ts +0 -16
  254. package/src/showcase/plus.svg +0 -1
  255. package/src/showcase/showcase-shell.css +0 -91
  256. package/src/showcase/stacked-section.css +0 -15
  257. package/src/showcase/success-check.svg +0 -1
  258. package/src/showcase/types.ts +0 -29
  259. package/src/svg-raw.d.ts +0 -7
@@ -1,111 +0,0 @@
1
- <script lang="ts" module>
2
- import type { Snippet } from "svelte";
3
-
4
- export interface ComposerProps {
5
- value: string;
6
- class?: string;
7
- /** Extra classes for the textarea (e.g. a taller min/max height). */
8
- inputClass?: string;
9
- placeholder?: string;
10
- /** Accent color for the send button and focus ring. Falls back to `--primary`. */
11
- accent?: string;
12
- sending?: boolean;
13
- disabled?: boolean;
14
- error?: string | null;
15
- sendLabel?: string;
16
- /**
17
- * Whether the message can be sent. When omitted, falls back to
18
- * "has non-empty text".
19
- */
20
- canSend?: boolean;
21
- onSubmit: () => void;
22
- inputRef?: HTMLTextAreaElement | null;
23
- /** Rendered left of the textarea (e.g. an attach button). */
24
- leading?: Snippet;
25
- /** Rendered above the input row (e.g. a reply-to banner). */
26
- header?: Snippet;
27
- /** Replaces the default spinner shown while sending. */
28
- busy?: Snippet;
29
- }
30
- </script>
31
-
32
- <script lang="ts">
33
- import "./Composer.css";
34
- import { cn } from "@heyramzi/utils";
35
- import { fade } from "svelte/transition";
36
- import PaperPlaneRight from "phosphor-svelte/lib/PaperPlaneRight";
37
- import Spinner from "phosphor-svelte/lib/Spinner";
38
-
39
- let {
40
- value = $bindable(),
41
- class: className,
42
- inputClass,
43
- placeholder = "Write a message...",
44
- accent,
45
- sending = false,
46
- disabled = false,
47
- error = null,
48
- sendLabel = "Send message",
49
- canSend,
50
- onSubmit,
51
- inputRef = $bindable(null),
52
- leading,
53
- header,
54
- busy,
55
- }: ComposerProps = $props();
56
-
57
- // When canSend is not supplied, fall back to "has non-empty text".
58
- const submittable = $derived(canSend ?? value.trim().length > 0);
59
-
60
- function handleKeydown(e: KeyboardEvent) {
61
- if (e.key === "Enter" && !e.shiftKey) {
62
- e.preventDefault();
63
- onSubmit();
64
- }
65
- }
66
- </script>
67
-
68
- <!-- WHY: visuals are scoped CSS so the composer renders without the consumer's
69
- Tailwind generating arbitrary classes; theme hooks come from CSS vars. -->
70
- <div class={cn("chat-composer", className)} style:--chat-accent={accent}>
71
- {@render header?.()}
72
-
73
- <form
74
- onsubmit={(e) => {
75
- e.preventDefault();
76
- onSubmit();
77
- }}
78
- class="chat-composer-row"
79
- >
80
- {@render leading?.()}
81
-
82
- <textarea
83
- bind:this={inputRef}
84
- bind:value
85
- onkeydown={handleKeydown}
86
- {placeholder}
87
- disabled={disabled || sending}
88
- rows={1}
89
- class={cn("chat-composer-input", inputClass)}
90
- ></textarea>
91
-
92
- <button
93
- type="submit"
94
- disabled={disabled || sending || !submittable}
95
- class="chat-composer-send"
96
- aria-label={sendLabel}
97
- >
98
- {#if sending && busy}
99
- {@render busy()}
100
- {:else if sending}
101
- <Spinner class="chat-composer-icon chat-composer-spin" />
102
- {:else}
103
- <PaperPlaneRight class="chat-composer-icon" />
104
- {/if}
105
- </button>
106
- </form>
107
-
108
- {#if error}
109
- <p class="chat-composer-error" in:fade={{ duration: 150 }}>{error}</p>
110
- {/if}
111
- </div>
@@ -1,10 +0,0 @@
1
- import Composer from "./Composer.svelte";
2
-
3
- import type { ComposerProps } from "./Composer.svelte";
4
-
5
- export {
6
- Composer,
7
- type ComposerProps,
8
- //
9
- Composer as Root,
10
- };
@@ -1,58 +0,0 @@
1
- /* Accordion expand — transitions.dev 21.
2
- Height animates on grid-template-rows 0fr -> 1fr, so no JS measures a
3
- height and a panel of any size collapses cleanly. Padding belongs on
4
- `-inner`: on the 0fr track it leaves a residual strip and the panel
5
- never fully closes. The chevron flips rather than morphing its `d`,
6
- because CSS path interpolation is Chromium-only. */
7
- :root {
8
- --acc-expand: var(--duration-fast, 250ms);
9
- --acc-collapse: var(--duration-fast, 250ms);
10
- --acc-chevron: var(--duration-fast, 250ms);
11
- --acc-ease: var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1));
12
- }
13
-
14
- .t-acc-panel {
15
- display: grid;
16
- grid-template-rows: 0fr;
17
- transition: grid-template-rows var(--acc-collapse) var(--acc-ease);
18
- }
19
- .t-acc[data-open="true"] .t-acc-panel {
20
- grid-template-rows: 1fr;
21
- transition: grid-template-rows var(--acc-expand) var(--acc-ease);
22
- }
23
- .t-acc-panel-inner {
24
- overflow: hidden;
25
- opacity: 0;
26
- filter: blur(2px);
27
- transition:
28
- opacity var(--acc-collapse) var(--acc-ease),
29
- filter var(--acc-collapse) var(--acc-ease);
30
- }
31
- .t-acc[data-open="true"] .t-acc-panel-inner {
32
- opacity: 1;
33
- filter: blur(0);
34
- transition:
35
- opacity var(--acc-expand) var(--acc-ease),
36
- filter var(--acc-expand) var(--acc-ease);
37
- }
38
-
39
- .t-acc-chevron {
40
- display: inline-flex;
41
- transform: scaleY(1);
42
- transform-origin: center;
43
- transition: transform var(--acc-chevron) var(--acc-ease);
44
- }
45
- .t-acc-chevron path {
46
- vector-effect: non-scaling-stroke;
47
- }
48
- .t-acc[data-open="true"] .t-acc-chevron {
49
- transform: scaleY(-1);
50
- }
51
-
52
- @media (prefers-reduced-motion: reduce) {
53
- .t-acc-panel,
54
- .t-acc-panel-inner,
55
- .t-acc-chevron {
56
- transition: none !important;
57
- }
58
- }
@@ -1,43 +0,0 @@
1
- /* Transitions.dev — Icon swap */
2
- /* Source: https://github.com/Jakubantalik/transitions.dev */
3
-
4
- :root {
5
- --icon-swap-dur: 200ms;
6
- --icon-swap-blur: var(--blur-small, 2px);
7
- --icon-swap-start-scale: 0.85;
8
- --icon-swap-ease: var(--ease-in-out, ease-in-out);
9
- }
10
-
11
- .t-icon-swap {
12
- position: relative;
13
- display: inline-grid;
14
- }
15
-
16
- .t-icon-swap .t-icon {
17
- grid-area: 1 / 1;
18
- transition:
19
- opacity var(--icon-swap-dur) var(--icon-swap-ease),
20
- filter var(--icon-swap-dur) var(--icon-swap-ease),
21
- transform var(--icon-swap-dur) var(--icon-swap-ease);
22
- will-change: opacity, filter, transform;
23
- }
24
-
25
- .t-icon-swap[data-state="a"] .t-icon[data-icon="a"],
26
- .t-icon-swap[data-state="b"] .t-icon[data-icon="b"] {
27
- opacity: 1;
28
- filter: blur(0);
29
- transform: scale(1);
30
- }
31
-
32
- .t-icon-swap[data-state="a"] .t-icon[data-icon="b"],
33
- .t-icon-swap[data-state="b"] .t-icon[data-icon="a"] {
34
- opacity: 0;
35
- filter: blur(var(--icon-swap-blur));
36
- transform: scale(var(--icon-swap-start-scale));
37
- }
38
-
39
- @media (prefers-reduced-motion: reduce) {
40
- .t-icon-swap .t-icon {
41
- transition: none !important;
42
- }
43
- }
@@ -1,81 +0,0 @@
1
- /* Transitions.dev — Notification badge */
2
- /* Source: https://github.com/Jakubantalik/transitions.dev */
3
-
4
- /*
5
- Usage:
6
- Place .t-badge inside your trigger (bell icon, button, etc.).
7
- The trigger must be position: relative so .t-badge can anchor to it.
8
-
9
- <button class="your-trigger" style="position: relative">
10
- <span class="t-badge" data-open="false">
11
- <span class="t-badge-dot">1</span>
12
- </span>
13
- </button>
14
-
15
- State: toggle data-open="true" / "false" on .t-badge.
16
- Only the badge slides + pops, the trigger itself stays put.
17
- */
18
-
19
- :root {
20
- --badge-slide-dur: 260ms;
21
- --badge-pop-dur: var(--duration-very-slow, 500ms);
22
- --badge-pop-close-dur: 180ms;
23
- --badge-fade-dur: var(--duration-slow, 400ms);
24
- --badge-fade-close-dur: 180ms;
25
- --badge-blur: var(--blur-small, 2px);
26
- --badge-offset-x: -8.2px;
27
- --badge-offset-y: 12.4px;
28
- --badge-slide-ease: var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1));
29
- --badge-pop-ease: var(--ease-smooth-out);
30
- --badge-close-ease: cubic-bezier(0.4, 0, 0.2, 1);
31
- }
32
-
33
- @keyframes t-badge-slide-in {
34
- from {
35
- transform: translate(var(--badge-offset-x), var(--badge-offset-y));
36
- }
37
- to {
38
- transform: translate(0, 0);
39
- }
40
- }
41
-
42
- .t-badge {
43
- position: absolute;
44
- top: -6px;
45
- right: -8px;
46
- pointer-events: none;
47
- will-change: transform;
48
- }
49
- .t-badge[data-open="true"] {
50
- animation: t-badge-slide-in var(--badge-slide-dur) var(--badge-slide-ease);
51
- }
52
-
53
- .t-badge-dot {
54
- display: block;
55
- transform-origin: center;
56
- transform: scale(1);
57
- opacity: 1;
58
- filter: blur(0);
59
- transition:
60
- transform var(--badge-pop-dur) var(--badge-pop-ease),
61
- opacity var(--badge-fade-dur) var(--badge-pop-ease),
62
- filter var(--badge-pop-dur) var(--badge-pop-ease);
63
- will-change: transform, opacity, filter;
64
- }
65
- .t-badge[data-open="false"] .t-badge-dot {
66
- transform: scale(0);
67
- opacity: 0;
68
- filter: blur(var(--badge-blur));
69
- transition:
70
- transform var(--badge-pop-close-dur) var(--badge-close-ease),
71
- opacity var(--badge-fade-close-dur) var(--badge-close-ease),
72
- filter var(--badge-pop-close-dur) var(--badge-close-ease);
73
- }
74
-
75
- @media (prefers-reduced-motion: reduce) {
76
- .t-badge,
77
- .t-badge-dot {
78
- animation: none !important;
79
- transition: none !important;
80
- }
81
- }
@@ -1,86 +0,0 @@
1
- /* Transitions.dev — Side panel */
2
- /* Source: https://github.com/Jakubantalik/transitions.dev */
3
-
4
- :root {
5
- --panel-open-dur: var(--duration-slow, 400ms);
6
- --panel-close-dur: var(--duration-medium, 350ms);
7
- --panel-translate-y: calc(187px * 0.5);
8
- --panel-blur: var(--blur-small, 2px);
9
- --panel-ease: var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1));
10
- }
11
-
12
- .t-panel-slide {
13
- transform: translateY(var(--panel-translate-y));
14
- opacity: 0;
15
- filter: blur(var(--panel-blur));
16
- pointer-events: none;
17
- transition:
18
- transform var(--panel-close-dur) var(--panel-ease),
19
- opacity var(--panel-close-dur) var(--panel-ease),
20
- filter var(--panel-close-dur) var(--panel-ease);
21
- will-change: transform, opacity, filter;
22
- }
23
-
24
- .t-panel-slide[data-open="true"] {
25
- transform: translateY(0);
26
- opacity: 1;
27
- filter: blur(0);
28
- pointer-events: auto;
29
- transition:
30
- transform var(--panel-open-dur) var(--panel-ease),
31
- opacity var(--panel-open-dur) var(--panel-ease),
32
- filter var(--panel-open-dur) var(--panel-ease);
33
- }
34
-
35
- @media (prefers-reduced-motion: reduce) {
36
- .t-panel-slide {
37
- transition: none !important;
38
- }
39
- }
40
-
41
- :root {
42
- --sheet-open-dur: 300ms;
43
- --sheet-close-dur: 250ms;
44
- --sheet-translate: 100%;
45
- --sheet-ease: cubic-bezier(0.22, 1, 0.36, 1);
46
- }
47
-
48
- .t-sheet {
49
- opacity: 0;
50
- pointer-events: none;
51
- transition:
52
- transform var(--sheet-close-dur) var(--sheet-ease),
53
- opacity var(--sheet-close-dur) var(--sheet-ease);
54
- will-change: transform, opacity;
55
- }
56
-
57
- .t-sheet[data-side="right"] {
58
- transform: translateX(var(--sheet-translate));
59
- }
60
-
61
- .t-sheet[data-side="left"] {
62
- transform: translateX(calc(-1 * var(--sheet-translate)));
63
- }
64
-
65
- .t-sheet[data-side="top"] {
66
- transform: translateY(calc(-1 * var(--sheet-translate)));
67
- }
68
-
69
- .t-sheet[data-side="bottom"] {
70
- transform: translateY(var(--sheet-translate));
71
- }
72
-
73
- .t-sheet[data-state="open"] {
74
- transform: translate(0, 0);
75
- opacity: 1;
76
- pointer-events: auto;
77
- transition:
78
- transform var(--sheet-open-dur) var(--sheet-ease),
79
- opacity var(--sheet-open-dur) var(--sheet-ease);
80
- }
81
-
82
- @media (prefers-reduced-motion: reduce) {
83
- .t-sheet {
84
- transition: none !important;
85
- }
86
- }
@@ -1,49 +0,0 @@
1
- /* Reasoning stream — transitions.dev 29.
2
- A card that clips a tall transcript and steps it upward while a model thinks.
3
- JS moves the scroll --reason-lines lines every --reason-hold and clones the
4
- text once, so the offset can wrap by one copy's height mid-hold and the loop
5
- never shows a seam. The edge fades are a mask on the viewport, not gradients
6
- painted over the text, so the card background can be anything. */
7
- :root {
8
- --reason-hold: 840ms;
9
- --reason-step: var(--duration-very-slow, 500ms);
10
- --reason-lines: 2;
11
- --reason-fade: 28px;
12
- --reason-ease: var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1));
13
- }
14
-
15
- .t-reason {
16
- position: relative;
17
- overflow: hidden;
18
- }
19
- .t-reason-viewport {
20
- position: absolute;
21
- inset: 0;
22
- overflow: hidden;
23
- -webkit-mask-image: linear-gradient(
24
- transparent 0,
25
- black var(--reason-fade),
26
- black calc(100% - var(--reason-fade)),
27
- transparent 100%
28
- );
29
- mask-image: linear-gradient(
30
- transparent 0,
31
- black var(--reason-fade),
32
- black calc(100% - var(--reason-fade)),
33
- transparent 100%
34
- );
35
- }
36
- .t-reason-scroll {
37
- position: absolute;
38
- left: 0;
39
- right: 0;
40
- transform: translateY(0);
41
- will-change: transform;
42
- }
43
-
44
- @media (prefers-reduced-motion: reduce) {
45
- .t-reason-scroll {
46
- transition: none !important;
47
- transform: none !important;
48
- }
49
- }
@@ -1,97 +0,0 @@
1
- /* Transitions.dev — Skeleton loader and reveal */
2
- /* Source: https://github.com/Jakubantalik/transitions.dev */
3
-
4
- /*
5
- Usage:
6
- <div class="t-skel" data-state="loading">
7
- <div class="t-skel-skeleton is-pulsing">…</div>
8
- <div class="t-skel-content">…</div>
9
- </div>
10
-
11
- State:
12
- Mount with .is-pulsing on the skeleton so it pulses
13
- --pulse-count times. When data arrives, add .is-revealed to
14
- .t-skel. To replay without animating the reverse, add
15
- .is-resetting, remove .is-revealed, force a reflow, then
16
- drop .is-resetting.
17
- */
18
-
19
- :root {
20
- --pulse-dur: 1000ms;
21
- --pulse-count: 1;
22
- --pulse-min: 0.5;
23
- --reveal-dur: var(--duration-slow, 400ms);
24
- --reveal-blur: var(--blur-small, 2px);
25
- --reveal-ease: var(--ease-in-out, ease-in-out);
26
- }
27
-
28
- /* The wrap stacks two layers on the same coordinates. The
29
- skeleton owns the cold pulse + the fade-out side of the
30
- reveal; the content owns the fade-in side. They share the
31
- same duration / ease so the swap reads as one motion. */
32
- .t-skel {
33
- position: relative;
34
- }
35
- .t-skel-skeleton,
36
- .t-skel-content {
37
- position: absolute;
38
- inset: 0;
39
- }
40
-
41
- .t-skel-skeleton {
42
- z-index: 1;
43
- opacity: 1;
44
- filter: blur(0);
45
- transition:
46
- opacity var(--reveal-dur) var(--reveal-ease),
47
- filter var(--reveal-dur) var(--reveal-ease);
48
- }
49
- .t-skel-content {
50
- z-index: 2;
51
- opacity: 0;
52
- filter: blur(var(--reveal-blur));
53
- transition:
54
- opacity var(--reveal-dur) var(--reveal-ease),
55
- filter var(--reveal-dur) var(--reveal-ease);
56
- }
57
- .t-skel.is-revealed .t-skel-skeleton {
58
- opacity: 0;
59
- filter: blur(var(--reveal-blur));
60
- }
61
- .t-skel.is-revealed .t-skel-content {
62
- opacity: 1;
63
- filter: blur(0);
64
- }
65
- /* Snap-back when replaying: kill transitions so the reverse
66
- (revealed → skeleton) is instant. Drop .is-resetting after a
67
- forced reflow and the next reveal animates again. */
68
- .t-skel.is-resetting .t-skel-skeleton,
69
- .t-skel.is-resetting .t-skel-content {
70
- transition: none !important;
71
- }
72
-
73
- /* Pulse: place the animation on the bar/avatar children, not
74
- on the skeleton itself, so the skeleton's opacity / filter
75
- stay free for the cross-fade transition above. */
76
- .t-skel-skeleton.is-pulsing > * {
77
- animation: t-skel-pulse var(--pulse-dur) ease-in-out var(--pulse-count);
78
- }
79
- @keyframes t-skel-pulse {
80
- 0%,
81
- 100% {
82
- opacity: 1;
83
- }
84
- 50% {
85
- opacity: var(--pulse-min);
86
- }
87
- }
88
-
89
- @media (prefers-reduced-motion: reduce) {
90
- .t-skel-skeleton,
91
- .t-skel-content {
92
- transition: none !important;
93
- }
94
- .t-skel-skeleton.is-pulsing > * {
95
- animation: none !important;
96
- }
97
- }
@@ -1,31 +0,0 @@
1
- /* Streaming text — transitions.dev 30.
2
- JS wraps each word in a `.t-stream-w` and adds `.is-in` word by word every
3
- --stream-gap, so each word resolves out of a small blur instead of appearing.
4
- To replay: wipe every span with transition: none, force one reflow, restore
5
- the transition, then release the words again. */
6
- :root {
7
- --stream-gap: 60ms;
8
- --stream-fade: var(--duration-medium, 350ms);
9
- --stream-blur: 1px;
10
- --stream-ease: var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1));
11
- }
12
-
13
- .t-stream-w {
14
- opacity: 0;
15
- filter: blur(var(--stream-blur));
16
- transition:
17
- opacity var(--stream-fade) var(--stream-ease),
18
- filter var(--stream-fade) var(--stream-ease);
19
- }
20
- .t-stream-w.is-in {
21
- opacity: 1;
22
- filter: blur(0);
23
- }
24
-
25
- @media (prefers-reduced-motion: reduce) {
26
- .t-stream-w {
27
- transition: none !important;
28
- filter: none !important;
29
- opacity: 1 !important;
30
- }
31
- }
@@ -1,83 +0,0 @@
1
- /* Transitions.dev — Tabs sliding */
2
- /* Source: https://github.com/Jakubantalik/transitions.dev */
3
-
4
- /*
5
- Usage:
6
- <div class="t-tabs" role="tablist">
7
- <span class="t-tabs-pill" aria-hidden="true"></span>
8
- <button class="t-tab" role="tab" aria-selected="true">Plan</button>
9
- <button class="t-tab" role="tab" aria-selected="false">Debug</button>
10
- </div>
11
-
12
- Wire-up:
13
- On click, flip aria-selected on each tab and write the active
14
- tab's offsetLeft / offsetWidth onto the pill. On first paint
15
- and resize, write the same values WITHOUT a transition so the
16
- pill snaps to position before any animation can run.
17
- */
18
-
19
- :root {
20
- --tabs-dur: var(--duration-fast, 250ms);
21
- --tabs-ease: var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1));
22
- --tabs-text-muted: rgba(15, 15, 15, 0.8);
23
- --tabs-text-active: #0f0f0f;
24
- --tabs-bar-bg: #f1f1f1;
25
- --tabs-pill-bg: #ffffff;
26
- }
27
-
28
- /* The bar is just a flex container with padding for the pill
29
- to sit inside. Tabs sit on z-index: 1, the pill on z-index: 0,
30
- so labels read above the pill background. */
31
- .t-tabs {
32
- position: relative;
33
- display: inline-flex;
34
- align-items: center;
35
- gap: 3px;
36
- padding: 3px;
37
- border-radius: 48px;
38
- background: var(--tabs-bar-bg);
39
- }
40
- .t-tab {
41
- position: relative;
42
- appearance: none;
43
- border: 0;
44
- background: transparent;
45
- height: 30px;
46
- padding: 4px 12px;
47
- color: var(--tabs-text-muted);
48
- cursor: pointer;
49
- border-radius: 48px;
50
- z-index: 1;
51
- transition: color var(--tabs-dur) var(--tabs-ease);
52
- }
53
- .t-tab:not([aria-selected="true"]):hover,
54
- .t-tab[aria-selected="true"] {
55
- color: var(--tabs-text-active);
56
- }
57
-
58
- /* The pill: width + transform are written inline by JS so the
59
- transition tweens between the previous and next measured
60
- positions. */
61
- .t-tabs-pill {
62
- position: absolute;
63
- top: 3px;
64
- left: 0;
65
- height: 30px;
66
- width: 0;
67
- background: var(--tabs-pill-bg);
68
- border-radius: 48px;
69
- transform: translateX(0);
70
- transition:
71
- transform var(--tabs-dur) var(--tabs-ease),
72
- width var(--tabs-dur) var(--tabs-ease);
73
- will-change: transform, width;
74
- z-index: 0;
75
- pointer-events: none;
76
- }
77
-
78
- @media (prefers-reduced-motion: reduce) {
79
- .t-tabs-pill,
80
- .t-tab {
81
- transition: none !important;
82
- }
83
- }