fancy-ui-svelte 0.7.0 → 0.9.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 (58) hide show
  1. package/README.md +107 -81
  2. package/dist/fancy-ui/animated-testimonials/README.md +44 -0
  3. package/dist/fancy-ui/animated-tooltip/README.md +40 -0
  4. package/dist/fancy-ui/apple-card-carousel/README.md +46 -0
  5. package/dist/fancy-ui/bento-grid/BentoGrid.test.d.ts +1 -0
  6. package/dist/fancy-ui/bento-grid/BentoGrid.test.js +109 -0
  7. package/dist/fancy-ui/border-beam/README.md +37 -0
  8. package/dist/fancy-ui/card-3d/CardContainer.test.d.ts +1 -0
  9. package/dist/fancy-ui/card-3d/CardContainer.test.js +118 -0
  10. package/dist/fancy-ui/card-spotlight/CardSpotlight.test.d.ts +1 -0
  11. package/dist/fancy-ui/card-spotlight/CardSpotlight.test.js +58 -0
  12. package/dist/fancy-ui/displacement-text/README.md +39 -0
  13. package/dist/fancy-ui/dock/README.md +1 -1
  14. package/dist/fancy-ui/editorial-engine/EditorialEngine.test.d.ts +1 -0
  15. package/dist/fancy-ui/editorial-engine/EditorialEngine.test.js +54 -0
  16. package/dist/fancy-ui/fluid-cursor/FluidCursor.svelte +1250 -1108
  17. package/dist/fancy-ui/fluid-cursor/FluidCursor.svelte.d.ts +11 -5
  18. package/dist/fancy-ui/fluid-cursor/FluidCursor.test.js +48 -0
  19. package/dist/fancy-ui/fluid-cursor/README.md +57 -6
  20. package/dist/fancy-ui/fluid-cursor/fluid-shared.d.ts +72 -0
  21. package/dist/fancy-ui/fluid-cursor/fluid-shared.js +125 -0
  22. package/dist/fancy-ui/fluid-cursor/fluid-shared.test.d.ts +1 -0
  23. package/dist/fancy-ui/fluid-cursor/fluid-shared.test.js +39 -0
  24. package/dist/fancy-ui/fluid-cursor/index.d.ts +1 -0
  25. package/dist/fancy-ui/fluid-cursor/webgpu-engine.d.ts +36 -0
  26. package/dist/fancy-ui/fluid-cursor/webgpu-engine.js +926 -0
  27. package/dist/fancy-ui/frosted-glass/FrostedGlass.svelte +5 -3
  28. package/dist/fancy-ui/frosted-glass/README.md +4 -2
  29. package/dist/fancy-ui/index.d.ts +1 -0
  30. package/dist/fancy-ui/index.js +1 -0
  31. package/dist/fancy-ui/line-hover-link/README.md +37 -0
  32. package/dist/fancy-ui/line-reveal/LineReveal.test.d.ts +1 -0
  33. package/dist/fancy-ui/line-reveal/LineReveal.test.js +77 -0
  34. package/dist/fancy-ui/liquid-glass/LiquidGlass.svelte +19 -2
  35. package/dist/fancy-ui/liquid-glass/LiquidGlass.svelte.d.ts +4 -0
  36. package/dist/fancy-ui/liquid-glass/LiquidGlass.test.js +14 -0
  37. package/dist/fancy-ui/liquid-glass/README.md +7 -1
  38. package/dist/fancy-ui/liquid-text/LiquidText.svelte +1151 -0
  39. package/dist/fancy-ui/liquid-text/LiquidText.svelte.d.ts +37 -0
  40. package/dist/fancy-ui/liquid-text/LiquidText.test.d.ts +1 -0
  41. package/dist/fancy-ui/liquid-text/LiquidText.test.js +219 -0
  42. package/dist/fancy-ui/liquid-text/README.md +139 -0
  43. package/dist/fancy-ui/liquid-text/index.d.ts +2 -0
  44. package/dist/fancy-ui/liquid-text/index.js +1 -0
  45. package/dist/fancy-ui/marquee/README.md +57 -0
  46. package/dist/fancy-ui/matrix-rain/MatrixRain.test.d.ts +1 -0
  47. package/dist/fancy-ui/matrix-rain/MatrixRain.test.js +30 -0
  48. package/dist/fancy-ui/matrix-rain/README.md +42 -0
  49. package/dist/fancy-ui/noise-reveal/README.md +52 -0
  50. package/dist/fancy-ui/rainbow-button/README.md +36 -0
  51. package/dist/fancy-ui/registry.js +144 -20
  52. package/dist/fancy-ui/ripple-button/README.md +36 -0
  53. package/dist/fancy-ui/smooth-cursor/SmoothCursor.test.d.ts +1 -0
  54. package/dist/fancy-ui/smooth-cursor/SmoothCursor.test.js +45 -0
  55. package/dist/fancy-ui/terminal-text/README.md +48 -0
  56. package/dist/fancy-ui/terminal-text/TerminalText.test.d.ts +1 -0
  57. package/dist/fancy-ui/terminal-text/TerminalText.test.js +88 -0
  58. package/package.json +18 -4
package/README.md CHANGED
@@ -5,12 +5,21 @@ Beautiful animation and UI components for **Svelte 5**.
5
5
  ![Svelte 5](https://img.shields.io/badge/Svelte-5-FF3E00?logo=svelte&logoColor=white)
6
6
  ![Tailwind CSS](https://img.shields.io/badge/Tailwind_CSS-4-06B6D4?logo=tailwindcss&logoColor=white)
7
7
  ![TypeScript](https://img.shields.io/badge/TypeScript-5-3178C6?logo=typescript&logoColor=white)
8
- ![Components](https://img.shields.io/badge/Components-56-8B5CF6)
8
+ ![Components](https://img.shields.io/badge/Components-61-8B5CF6)
9
9
  ![MIT License](https://img.shields.io/badge/License-MIT-green)
10
10
 
11
+ <p align="center">
12
+ <a href="https://www.anthropic.com/claude-code">
13
+ <picture>
14
+ <source media="(prefers-color-scheme: dark)" srcset=".github/claude-for-open-source-program-dark.svg">
15
+ <img src=".github/claude-for-open-source-program.svg" alt="Claude for Open Source Program" width="280">
16
+ </picture>
17
+ </a>
18
+ </p>
19
+
11
20
  <p align="center">
12
21
  <a href="https://fancy-ui.rama.app">
13
- <img src=".github/demo-gallery.png" alt="fancy-ui demo gallery" width="800" />
22
+ <img src=".github/fancyui-readme.png" alt="FancyUI preview" width="800" />
14
23
  </a>
15
24
  </p>
16
25
 
@@ -23,96 +32,107 @@ Beautiful animation and UI components for **Svelte 5**.
23
32
  - **Svelte 5 Runes** &mdash; Built with `$state`, `$derived`, `$effect`, and `$props`
24
33
  - **Tailwind CSS 4** &mdash; Utility-first styling with theme tokens
25
34
  - **TypeScript** &mdash; Fully typed props and events
26
- - **56 Components** &mdash; Buttons, text animations, backgrounds, effects, and more
35
+ - **61 Components** &mdash; Buttons, text animations, backgrounds, effects, and more
27
36
  - **Dark Mode** &mdash; All components support light and dark themes
28
- - **Tested** &mdash; Component tests with Vitest and Testing Library
37
+ - **Tested** &mdash; 600+ unit tests with Vitest and Testing Library
29
38
 
30
39
  ## Components
31
40
 
32
41
  ### Buttons
33
42
 
34
- | Component | Description | Demo |
35
- | ---------------------- | ---------------------------------------- | --------------------------------------------------------------- |
36
- | RainbowButton | Animated rainbow gradient border effect | [Demo](https://fancy-ui.rama.app/demo/rainbow-button) |
37
- | RippleButton | Ripple click effect | [Demo](https://fancy-ui.rama.app/demo/ripple-button) |
38
- | ShimmerButton | Rotating conic-gradient shimmer border | [Demo](https://fancy-ui.rama.app/demo/shimmer-button) |
39
- | GradientButton | Rotating conic-gradient rainbow border | [Demo](https://fancy-ui.rama.app/demo/gradient-button) |
40
- | InteractiveHoverButton | Hover effect revealing alternate content | [Demo](https://fancy-ui.rama.app/demo/interactive-hover-button) |
43
+ | Component | Description | Demo |
44
+ | ---------------------- | ---------------------------------------- | -------------------------------------------------------------------------- |
45
+ | RainbowButton | Animated rainbow gradient border effect | [Demo](https://fancy-ui.rama.app/docs/components/rainbow-button) |
46
+ | RippleButton | Ripple click effect | [Demo](https://fancy-ui.rama.app/docs/components/ripple-button) |
47
+ | ShimmerButton | Rotating conic-gradient shimmer border | [Demo](https://fancy-ui.rama.app/docs/components/shimmer-button) |
48
+ | GradientButton | Rotating conic-gradient rainbow border | [Demo](https://fancy-ui.rama.app/docs/components/gradient-button) |
49
+ | InteractiveHoverButton | Hover effect revealing alternate content | [Demo](https://fancy-ui.rama.app/docs/components/interactive-hover-button) |
41
50
 
42
51
  ### Cards
43
52
 
44
- | Component | Description | Demo |
45
- | ------------------- | -------------------------------------------- | ------------------------------------------------------------ |
46
- | Card3D | 3D tilt card with mouse tracking | [Demo](https://fancy-ui.rama.app/demo/card-3d) |
47
- | CardSpotlight | Spotlight effect following mouse | [Demo](https://fancy-ui.rama.app/demo/card-spotlight) |
48
- | DirectionAwareHover | Overlay slides in from mouse entry direction | [Demo](https://fancy-ui.rama.app/demo/direction-aware-hover) |
49
- | FlipCard | Two-sided card with flip animation | [Demo](https://fancy-ui.rama.app/demo/flip-card) |
50
- | GlareCard | Glare reflection effect on hover | [Demo](https://fancy-ui.rama.app/demo/glare-card) |
51
- | TextRevealCard | Text reveal on hover | [Demo](https://fancy-ui.rama.app/demo/text-reveal-card) |
53
+ | Component | Description | Demo |
54
+ | ------------------- | ------------------------------------------------------------------- | ----------------------------------------------------------------------- |
55
+ | AppleCardCarousel | Horizontal card carousel with spring-animated full-screen expansion | [Demo](https://fancy-ui.rama.app/docs/components/apple-card-carousel) |
56
+ | Card3D | 3D tilt card with mouse tracking | [Demo](https://fancy-ui.rama.app/docs/components/card-3d) |
57
+ | CardSpotlight | Spotlight effect following mouse | [Demo](https://fancy-ui.rama.app/docs/components/card-spotlight) |
58
+ | DirectionAwareHover | Overlay slides in from mouse entry direction | [Demo](https://fancy-ui.rama.app/docs/components/direction-aware-hover) |
59
+ | FlipCard | Two-sided card with flip animation | [Demo](https://fancy-ui.rama.app/docs/components/flip-card) |
60
+ | GlareCard | Glare reflection effect on hover | [Demo](https://fancy-ui.rama.app/docs/components/glare-card) |
61
+ | TextRevealCard | Text reveal on hover | [Demo](https://fancy-ui.rama.app/docs/components/text-reveal-card) |
52
62
 
53
63
  ### Text & Typography
54
64
 
55
- | Component | Description | Demo |
56
- | ------------------ | ---------------------------------------------- | ----------------------------------------------------------- |
57
- | BlurReveal | Scroll-triggered blur-to-clear reveal | [Demo](https://fancy-ui.rama.app/demo/blur-reveal) |
58
- | BoxReveal | Sliding colored box reveal animation | [Demo](https://fancy-ui.rama.app/demo/box-reveal) |
59
- | ColourfulText | Per-character color animation | [Demo](https://fancy-ui.rama.app/demo/colourful-text) |
60
- | ContainerTextFlip | Text flipping inside a container | [Demo](https://fancy-ui.rama.app/demo/container-text-flip) |
61
- | FlipWords | Cycling word animation with per-letter effects | [Demo](https://fancy-ui.rama.app/demo/flip-words) |
62
- | HyperText | Character scramble on hover | [Demo](https://fancy-ui.rama.app/demo/hyper-text) |
63
- | LetterPullup | Staggered letter pull-up animation | [Demo](https://fancy-ui.rama.app/demo/letter-pullup) |
64
- | LineShadowText | Text with animated line shadow | [Demo](https://fancy-ui.rama.app/demo/line-shadow-text) |
65
- | NumberTicker | Animated number counter with easing | [Demo](https://fancy-ui.rama.app/demo/number-ticker) |
66
- | SparklesText | Animated SVG sparkle stars overlay | [Demo](https://fancy-ui.rama.app/demo/sparkles-text) |
67
- | TextGenerateEffect | Word-by-word text generation effect | [Demo](https://fancy-ui.rama.app/demo/text-generate-effect) |
65
+ | Component | Description | Demo |
66
+ | ------------------ | ------------------------------------------------------------------------------ | ---------------------------------------------------------------------- |
67
+ | BlurReveal | Scroll-triggered blur-to-clear reveal | [Demo](https://fancy-ui.rama.app/docs/components/blur-reveal) |
68
+ | BoxReveal | Sliding colored box reveal animation | [Demo](https://fancy-ui.rama.app/docs/components/box-reveal) |
69
+ | ColourfulText | Per-character color animation | [Demo](https://fancy-ui.rama.app/docs/components/colourful-text) |
70
+ | ContainerTextFlip | Text flipping inside a container | [Demo](https://fancy-ui.rama.app/docs/components/container-text-flip) |
71
+ | DisplacementText | 3D text with WebGL displacement that follows the cursor using Three.js shaders | [Demo](https://fancy-ui.rama.app/docs/components/displacement-text) |
72
+ | EditorialEngine | Live magazine layout with multi-column text flowing around draggable orbs | [Demo](https://fancy-ui.rama.app/docs/components/editorial-engine) |
73
+ | FlipWords | Cycling word animation with per-letter effects | [Demo](https://fancy-ui.rama.app/docs/components/flip-words) |
74
+ | HyperText | Character scramble on hover | [Demo](https://fancy-ui.rama.app/docs/components/hyper-text) |
75
+ | LetterPullup | Staggered letter pull-up animation | [Demo](https://fancy-ui.rama.app/docs/components/letter-pullup) |
76
+ | LineReveal | Staggered line-by-line text reveal | [Demo](https://fancy-ui.rama.app/docs/components/line-reveal) |
77
+ | LineShadowText | Text with animated line shadow | [Demo](https://fancy-ui.rama.app/docs/components/line-shadow-text) |
78
+ | LiquidText | Big text that liquefies along the cursor's path via a WebGL fluid solver | [Demo](https://fancy-ui.rama.app/docs/components/liquid-text) |
79
+ | NumberTicker | Animated number counter with easing | [Demo](https://fancy-ui.rama.app/docs/components/number-ticker) |
80
+ | SparklesText | Animated SVG sparkle stars overlay | [Demo](https://fancy-ui.rama.app/docs/components/sparkles-text) |
81
+ | TerminalText | Terminal-style text streamer with blinking cursor and glitch effect | [Demo](https://fancy-ui.rama.app/docs/components/terminal-text) |
82
+ | TextGenerateEffect | Word-by-word text generation effect | [Demo](https://fancy-ui.rama.app/docs/components/text-generate-effect) |
68
83
 
69
84
  ### Backgrounds
70
85
 
71
- | Component | Description | Demo |
72
- | ---------------------- | -------------------------------------- | --------------------------------------------------------------- |
73
- | FallingStarsBg | Canvas 3D starfield with motion trails | [Demo](https://fancy-ui.rama.app/demo/bg-falling-stars) |
74
- | FlickeringGrid | Canvas grid with flickering opacity | [Demo](https://fancy-ui.rama.app/demo/flickering-grid) |
75
- | InteractiveGridPattern | SVG grid with hover highlights | [Demo](https://fancy-ui.rama.app/demo/interactive-grid-pattern) |
76
- | StarsBackground | Starfield with parallax mouse tracking | [Demo](https://fancy-ui.rama.app/demo/bg-stars) |
86
+ | Component | Description | Demo |
87
+ | ---------------------- | --------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
88
+ | FallingStarsBg | Canvas 3D starfield with motion trails | [Demo](https://fancy-ui.rama.app/docs/components/bg-falling-stars) |
89
+ | FlickeringGrid | Canvas grid with flickering opacity | [Demo](https://fancy-ui.rama.app/docs/components/flickering-grid) |
90
+ | InteractiveGridPattern | SVG grid with hover highlights | [Demo](https://fancy-ui.rama.app/docs/components/interactive-grid-pattern) |
91
+ | MatrixRain | Canvas-based falling glyph rain with configurable color, speed, and density | [Demo](https://fancy-ui.rama.app/docs/components/matrix-rain) |
92
+ | StarsBackground | Starfield with parallax mouse tracking | [Demo](https://fancy-ui.rama.app/docs/components/bg-stars) |
77
93
 
78
94
  ### Effects & Animations
79
95
 
80
- | Component | Description | Demo |
81
- | ---------------- | ----------------------------------------- | --------------------------------------------------------- |
82
- | AnimatedBeam | SVG beams connecting elements | [Demo](https://fancy-ui.rama.app/demo/animated-beam) |
83
- | BorderBeam | Beam effect traveling around borders | [Demo](https://fancy-ui.rama.app/demo/border-beam) |
84
- | Confetti | Configurable confetti burst | [Demo](https://fancy-ui.rama.app/demo/confetti) |
85
- | FluidCursor | WebGL fluid simulation following cursor | [Demo](https://fancy-ui.rama.app/demo/fluid-cursor) |
86
- | GlowBorder | Animated glowing border with gradients | [Demo](https://fancy-ui.rama.app/demo/glow-border) |
87
- | GlowingEffect | Glowing highlight on hover | [Demo](https://fancy-ui.rama.app/demo/glowing-effect) |
88
- | ImageTrailCursor | Cursor-following image trail (8 variants) | [Demo](https://fancy-ui.rama.app/demo/image-trail-cursor) |
89
- | LiquidGlass | Liquid glass morphism effect | [Demo](https://fancy-ui.rama.app/demo/liquid-glass) |
90
- | Meteors | Animated meteor shower effect | [Demo](https://fancy-ui.rama.app/demo/meteors) |
91
- | NeonBorder | Dual-color neon glow border | [Demo](https://fancy-ui.rama.app/demo/neon-border) |
92
- | Ripple | Expanding ripple rings | [Demo](https://fancy-ui.rama.app/demo/ripple) |
93
- | SmoothCursor | Smooth lagging cursor follower | [Demo](https://fancy-ui.rama.app/demo/smooth-cursor) |
94
- | Sparkles | Particle sparkle canvas | [Demo](https://fancy-ui.rama.app/demo/sparkles) |
95
- | TracingBeam | Scroll-driven tracing beam | [Demo](https://fancy-ui.rama.app/demo/tracing-beam) |
96
+ | Component | Description | Demo |
97
+ | ---------------- | -------------------------------------------------------------- | -------------------------------------------------------------------- |
98
+ | AnimatedBeam | SVG beams connecting elements | [Demo](https://fancy-ui.rama.app/docs/components/animated-beam) |
99
+ | BorderBeam | Beam effect traveling around borders | [Demo](https://fancy-ui.rama.app/docs/components/border-beam) |
100
+ | Confetti | Configurable confetti burst | [Demo](https://fancy-ui.rama.app/docs/components/confetti) |
101
+ | FluidCursor | WebGL fluid simulation following cursor | [Demo](https://fancy-ui.rama.app/docs/components/fluid-cursor) |
102
+ | FrostedGlass | Frosted glass surface with organic turbulence-noise refraction | [Demo](https://fancy-ui.rama.app/docs/components/frosted-glass) |
103
+ | GlowBorder | Animated glowing border with gradients | [Demo](https://fancy-ui.rama.app/docs/components/glow-border) |
104
+ | GlowingEffect | Glowing highlight on hover | [Demo](https://fancy-ui.rama.app/docs/components/glowing-effect) |
105
+ | ImageTrailCursor | Cursor-following image trail (8 variants) | [Demo](https://fancy-ui.rama.app/docs/components/image-trail-cursor) |
106
+ | LiquidGlass | Liquid glass morphism effect | [Demo](https://fancy-ui.rama.app/docs/components/liquid-glass) |
107
+ | Meteors | Animated meteor shower effect | [Demo](https://fancy-ui.rama.app/docs/components/meteors) |
108
+ | NeonBorder | Dual-color neon glow border | [Demo](https://fancy-ui.rama.app/docs/components/neon-border) |
109
+ | Ripple | Expanding ripple rings | [Demo](https://fancy-ui.rama.app/docs/components/ripple) |
110
+ | SmoothCursor | Smooth lagging cursor follower | [Demo](https://fancy-ui.rama.app/docs/components/smooth-cursor) |
111
+ | Sparkles | Particle sparkle canvas | [Demo](https://fancy-ui.rama.app/docs/components/sparkles) |
112
+ | TracingBeam | Scroll-driven tracing beam | [Demo](https://fancy-ui.rama.app/docs/components/tracing-beam) |
96
113
 
97
114
  ### Layout
98
115
 
99
- | Component | Description | Demo |
100
- | --------------- | --------------------------------------------- | ------------------------------------------------------- |
101
- | BentoGrid | Bento-style responsive grid layout | [Demo](https://fancy-ui.rama.app/demo/bento-grid) |
102
- | Book | 3D book flip animation | [Demo](https://fancy-ui.rama.app/demo/book) |
103
- | ContainerScroll | 3D scroll perspective container | [Demo](https://fancy-ui.rama.app/demo/container-scroll) |
104
- | Focus | Focus-expand card layout | [Demo](https://fancy-ui.rama.app/demo/focus) |
105
- | Marquee | Infinite scrolling for text, images, or cards | [Demo](https://fancy-ui.rama.app/demo/marquee) |
116
+ | Component | Description | Demo |
117
+ | --------------- | --------------------------------------------- | ------------------------------------------------------------------ |
118
+ | BentoGrid | Bento-style responsive grid layout | [Demo](https://fancy-ui.rama.app/docs/components/bento-grid) |
119
+ | Book | 3D book flip animation | [Demo](https://fancy-ui.rama.app/docs/components/book) |
120
+ | ContainerScroll | 3D scroll perspective container | [Demo](https://fancy-ui.rama.app/docs/components/container-scroll) |
121
+ | Focus | Focus-expand card layout | [Demo](https://fancy-ui.rama.app/docs/components/focus) |
122
+ | Marquee | Infinite scrolling for text, images, or cards | [Demo](https://fancy-ui.rama.app/docs/components/marquee) |
106
123
 
107
124
  ### Navigation & Display
108
125
 
109
- | Component | Description | Demo |
110
- | --------------- | --------------------------------------------- | ------------------------------------------------------- |
111
- | AnimatedTooltip | Avatar row with mouse-following tooltips | [Demo](https://fancy-ui.rama.app/demo/animated-tooltip) |
112
- | Compare | Before/after image comparison slider | [Demo](https://fancy-ui.rama.app/demo/compare) |
113
- | Dock | macOS-style dock with icon magnification | [Demo](https://fancy-ui.rama.app/demo/dock) |
114
- | LogoCloud | Marquee, grid, and icon logo layouts | [Demo](https://fancy-ui.rama.app/demo/logo-cloud) |
115
- | Timeline | Vertical timeline with scroll-driven progress | [Demo](https://fancy-ui.rama.app/demo/timeline) |
126
+ | Component | Description | Demo |
127
+ | -------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------------------------- |
128
+ | AnimatedTestimonials | Testimonial carousel with smooth slide animations and optional autoplay | [Demo](https://fancy-ui.rama.app/docs/components/animated-testimonials) |
129
+ | AnimatedTooltip | Avatar row with mouse-following tooltips | [Demo](https://fancy-ui.rama.app/docs/components/animated-tooltip) |
130
+ | Compare | Before/after image comparison slider | [Demo](https://fancy-ui.rama.app/docs/components/compare) |
131
+ | Dock | Icon dock where items magnify as the cursor approaches | [Demo](https://fancy-ui.rama.app/docs/components/dock) |
132
+ | LineHoverLink | Link with 11 animated underline hover effects, pure CSS | [Demo](https://fancy-ui.rama.app/docs/components/line-hover-link) |
133
+ | LogoCloud | Marquee, grid, and icon logo layouts | [Demo](https://fancy-ui.rama.app/docs/components/logo-cloud) |
134
+ | NoiseReveal | WebGL image reveal with a Perlin-noise dissolve mask | [Demo](https://fancy-ui.rama.app/docs/components/noise-reveal) |
135
+ | Timeline | Vertical timeline with scroll-driven progress | [Demo](https://fancy-ui.rama.app/docs/components/timeline) |
116
136
 
117
137
  ## Quick Start
118
138
 
@@ -186,12 +206,14 @@ SmoothCursor) mount once in the root +layout.svelte; Svelte 5 syntax only.
186
206
  ## Development
187
207
 
188
208
  ```bash
189
- pnpm dev # Start dev server
190
- pnpm check # Run Svelte type checker
191
- pnpm test # Run tests
192
- pnpm test:watch # Run tests in watch mode
193
- pnpm build # Production build
194
- pnpm storybook # Component workshop on :6006
209
+ pnpm dev # Start dev server
210
+ pnpm check # Run Svelte type checker
211
+ pnpm check:registry # Verify component registry parity (CI gate)
212
+ pnpm check:i18n # Verify i18n message catalog parity (CI gate)
213
+ pnpm test # Run tests
214
+ pnpm test:watch # Run tests in watch mode
215
+ pnpm build # Production build
216
+ pnpm storybook # Component workshop on :6006
195
217
  ```
196
218
 
197
219
  Component stories live in `src/stories/` — see the [Storybook section in CONTRIBUTING.md](./CONTRIBUTING.md#storybook).
@@ -210,22 +232,26 @@ src/
210
232
  │ │ ├── registry.ts # Component registry & metadata
211
233
  │ │ └── index.ts # Barrel exports
212
234
  │ └── components/ui/ # shadcn-svelte primitives
213
- ├── routes/
214
- │ ├── +page.svelte # Home page
215
- │ └── demo/ # Component demo pages
216
- │ └── [component]/+page.svelte
217
- └── tests/
235
+ └── routes/
236
+ ├── +page.svelte # Home page
237
+ └── docs/ # Docs site (registry-driven component pages)
238
+ └── components/[slug]/+page.svelte
239
+
240
+ tests/
241
+ └── e2e/ # Playwright end-to-end tests
218
242
  ```
219
243
 
244
+ Component tests are colocated with their component (see `RainbowButton.test.ts` above); there is no separate top-level unit-test directory.
245
+
220
246
  ## Contributing
221
247
 
222
- Contributions are welcome! 56 components and counting — PRs for new components, bug fixes, and improvements are appreciated.
248
+ Contributions are welcome! 61 components and counting — PRs for new components, bug fixes, and improvements are appreciated.
223
249
 
224
250
  ### Adding a new component
225
251
 
226
252
  1. Create the component folder under `src/lib/fancy-ui/`
227
253
  2. Implement the component in idiomatic Svelte 5
228
- 3. Add a demo page at `src/routes/demo/[slug]/+page.svelte`
254
+ 3. Add a docs example under `src/lib/components/docs/examples/<slug>/` (`BasicUsage.svelte`)
229
255
  4. Register it in `src/lib/fancy-ui/registry.ts`
230
256
  5. Export it from `src/lib/fancy-ui/index.ts`
231
257
 
@@ -0,0 +1,44 @@
1
+ # AnimatedTestimonials
2
+
3
+ A testimonial carousel that cross-fades between quote/author pairs, with a matching stack of avatar images that slide and rotate in behind it. Supports manual prev/next navigation and optional autoplay that pauses on hover.
4
+
5
+ ## Usage
6
+
7
+ ```svelte
8
+ <script lang="ts">
9
+ import { AnimatedTestimonials } from "fancy-ui-svelte";
10
+ import type { Testimonial } from "fancy-ui-svelte";
11
+
12
+ const testimonials: Testimonial[] = [
13
+ {
14
+ quote:
15
+ "The attention to detail and innovative features have completely transformed our workflow.",
16
+ name: "Sarah Chen",
17
+ designation: "Product Manager at TechFlow",
18
+ src: "https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=500",
19
+ },
20
+ ];
21
+ </script>
22
+
23
+ <AnimatedTestimonials {testimonials} autoplay interval={4000} />
24
+ ```
25
+
26
+ ## Props
27
+
28
+ | Prop | Type | Default | Description |
29
+ | -------------- | --------------- | ------- | ------------------------------------------- |
30
+ | `testimonials` | `Testimonial[]` | — | Array of testimonials to display (required) |
31
+ | `autoplay` | `boolean` | `false` | Auto-advance testimonials |
32
+ | `interval` | `number` | `5000` | Interval between auto-advances (ms) |
33
+ | `class` | `string` | — | Additional CSS classes on the root |
34
+
35
+ `Testimonial` shape: `{ quote: string; name: string; designation: string; src: string }` — `src` is the author's avatar image URL.
36
+
37
+ ## Implementation notes
38
+
39
+ - `navigate()` is guarded by an `isAnimating` flag so rapid clicks or a running autoplay timer can't overlap two transitions; a new navigation is dropped, not queued, while one is in flight.
40
+ - Autoplay is a single `$effect` that starts a `setInterval` whenever `autoplay`, `interval`, or hover state changes, and returns its own cleanup — hovering the container (`onmouseenter`/`onmouseleave`) pauses it without a separate timer to manage.
41
+ - The image stack renders every testimonial absolutely-positioned and stacked (`z-20`/`z-10`), swapping visibility and transform per index rather than mounting/unmounting nodes — this is what makes the slide-in-behind effect possible without a Svelte transition.
42
+ - The image and text transition durations are both tied to the same `TRANSITION_DURATION` module constant (300ms); it isn't exposed as a prop, so it must be edited in the component source if a different pace is needed.
43
+ - Renders a "No testimonials available." message instead of the carousel when `testimonials` is empty, rather than crashing on an out-of-bounds `activeIndex`.
44
+ - No `prefers-reduced-motion` handling — the slide/scale/opacity transitions run regardless of user preference.
@@ -0,0 +1,40 @@
1
+ # AnimatedTooltip
2
+
3
+ A row of overlapping avatars that pop a name/role tooltip above the hovered item. The tooltip tilts and shifts horizontally based on where the cursor is over the avatar, giving it a light spring-like feel without a physics library.
4
+
5
+ ## Usage
6
+
7
+ ```svelte
8
+ <script lang="ts">
9
+ import { AnimatedTooltip } from "fancy-ui-svelte";
10
+ import type { TooltipItem } from "fancy-ui-svelte";
11
+
12
+ const people: TooltipItem[] = [
13
+ {
14
+ id: 1,
15
+ name: "John Doe",
16
+ designation: "Software Engineer",
17
+ image: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=100&h=100&fit=crop",
18
+ },
19
+ ];
20
+ </script>
21
+
22
+ <AnimatedTooltip items={people} />
23
+ ```
24
+
25
+ ## Props
26
+
27
+ | Prop | Type | Default | Description |
28
+ | ------- | --------------- | ------- | --------------------------------------- |
29
+ | `items` | `TooltipItem[]` | — | Array of items to display (required) |
30
+ | `class` | `string` | — | Additional CSS classes on the container |
31
+
32
+ `TooltipItem` shape: `{ id: number | string; name: string; designation: string; image: string }`.
33
+
34
+ ## Implementation notes
35
+
36
+ - Rotation and horizontal translation are both derived from the same value: `mouseX`, the pointer's offset from the hovered avatar's horizontal center, scaled by `/100 * 50`. One `$derived` value drives both the `rotate()` and the `translateX()` in the tooltip's inline `style`.
37
+ - `mouseX` is recalculated from scratch on `mouseenter` (not carried over from the previous avatar) to avoid a jump when the pointer moves between adjacent, overlapping avatars.
38
+ - The tooltip is conditionally rendered (`{#if hoveredIndex === item.id}`) rather than always mounted and toggled with opacity, so it uses Svelte's `transition:scale` (200ms, `start: 0.6`) on enter/exit instead of a CSS-only transition.
39
+ - Avatars overlap via a `-mr-4` negative margin on each item and `group-hover:z-30`/`scale-105` to lift the hovered one above its neighbors.
40
+ - No `prefers-reduced-motion` handling — the scale transition and position/rotation tracking run regardless of user preference.
@@ -0,0 +1,46 @@
1
+ # AppleCardCarousel
2
+
3
+ A horizontally scroll-snapping card carousel where tapping a card grows it from its on-screen position into a full-screen modal, then shrinks it back to that same spot on close — the geometry is measured, not animated between two fixed states.
4
+
5
+ ## Usage
6
+
7
+ ```svelte
8
+ <script lang="ts">
9
+ import { AppleCardCarousel } from "fancy-ui-svelte";
10
+ import type { AppleCardData } from "fancy-ui-svelte";
11
+
12
+ const cards: AppleCardData[] = [
13
+ {
14
+ category: "Nature",
15
+ title: "Misty Mountains",
16
+ src: "https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=800",
17
+ description: "A breathtaking view of misty mountains at dawn.",
18
+ },
19
+ ];
20
+ </script>
21
+
22
+ <AppleCardCarousel {cards} />
23
+ ```
24
+
25
+ ## Props
26
+
27
+ ### AppleCardCarousel
28
+
29
+ | Prop | Type | Default | Description |
30
+ | ------- | ----------------- | ------- | ---------------------------------- |
31
+ | `cards` | `AppleCardData[]` | — | Cards to display (required) |
32
+ | `class` | `string` | `""` | Additional CSS classes on the root |
33
+
34
+ `AppleCardData` shape: `{ category: string; title: string; src: string; description?: string; content?: Snippet }`. `content`, when provided, replaces `description` in the expanded view — pass a Svelte snippet for rich content (headings, lists, embedded components) instead of a plain paragraph.
35
+
36
+ `AppleCard` is also exported directly (`import { AppleCard } from "fancy-ui-svelte"`) for building a custom carousel shell around the individual expand/collapse card, but its own prop interface is internal to the component and not re-exported as a named type.
37
+
38
+ ## Implementation notes
39
+
40
+ - Only one card can be expanded at a time: `expandedIndex` lives in `AppleCardCarousel` (not in each `AppleCard`) and is passed down along with `onExpand`/`onCollapse` callbacks, so a card whose `handleExpand()` fires while another is already open is a no-op (`if (expandedIndex !== -1) return`).
41
+ - The expand animation is a FLIP-style measure-then-morph: on click, `AppleCard` reads the collapsed card's `getBoundingClientRect()` and freezes it as the overlay's starting `top`/`left`/`width`/`height`, then flips a `fullyExpanded` flag (via a double `requestAnimationFrame` to guarantee a layout pass) that CSS-transitions those same properties to full-viewport.
42
+ - `prefers-reduced-motion` is detected once via `matchMedia` in `AppleCardCarousel` (with a `change` listener, so it updates if the user flips the OS setting mid-session) and passed down as `reducedMotion`. When true, `AppleCard` skips the double-rAF and the geometry transition duration drops to `0`.
43
+ - Focus management: opening a card saves `document.activeElement`, moves focus to the modal's close button, and traps `Tab`/`Shift+Tab` inside the dialog by walking its focusable elements; closing restores focus to whatever had it before.
44
+ - `Escape` closes the expanded card from anywhere inside the dialog (`onkeydown` on the dialog root).
45
+ - Collapse is deferred: the overlay stays mounted for `TRANSITION_MS` (400ms, or `0` under reduced motion) after `fullyExpanded` flips back to `false`, so the shrink transition can play before the DOM node is removed and `onCollapse` fires.
46
+ - The carousel track uses native scroll-snap (`snap-x snap-mandatory`) with the scrollbar hidden via `[scrollbar-width:none]` / `[&::-webkit-scrollbar]:hidden`, not a JS-driven scroller.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,109 @@
1
+ import { render, cleanup } from "@testing-library/svelte";
2
+ import { createRawSnippet } from "svelte";
3
+ import { afterEach, describe, it, expect } from "vitest";
4
+ import BentoGrid from "./BentoGrid.svelte";
5
+ import BentoGridItem from "./BentoGridItem.svelte";
6
+ import BentoGridCard from "./BentoGridCard.svelte";
7
+ function textSnippet(html) {
8
+ return createRawSnippet(() => ({ render: () => html }));
9
+ }
10
+ describe("BentoGrid", () => {
11
+ afterEach(cleanup);
12
+ it("renders a grid wrapper with the expected layout classes", () => {
13
+ const { container } = render(BentoGrid);
14
+ const grid = container.firstElementChild;
15
+ expect(grid.className).toContain("grid");
16
+ expect(grid.className).toContain("md:grid-cols-3");
17
+ });
18
+ it("applies custom class names alongside the base layout classes", () => {
19
+ const { container } = render(BentoGrid, { props: { class: "my-grid" } });
20
+ const grid = container.firstElementChild;
21
+ expect(grid.className).toContain("my-grid");
22
+ expect(grid.className).toContain("grid");
23
+ });
24
+ it("renders children content passed via the default snippet", () => {
25
+ const { container } = render(BentoGrid, {
26
+ props: { children: textSnippet("<span data-testid='child'>card</span>") },
27
+ });
28
+ expect(container.querySelector("[data-testid='child']")?.textContent).toBe("card");
29
+ });
30
+ });
31
+ describe("BentoGridItem", () => {
32
+ afterEach(cleanup);
33
+ it("renders with the base bento-card classes", () => {
34
+ const { container } = render(BentoGridItem);
35
+ const item = container.firstElementChild;
36
+ expect(item.className).toContain("group/bento");
37
+ expect(item.className).toContain("rounded-xl");
38
+ });
39
+ it("applies custom class names", () => {
40
+ const { container } = render(BentoGridItem, { props: { class: "my-item" } });
41
+ const item = container.firstElementChild;
42
+ expect(item.className).toContain("my-item");
43
+ });
44
+ it("renders the title snippet", () => {
45
+ const { container } = render(BentoGridItem, {
46
+ props: { title: textSnippet("<span>Widget title</span>") },
47
+ });
48
+ expect(container.textContent).toContain("Widget title");
49
+ });
50
+ it("renders the description snippet", () => {
51
+ const { container } = render(BentoGridItem, {
52
+ props: { description: textSnippet("<span>Widget description</span>") },
53
+ });
54
+ expect(container.textContent).toContain("Widget description");
55
+ });
56
+ it("renders the header and icon snippets", () => {
57
+ const { container } = render(BentoGridItem, {
58
+ props: {
59
+ header: textSnippet("<div data-testid='header'>H</div>"),
60
+ icon: textSnippet("<svg data-testid='icon'></svg>"),
61
+ },
62
+ });
63
+ expect(container.querySelector("[data-testid='header']")).toBeTruthy();
64
+ expect(container.querySelector("[data-testid='icon']")).toBeTruthy();
65
+ });
66
+ it("omits the title/description wrappers when those snippets are not provided", () => {
67
+ const { container } = render(BentoGridItem);
68
+ // Only the outer card and the inner hover-translate wrapper should exist.
69
+ expect(container.querySelectorAll("div").length).toBe(2);
70
+ });
71
+ });
72
+ describe("BentoGridCard", () => {
73
+ afterEach(cleanup);
74
+ const baseProps = {
75
+ name: "Feature",
76
+ description: "Does a thing",
77
+ href: "/feature",
78
+ cta: "Learn more",
79
+ };
80
+ it("renders the name, description, and cta link", () => {
81
+ const { container } = render(BentoGridCard, { props: baseProps });
82
+ const heading = container.querySelector("h3");
83
+ const desc = container.querySelector("p");
84
+ const link = container.querySelector("a");
85
+ expect(heading?.textContent?.trim()).toBe("Feature");
86
+ expect(desc?.textContent).toBe("Does a thing");
87
+ expect(link.getAttribute("href")).toBe("/feature");
88
+ expect(link.textContent).toContain("Learn more");
89
+ });
90
+ it("applies custom class names", () => {
91
+ const { container } = render(BentoGridCard, {
92
+ props: { ...baseProps, class: "my-card" },
93
+ });
94
+ const card = container.firstElementChild;
95
+ expect(card.className).toContain("my-card");
96
+ });
97
+ it("renders an icon snippet when provided", () => {
98
+ const { container } = render(BentoGridCard, {
99
+ props: { ...baseProps, icon: textSnippet("<svg data-testid='icon'></svg>") },
100
+ });
101
+ expect(container.querySelector("[data-testid='icon']")).toBeTruthy();
102
+ });
103
+ it("renders a background snippet when provided", () => {
104
+ const { container } = render(BentoGridCard, {
105
+ props: { ...baseProps, background: textSnippet("<div data-testid='bg'></div>") },
106
+ });
107
+ expect(container.querySelector("[data-testid='bg']")).toBeTruthy();
108
+ });
109
+ });
@@ -0,0 +1,37 @@
1
+ # BorderBeam
2
+
3
+ An animated light beam that travels around a container's border using a CSS `offset-path` motion path — no JS, no SVG. Place it inside a `position: relative; overflow: hidden` container; it renders as an absolutely-positioned overlay that traces the container's edge.
4
+
5
+ ## Usage
6
+
7
+ ```svelte
8
+ <script lang="ts">
9
+ import { BorderBeam } from "fancy-ui-svelte";
10
+ </script>
11
+
12
+ <div class="relative overflow-hidden rounded-xl border p-6">
13
+ <p>Content goes here</p>
14
+ <BorderBeam />
15
+ </div>
16
+ ```
17
+
18
+ Multiple beams can be layered in the same container (e.g. different `duration`/`delay`/colors per beam) for a multi-beam effect — see the `MultipleBeams` docs example.
19
+
20
+ ## Props
21
+
22
+ | Prop | Type | Default | Description |
23
+ | ------------- | -------- | ----------- | --------------------------------------------- |
24
+ | `size` | `number` | `200` | Size of the beam in pixels |
25
+ | `duration` | `number` | `15` | Animation duration in seconds |
26
+ | `borderWidth` | `number` | `1.5` | Border width in pixels |
27
+ | `anchor` | `number` | `90` | Anchor position along the offset path (0–100) |
28
+ | `colorFrom` | `string` | `"#ffaa40"` | Gradient start color |
29
+ | `colorTo` | `string` | `"#9c40ff"` | Gradient end color |
30
+ | `delay` | `number` | `0` | Animation delay in seconds |
31
+ | `class` | `string` | — | Additional CSS classes |
32
+
33
+ ## Implementation notes
34
+
35
+ - Every prop is a CSS custom property (`--border-beam-*`) written into the root `<div>`'s inline `style` via a single `$derived` string — the component holds no other reactive state, and the animation itself runs entirely in a scoped `<style>` block (`@keyframes border-beam-animation`, driven by `offset-distance`).
36
+ - The border itself is drawn with a transparent border plus a two-layer `mask` (`linear-gradient(transparent,transparent), linear-gradient(white,white)`) and `mask-composite: intersect`, so only the ring where the border would be is visible — the beam element's `::after` pseudo-element is what actually moves, via `offset-path: rect(...)` sized from `--border-beam-size`.
37
+ - No `prefers-reduced-motion` handling — the beam animates continuously (`infinite linear`) regardless of user preference.
@@ -0,0 +1 @@
1
+ export {};