fancy-ui-svelte 0.6.0 → 0.7.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.
package/README.md CHANGED
@@ -31,88 +31,88 @@ Beautiful animation and UI components for **Svelte 5**.
31
31
 
32
32
  ### Buttons
33
33
 
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) |
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
40
  | InteractiveHoverButton | Hover effect revealing alternate content | [Demo](https://fancy-ui.rama.app/demo/interactive-hover-button) |
41
41
 
42
42
  ### Cards
43
43
 
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) |
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
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) |
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) |
52
52
 
53
53
  ### Text & Typography
54
54
 
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) |
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) |
68
68
 
69
69
  ### Backgrounds
70
70
 
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) |
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) |
77
77
 
78
78
  ### Effects & Animations
79
79
 
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) |
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
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) |
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
96
 
97
97
  ### Layout
98
98
 
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) |
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) |
106
106
 
107
107
  ### Navigation & Display
108
108
 
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) |
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) |
116
116
 
117
117
  ## Quick Start
118
118
 
@@ -125,7 +125,7 @@ npm install fancy-ui-svelte
125
125
  Then import any component:
126
126
 
127
127
  ```ts
128
- import { Marquee, BorderBeam, Confetti } from 'fancy-ui-svelte';
128
+ import { Marquee, BorderBeam, Confetti } from "fancy-ui-svelte";
129
129
  ```
130
130
 
131
131
  Add the Tailwind integration to your app's CSS (e.g. `src/app.css`):
@@ -146,9 +146,11 @@ This single import tells Tailwind v4 to scan the library's components so all uti
146
146
  ```
147
147
 
148
148
  The path is relative to your CSS file location.
149
+
149
150
  </details>
150
151
 
151
152
  **Or browse and copy a component:**
153
+
152
154
  1. Find the component you need in the [live demo](https://fancy-ui.rama.app)
153
155
  2. Copy the source from `src/lib/fancy-ui/[component-name]/`
154
156
  3. Paste into your project
@@ -189,8 +191,11 @@ pnpm check # Run Svelte type checker
189
191
  pnpm test # Run tests
190
192
  pnpm test:watch # Run tests in watch mode
191
193
  pnpm build # Production build
194
+ pnpm storybook # Component workshop on :6006
192
195
  ```
193
196
 
197
+ Component stories live in `src/stories/` — see the [Storybook section in CONTRIBUTING.md](./CONTRIBUTING.md#storybook).
198
+
194
199
  ## Project Structure
195
200
 
196
201
  ```
@@ -226,15 +231,15 @@ Contributions are welcome! 56 components and counting — PRs for new components
226
231
 
227
232
  ## Tech Stack
228
233
 
229
- | Technology | Version | Purpose |
230
- |------------|---------|---------|
231
- | [Svelte](https://svelte.dev) | 5 | UI framework |
232
- | [SvelteKit](https://svelte.dev/docs/kit) | 2 | App framework |
233
- | [Tailwind CSS](https://tailwindcss.com) | 4 | Styling |
234
- | [TypeScript](https://www.typescriptlang.org) | 5 | Type safety |
235
- | [Vitest](https://vitest.dev) | 4 | Testing |
236
- | [bits-ui](https://bits-ui.com) | 2 | Headless primitives |
237
- | [GSAP](https://gsap.com) | 3 | Advanced animations |
234
+ | Technology | Version | Purpose |
235
+ | -------------------------------------------- | ------- | ------------------- |
236
+ | [Svelte](https://svelte.dev) | 5 | UI framework |
237
+ | [SvelteKit](https://svelte.dev/docs/kit) | 2 | App framework |
238
+ | [Tailwind CSS](https://tailwindcss.com) | 4 | Styling |
239
+ | [TypeScript](https://www.typescriptlang.org) | 5 | Type safety |
240
+ | [Vitest](https://vitest.dev) | 4 | Testing |
241
+ | [bits-ui](https://bits-ui.com) | 2 | Headless primitives |
242
+ | [GSAP](https://gsap.com) | 3 | Advanced animations |
238
243
 
239
244
  ## Credits
240
245
 
@@ -0,0 +1,202 @@
1
+ <script lang="ts">
2
+ import { cn } from "../../utils";
3
+ import { onMount } from "svelte";
4
+ import type { Snippet } from "svelte";
5
+
6
+ interface Props {
7
+ radius?: number;
8
+ baseFrequency?: number;
9
+ numOctaves?: number;
10
+ seed?: number;
11
+ noiseBlur?: number;
12
+ scale?: number;
13
+ tint?: string;
14
+ highlight?: string;
15
+ border?: boolean;
16
+ fallbackBlur?: number;
17
+ fallbackSaturation?: number;
18
+ class?: string;
19
+ containerClass?: string;
20
+ children?: Snippet;
21
+ }
22
+
23
+ let {
24
+ radius = 24,
25
+ baseFrequency = 0.008,
26
+ numOctaves = 2,
27
+ seed = 92,
28
+ noiseBlur = 2,
29
+ scale = 70,
30
+ tint = "hsla(0, 0%, 100%, 0.25)",
31
+ highlight = "hsla(0, 0%, 100%, 0.75)",
32
+ border = true,
33
+ fallbackBlur = 20,
34
+ fallbackSaturation = 180,
35
+ class: className = "",
36
+ containerClass = "",
37
+ children,
38
+ }: Props = $props();
39
+
40
+ let filterId = $state("");
41
+
42
+ let containerStyle = $derived(
43
+ `border-radius:${radius}px;--fg-tint:${tint};--fg-highlight:${highlight};` +
44
+ `--fg-fallback-blur:${fallbackBlur}px;--fg-fallback-saturation:${fallbackSaturation}%;`
45
+ );
46
+
47
+ onMount(() => {
48
+ filterId = `fg-dist-${Math.random().toString(36).slice(2, 8)}`;
49
+ });
50
+ </script>
51
+
52
+ <div
53
+ class={cn("frosted-glass", border && "frosted-glass-border", containerClass)}
54
+ style={containerStyle}
55
+ >
56
+ {#if filterId}
57
+ <div class="frosted-glass-filter" style="filter:url(#{filterId});"></div>
58
+
59
+ <svg class="frosted-glass-defs" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
60
+ <defs>
61
+ <filter
62
+ id={filterId}
63
+ x="-50%"
64
+ y="-50%"
65
+ width="200%"
66
+ height="200%"
67
+ filterUnits="objectBoundingBox"
68
+ primitiveUnits="userSpaceOnUse"
69
+ color-interpolation-filters="linearRGB"
70
+ >
71
+ <feTurbulence
72
+ type="fractalNoise"
73
+ baseFrequency="{baseFrequency} {baseFrequency}"
74
+ {numOctaves}
75
+ {seed}
76
+ stitchTiles="stitch"
77
+ result="noise"
78
+ />
79
+ <feGaussianBlur in="noise" stdDeviation={noiseBlur} result="blurred" />
80
+ <feDisplacementMap
81
+ in="SourceGraphic"
82
+ in2="blurred"
83
+ {scale}
84
+ xChannelSelector="R"
85
+ yChannelSelector="G"
86
+ />
87
+ </filter>
88
+ </defs>
89
+ </svg>
90
+ {/if}
91
+
92
+ <div class="frosted-glass-overlay"></div>
93
+ <div class="frosted-glass-specular"></div>
94
+
95
+ <div class={cn("frosted-glass-content", className)}>
96
+ {#if children}
97
+ {@render children()}
98
+ {/if}
99
+ </div>
100
+ </div>
101
+
102
+ <style>
103
+ .frosted-glass {
104
+ position: relative;
105
+ display: flex;
106
+ background: transparent;
107
+ overflow: hidden;
108
+ contain: layout paint;
109
+ box-shadow:
110
+ 0 2px 4px rgba(0, 0, 0, 0.1),
111
+ 0 0 8px rgba(0, 0, 0, 0.05);
112
+ }
113
+
114
+ .frosted-glass-border::before {
115
+ content: "";
116
+ position: absolute;
117
+ inset: 0;
118
+ z-index: 4;
119
+ border-radius: inherit;
120
+ padding: 1px;
121
+ background:
122
+ conic-gradient(
123
+ from -75deg at 50% 50%,
124
+ rgba(20, 60, 120, 0.5),
125
+ rgba(150, 200, 255, 0.1) 5% 40%,
126
+ rgba(20, 60, 120, 0.5) 50%,
127
+ rgba(150, 200, 255, 0.1) 60% 95%,
128
+ rgba(20, 60, 120, 0.5)
129
+ ),
130
+ linear-gradient(180deg, rgba(220, 240, 255, 0.5), rgba(240, 250, 255, 0.5));
131
+ box-shadow: inset 0 0 0 0.5px rgba(220, 240, 255, 0.5);
132
+ pointer-events: none;
133
+ mask:
134
+ linear-gradient(#fff 0 0) content-box,
135
+ linear-gradient(#fff 0 0);
136
+ mask-composite: exclude;
137
+ }
138
+
139
+ /* backdrop-filter: blur(0) pulls the backdrop into this layer so the SVG
140
+ displacement filter can distort it */
141
+ .frosted-glass-filter {
142
+ position: absolute;
143
+ inset: 0;
144
+ z-index: 0;
145
+ backdrop-filter: blur(0);
146
+ isolation: isolate;
147
+ transform: translateZ(0);
148
+ will-change: filter;
149
+ animation: frosted-glass-settle 0.22s ease-out;
150
+ }
151
+
152
+ @keyframes frosted-glass-settle {
153
+ 0% {
154
+ opacity: 0;
155
+ }
156
+ }
157
+
158
+ /* Safari can't combine filter:url() with backdrop-filter — fall back to
159
+ plain frosted blur */
160
+ @supports (-webkit-hyphens: none) {
161
+ .frosted-glass-filter {
162
+ filter: none !important;
163
+ backdrop-filter: blur(var(--fg-fallback-blur)) saturate(var(--fg-fallback-saturation));
164
+ }
165
+
166
+ .frosted-glass-overlay {
167
+ background: hsla(0, 0%, 100%, 0.5);
168
+ }
169
+ }
170
+
171
+ .frosted-glass-defs {
172
+ position: absolute;
173
+ width: 0;
174
+ height: 0;
175
+ }
176
+
177
+ .frosted-glass-overlay {
178
+ position: absolute;
179
+ inset: 0;
180
+ z-index: 1;
181
+ background: var(--fg-tint);
182
+ }
183
+
184
+ .frosted-glass-specular {
185
+ position: absolute;
186
+ inset: 0;
187
+ z-index: 2;
188
+ border-radius: inherit;
189
+ overflow: hidden;
190
+ box-shadow:
191
+ inset 1px 1px 0 var(--fg-highlight),
192
+ inset 0 0 5px var(--fg-highlight);
193
+ }
194
+
195
+ .frosted-glass-content {
196
+ position: relative;
197
+ z-index: 3;
198
+ display: flex;
199
+ align-items: center;
200
+ width: 100%;
201
+ }
202
+ </style>
@@ -0,0 +1,20 @@
1
+ import type { Snippet } from "svelte";
2
+ interface Props {
3
+ radius?: number;
4
+ baseFrequency?: number;
5
+ numOctaves?: number;
6
+ seed?: number;
7
+ noiseBlur?: number;
8
+ scale?: number;
9
+ tint?: string;
10
+ highlight?: string;
11
+ border?: boolean;
12
+ fallbackBlur?: number;
13
+ fallbackSaturation?: number;
14
+ class?: string;
15
+ containerClass?: string;
16
+ children?: Snippet;
17
+ }
18
+ declare const FrostedGlass: import("svelte").Component<Props, {}, "">;
19
+ type FrostedGlass = ReturnType<typeof FrostedGlass>;
20
+ export default FrostedGlass;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,48 @@
1
+ import { render, cleanup } from "@testing-library/svelte";
2
+ import { afterEach, describe, it, expect } from "vitest";
3
+ import FrostedGlass from "./FrostedGlass.svelte";
4
+ describe("FrostedGlass", () => {
5
+ afterEach(cleanup);
6
+ it("renders the component", () => {
7
+ const { container } = render(FrostedGlass);
8
+ const wrapper = container.querySelector(".frosted-glass");
9
+ expect(wrapper).toBeInTheDocument();
10
+ });
11
+ it("renders the layer stack", () => {
12
+ const { container } = render(FrostedGlass);
13
+ expect(container.querySelector(".frosted-glass-overlay")).toBeInTheDocument();
14
+ expect(container.querySelector(".frosted-glass-specular")).toBeInTheDocument();
15
+ expect(container.querySelector(".frosted-glass-content")).toBeInTheDocument();
16
+ });
17
+ it("applies custom container class", () => {
18
+ const { container } = render(FrostedGlass, {
19
+ props: { containerClass: "my-container" },
20
+ });
21
+ const wrapper = container.querySelector(".frosted-glass");
22
+ expect(wrapper?.className).toContain("my-container");
23
+ });
24
+ it("applies custom class to content", () => {
25
+ const { container } = render(FrostedGlass, { props: { class: "my-content" } });
26
+ const content = container.querySelector(".frosted-glass-content");
27
+ expect(content?.className).toContain("my-content");
28
+ });
29
+ it("sets border radius", () => {
30
+ const { container } = render(FrostedGlass, { props: { radius: 9999 } });
31
+ const wrapper = container.querySelector(".frosted-glass");
32
+ expect(wrapper.style.borderRadius).toBe("9999px");
33
+ });
34
+ it("sets tint CSS variable", () => {
35
+ const { container } = render(FrostedGlass, {
36
+ props: { tint: "hsla(0, 0%, 0%, 0.3)" },
37
+ });
38
+ const wrapper = container.querySelector(".frosted-glass");
39
+ expect(wrapper.style.getPropertyValue("--fg-tint")).toBe("hsla(0, 0%, 0%, 0.3)");
40
+ });
41
+ it("renders border layer by default and hides it when border=false", () => {
42
+ const withBorder = render(FrostedGlass);
43
+ expect(withBorder.container.querySelector(".frosted-glass-border")).toBeInTheDocument();
44
+ cleanup();
45
+ const withoutBorder = render(FrostedGlass, { props: { border: false } });
46
+ expect(withoutBorder.container.querySelector(".frosted-glass-border")).not.toBeInTheDocument();
47
+ });
48
+ });
@@ -0,0 +1,59 @@
1
+ # FrostedGlass
2
+
3
+ Frosted glass surface with an organic, wavy refraction of the content behind it. An alternative to [LiquidGlass](../liquid-glass/README.md): where LiquidGlass produces chromatic (rainbow-edge) refraction from gradient displacement maps, FrostedGlass distorts the backdrop with fractal turbulence noise for a softer, rippled-glass look — the effect used by glassy pill navbars.
4
+
5
+ ## How it works
6
+
7
+ The effect stacks four layers inside a rounded container:
8
+
9
+ 1. **Filter layer** — `backdrop-filter: blur(0)` pulls the backdrop into the element's own rendering, then a CSS `filter: url(#...)` pointing at an inline SVG filter distorts it: `feTurbulence` (fractal noise) → `feGaussianBlur` → `feDisplacementMap`.
10
+ 2. **Overlay** — translucent tint (`tint` prop).
11
+ 3. **Specular** — inset highlights simulating a lit glass rim (`highlight` prop).
12
+ 4. **Content** — your slotted content.
13
+
14
+ An optional conic-gradient border (`border` prop) frames the container.
15
+
16
+ Safari cannot combine `filter: url()` with `backdrop-filter`, so it falls back to a plain `blur() saturate()` frosted look (tunable via `fallbackBlur` / `fallbackSaturation`).
17
+
18
+ ## Usage
19
+
20
+ ```svelte
21
+ <script>
22
+ import { FrostedGlass } from "fancy-ui-svelte";
23
+ </script>
24
+
25
+ <FrostedGlass radius={9999}>
26
+ <nav class="flex w-full items-center justify-between px-7 py-4">
27
+ <span class="font-semibold">Brand</span>
28
+ <a href="/download">Download</a>
29
+ </nav>
30
+ </FrostedGlass>
31
+ ```
32
+
33
+ ## Props
34
+
35
+ | Prop | Type | Default | Description |
36
+ | -------------------- | --------- | --------------------------- | ------------------------------------------------- |
37
+ | `radius` | `number` | `24` | Border radius in pixels |
38
+ | `baseFrequency` | `number` | `0.008` | Turbulence noise frequency (lower = wider waves) |
39
+ | `numOctaves` | `number` | `2` | Turbulence octaves (detail of the noise) |
40
+ | `seed` | `number` | `92` | Turbulence random seed |
41
+ | `noiseBlur` | `number` | `2` | Gaussian blur softening the noise before displace |
42
+ | `scale` | `number` | `70` | Displacement intensity |
43
+ | `tint` | `string` | `"hsla(0, 0%, 100%, 0.25)"` | Overlay tint color |
44
+ | `highlight` | `string` | `"hsla(0, 0%, 100%, 0.75)"` | Specular rim highlight color |
45
+ | `border` | `boolean` | `true` | Show the conic-gradient glass border |
46
+ | `fallbackBlur` | `number` | `20` | Backdrop blur (px) for the Safari fallback |
47
+ | `fallbackSaturation` | `number` | `180` | Backdrop saturation (%) for the Safari fallback |
48
+ | `class` | `string` | `""` | CSS classes for the content layer |
49
+ | `containerClass` | `string` | `""` | CSS classes for the outer container |
50
+
51
+ ## Slots
52
+
53
+ | Slot | Description |
54
+ | ---------- | ------------------------------------ |
55
+ | `children` | Content rendered on top of the glass |
56
+
57
+ ## Notes
58
+
59
+ - The displacement only shows over content that scrolls or moves behind the glass; over a flat background the effect reads as a subtle frost.
@@ -0,0 +1 @@
1
+ export { default as FrostedGlass } from "./FrostedGlass.svelte";
@@ -0,0 +1 @@
1
+ export { default as FrostedGlass } from "./FrostedGlass.svelte";
@@ -42,6 +42,7 @@ export * from "./text-reveal-card/index.js";
42
42
  export * from "./container-scroll/index.js";
43
43
  export * from "./container-text-flip/index.js";
44
44
  export * from "./focus/index.js";
45
+ export * from "./frosted-glass/index.js";
45
46
  export * from "./liquid-glass/index.js";
46
47
  export * from "./smooth-cursor/index.js";
47
48
  export * from "./sparkles/index.js";
@@ -47,6 +47,7 @@ export * from "./text-reveal-card/index.js";
47
47
  export * from "./container-scroll/index.js";
48
48
  export * from "./container-text-flip/index.js";
49
49
  export * from "./focus/index.js";
50
+ export * from "./frosted-glass/index.js";
50
51
  export * from "./liquid-glass/index.js";
51
52
  export * from "./smooth-cursor/index.js";
52
53
  export * from "./sparkles/index.js";
@@ -1634,6 +1634,74 @@ export const registry = {
1634
1634
  },
1635
1635
  ],
1636
1636
  },
1637
+ "frosted-glass": {
1638
+ name: "FrostedGlass",
1639
+ slug: "frosted-glass",
1640
+ description: "Frosted glass surface with organic turbulence-noise refraction, an alternative to LiquidGlass",
1641
+ category: "effects",
1642
+ status: "done",
1643
+ tags: ["glass", "effect", "svg", "filter", "turbulence", "displacement", "blur", "navbar"],
1644
+ props: [
1645
+ { name: "radius", type: "number", default: "24", description: "Border radius in pixels" },
1646
+ {
1647
+ name: "baseFrequency",
1648
+ type: "number",
1649
+ default: "0.008",
1650
+ description: "Turbulence noise frequency (lower = wider waves)",
1651
+ },
1652
+ {
1653
+ name: "numOctaves",
1654
+ type: "number",
1655
+ default: "2",
1656
+ description: "Turbulence octaves controlling noise detail",
1657
+ },
1658
+ { name: "seed", type: "number", default: "92", description: "Turbulence random seed" },
1659
+ {
1660
+ name: "noiseBlur",
1661
+ type: "number",
1662
+ default: "2",
1663
+ description: "Gaussian blur softening the noise before displacement",
1664
+ },
1665
+ { name: "scale", type: "number", default: "70", description: "Displacement intensity" },
1666
+ {
1667
+ name: "tint",
1668
+ type: "string",
1669
+ default: '"hsla(0, 0%, 100%, 0.25)"',
1670
+ description: "Overlay tint color",
1671
+ },
1672
+ {
1673
+ name: "highlight",
1674
+ type: "string",
1675
+ default: '"hsla(0, 0%, 100%, 0.75)"',
1676
+ description: "Specular rim highlight color",
1677
+ },
1678
+ {
1679
+ name: "border",
1680
+ type: "boolean",
1681
+ default: "true",
1682
+ description: "Show the conic-gradient glass border",
1683
+ },
1684
+ {
1685
+ name: "fallbackBlur",
1686
+ type: "number",
1687
+ default: "20",
1688
+ description: "Backdrop blur in pixels for the Safari fallback",
1689
+ },
1690
+ {
1691
+ name: "fallbackSaturation",
1692
+ type: "number",
1693
+ default: "180",
1694
+ description: "Backdrop saturation percentage for the Safari fallback",
1695
+ },
1696
+ {
1697
+ name: "containerClass",
1698
+ type: "string",
1699
+ default: '""',
1700
+ description: "CSS classes for the outer container",
1701
+ },
1702
+ ],
1703
+ slots: [{ name: "children", description: "Content rendered on top of the glass" }],
1704
+ },
1637
1705
  "liquid-glass": {
1638
1706
  name: "LiquidGlass",
1639
1707
  slug: "liquid-glass",