Skip to content

Commit 928e5fb

Browse files
showcase
1 parent 965e811 commit 928e5fb

File tree

2 files changed

+392
-0
lines changed

2 files changed

+392
-0
lines changed

src/styleguide/index.html

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,31 @@ <h1 class="text-3xl font-bold text-gray-900 dark:text-white">Living Styleguide</
3030
</div>
3131
</header>
3232

33+
<!-- Showcases Section -->
34+
<section class="mb-12" id="showcases">
35+
<h2 class="text-2xl font-semibold border-b border-gray-300 dark:border-gray-700 pb-2 mb-6">Showcases</h2>
36+
<p class="text-gray-600 dark:text-gray-400 mb-6">
37+
Interactive demonstrations of advanced components and effects. Each showcase includes live examples and implementation documentation.
38+
</p>
39+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
40+
<!-- Reverse Explosion Showcase -->
41+
<a href="showcases/reverse-explosion.html" class="group block p-5 bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 hover:shadow-md hover:border-blue-300 dark:hover:border-blue-600 transition-all duration-200">
42+
<div class="flex items-center gap-3 mb-2">
43+
<svg class="w-6 h-6 text-blue-500 dark:text-blue-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
44+
<path stroke-linecap="round" stroke-linejoin="round" d="M9.813 15.904 9 18.75l-.813-2.846a4.5 4.5 0 0 0-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 0 0 3.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 0 0 3.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 0 0-3.09 3.09ZM18.259 8.715 18 9.75l-.259-1.035a3.375 3.375 0 0 0-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 0 0 2.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 0 0 2.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 0 0-2.456 2.456ZM16.894 20.567 16.5 21.75l-.394-1.183a2.25 2.25 0 0 0-1.423-1.423L13.5 18.75l1.183-.394a2.25 2.25 0 0 0 1.423-1.423l.394-1.183.394 1.183a2.25 2.25 0 0 0 1.423 1.423l1.183.394-1.183.394a2.25 2.25 0 0 0-1.423 1.423Z" />
45+
</svg>
46+
<h3 class="text-lg font-semibold text-gray-900 dark:text-white group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">Reverse Explosion</h3>
47+
</div>
48+
<p class="text-sm text-gray-600 dark:text-gray-400">
49+
Dramatic hero entrance where elements scatter in 3D and animate inward.
50+
</p>
51+
<span class="inline-block mt-3 text-sm font-medium text-blue-600 dark:text-blue-400 group-hover:underline">
52+
View Showcase &rarr;
53+
</span>
54+
</a>
55+
</div>
56+
</section>
57+
3358
<!-- Typography Section -->
3459
<section class="mb-12" id="typography">
3560
<h2 class="text-2xl font-semibold border-b border-gray-300 dark:border-gray-700 pb-2 mb-6">Typography</h2>
Lines changed: 367 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,367 @@
1+
<!DOCTYPE html>
2+
<html lang="en" class="h-full scroll-smooth">
3+
4+
<head>
5+
<title>Reverse Explosion Hero - Living Styleguide</title>
6+
<meta charset="utf-8">
7+
<meta name="viewport" content="width=device-width, initial-scale=1">
8+
9+
<include src="partials/theme-fouc-guard.html"></include>
10+
11+
<style>
12+
.reverse-explosion-stage {
13+
perspective: 1400px;
14+
perspective-origin: center 35%;
15+
overflow: visible;
16+
}
17+
18+
.reverse-explosion-content {
19+
transform-style: preserve-3d;
20+
}
21+
22+
[data-reverse-explosion-item] {
23+
opacity: 0;
24+
transform: translate3d(var(--rx-x, 0px), var(--rx-y, 0px), var(--rx-z, 0px))
25+
rotate(var(--rx-rot, 0deg))
26+
scale(var(--rx-scale, 1));
27+
filter: blur(var(--rx-blur, 0px));
28+
transition:
29+
transform var(--rx-duration, 2800ms) cubic-bezier(0.16, 1, 0.3, 1),
30+
opacity var(--rx-duration, 2800ms) cubic-bezier(0.16, 1, 0.3, 1),
31+
filter var(--rx-duration, 2800ms) cubic-bezier(0.16, 1, 0.3, 1);
32+
transition-delay: var(--rx-delay, 0ms);
33+
transform-style: preserve-3d;
34+
}
35+
36+
[data-reverse-explosion].is-active [data-reverse-explosion-item] {
37+
opacity: 1;
38+
transform: translate3d(0px, 0px, 0px) rotate(0deg) scale(1);
39+
filter: blur(0px);
40+
}
41+
42+
@media (prefers-reduced-motion: reduce) {
43+
[data-reverse-explosion-item] {
44+
opacity: 1;
45+
transform: none;
46+
filter: none;
47+
transition: none;
48+
}
49+
}
50+
</style>
51+
</head>
52+
53+
<body class="h-full bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-gray-100 transition-colors duration-200">
54+
55+
<div class="container mx-auto px-4 py-12 max-w-5xl">
56+
57+
<header class="mb-12 flex justify-between items-center">
58+
<div>
59+
<a href="../index.html" class="text-blue-600 dark:text-blue-400 hover:underline text-sm mb-2 inline-block">&larr; Back to Styleguide</a>
60+
<h1 class="text-3xl font-bold text-gray-900 dark:text-white">Reverse Explosion Hero</h1>
61+
</div>
62+
<div data-controller="theme">
63+
<button
64+
data-theme-target="toggleButton"
65+
data-action="click->theme#toggle"
66+
class="px-4 py-2 font-semibold text-sm text-white bg-purple-600 rounded-md shadow-sm hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500 dark:bg-indigo-600 dark:hover:bg-indigo-700 dark:focus:ring-offset-gray-800 cursor-pointer"
67+
></button>
68+
</div>
69+
</header>
70+
71+
<section class="mb-12">
72+
<p class="text-lg text-gray-600 dark:text-gray-300 leading-relaxed mb-4">
73+
The <strong>Reverse Explosion</strong> effect creates a dramatic entrance animation where
74+
elements start scattered in 3D space (random positions, rotations, blur) and animate inward
75+
to their final positions.
76+
</p>
77+
<p class="text-gray-600 dark:text-gray-400">
78+
The animation respects <code class="px-1.5 py-0.5 bg-gray-200 dark:bg-gray-700 rounded text-sm">prefers-reduced-motion</code>.
79+
</p>
80+
</section>
81+
82+
</div>
83+
84+
<!-- Live Demo -->
85+
<section
86+
class="reverse-explosion-stage relative mb-16"
87+
data-reverse-explosion
88+
>
89+
<div
90+
class="reverse-explosion-content relative py-24 px-6 bg-gradient-to-br from-blue-600 via-indigo-700 to-purple-800 dark:from-blue-800 dark:via-indigo-900 dark:to-purple-950"
91+
>
92+
<div class="absolute inset-0 overflow-hidden pointer-events-none">
93+
<div class="absolute -top-24 -right-24 w-96 h-96 bg-white/10 rounded-full blur-3xl"></div>
94+
<div class="absolute -bottom-24 -left-24 w-80 h-80 bg-purple-500/20 rounded-full blur-3xl"></div>
95+
</div>
96+
97+
<div class="relative z-10 max-w-4xl mx-auto text-center reverse-explosion-content">
98+
<span
99+
class="inline-block px-4 py-1.5 mb-6 text-sm font-semibold text-blue-100 bg-white/10 backdrop-blur-sm rounded-full border border-white/20"
100+
data-reverse-explosion-item
101+
>
102+
Reverse Explosion Effect
103+
</span>
104+
105+
<h1
106+
class="text-4xl md:text-5xl lg:text-6xl font-extrabold text-white mb-6 leading-tight"
107+
data-reverse-explosion-item
108+
>
109+
Elements Fly In From
110+
<span class="bg-gradient-to-r from-amber-300 to-orange-400 bg-clip-text text-transparent">
111+
Every Direction
112+
</span>
113+
</h1>
114+
115+
<p
116+
class="text-lg md:text-xl text-blue-100 dark:text-blue-200 mb-10 max-w-2xl mx-auto leading-relaxed"
117+
data-reverse-explosion-item
118+
>
119+
Create stunning hero entrances that capture attention. Each element starts
120+
scattered in 3D space and smoothly animates to its final position.
121+
</p>
122+
123+
<div
124+
class="flex flex-col sm:flex-row gap-4 justify-center mb-12"
125+
data-reverse-explosion-item
126+
>
127+
<a
128+
href="#usage"
129+
class="inline-block px-8 py-4 font-bold text-lg text-indigo-700 bg-white rounded-lg shadow-lg hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-white focus:ring-offset-indigo-700 transition duration-150 ease-in-out"
130+
>
131+
See How It Works
132+
</a>
133+
<button
134+
data-reverse-explosion-replay
135+
class="inline-block px-8 py-4 font-bold text-lg text-white bg-white/10 backdrop-blur-sm rounded-lg border border-white/30 hover:bg-white/20 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-white focus:ring-offset-indigo-700 transition duration-150 ease-in-out cursor-pointer"
136+
>
137+
Replay Animation
138+
</button>
139+
</div>
140+
141+
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 max-w-3xl mx-auto">
142+
<div
143+
class="p-4 bg-white/10 backdrop-blur-sm rounded-xl border border-white/20"
144+
data-reverse-explosion-item
145+
data-reverse-explosion-strength="0.8"
146+
>
147+
<h3 class="font-semibold text-white mb-1">3D Transforms</h3>
148+
<p class="text-sm text-blue-100">Elements scatter in X, Y, and Z axes</p>
149+
</div>
150+
<div
151+
class="p-4 bg-white/10 backdrop-blur-sm rounded-xl border border-white/20"
152+
data-reverse-explosion-item
153+
data-reverse-explosion-strength="0.8"
154+
>
155+
<h3 class="font-semibold text-white mb-1">Staggered Timing</h3>
156+
<p class="text-sm text-blue-100">Each element has unique delay</p>
157+
</div>
158+
<div
159+
class="p-4 bg-white/10 backdrop-blur-sm rounded-xl border border-white/20"
160+
data-reverse-explosion-item
161+
data-reverse-explosion-strength="0.8"
162+
>
163+
<h3 class="font-semibold text-white mb-1">Blur Effect</h3>
164+
<p class="text-sm text-blue-100">Distant elements start blurred</p>
165+
</div>
166+
</div>
167+
</div>
168+
</div>
169+
</section>
170+
171+
<!-- Documentation -->
172+
<div class="container mx-auto px-4 py-12 max-w-5xl">
173+
174+
<section class="mb-16" id="usage">
175+
<h2 class="text-2xl font-semibold border-b border-gray-300 dark:border-gray-700 pb-2 mb-6">Usage</h2>
176+
177+
<div class="space-y-8">
178+
<div>
179+
<h3 class="text-lg font-medium mb-3">1. HTML Structure</h3>
180+
<p class="text-gray-600 dark:text-gray-400 mb-4">
181+
Mark the container with <code class="px-1.5 py-0.5 bg-gray-200 dark:bg-gray-700 rounded text-sm">data-reverse-explosion</code>
182+
and each animated element with <code class="px-1.5 py-0.5 bg-gray-200 dark:bg-gray-700 rounded text-sm">data-reverse-explosion-item</code>.
183+
</p>
184+
<pre class="p-4 bg-gray-100 dark:bg-gray-800 rounded-lg overflow-x-auto text-sm"><code class="text-gray-800 dark:text-gray-200">&lt;section data-reverse-explosion style="perspective: 1400px;"&gt;
185+
&lt;div style="transform-style: preserve-3d;"&gt;
186+
&lt;h1 data-reverse-explosion-item&gt;Headline&lt;/h1&gt;
187+
&lt;p data-reverse-explosion-item&gt;Subtext&lt;/p&gt;
188+
&lt;button data-reverse-explosion-replay&gt;Replay&lt;/button&gt;
189+
&lt;/div&gt;
190+
&lt;/section&gt;</code></pre>
191+
</div>
192+
193+
<div>
194+
<h3 class="text-lg font-medium mb-3">2. Include the CSS</h3>
195+
<p class="text-gray-600 dark:text-gray-400 mb-4">
196+
The CSS is included in <code class="px-1.5 py-0.5 bg-gray-200 dark:bg-gray-700 rounded text-sm">main.css</code>.
197+
Here's the core for reference:
198+
</p>
199+
<pre class="p-4 bg-gray-100 dark:bg-gray-800 rounded-lg overflow-x-auto text-sm"><code class="text-gray-800 dark:text-gray-200">[data-reverse-explosion-item] {
200+
opacity: 0;
201+
transform: translate3d(var(--rx-x, 0), var(--rx-y, 0), var(--rx-z, 0))
202+
rotate(var(--rx-rot, 0deg)) scale(var(--rx-scale, 1));
203+
filter: blur(var(--rx-blur, 0px));
204+
transition: transform var(--rx-duration) cubic-bezier(0.16, 1, 0.3, 1),
205+
opacity var(--rx-duration) cubic-bezier(0.16, 1, 0.3, 1),
206+
filter var(--rx-duration) cubic-bezier(0.16, 1, 0.3, 1);
207+
transition-delay: var(--rx-delay, 0ms);
208+
}
209+
210+
[data-reverse-explosion].is-active [data-reverse-explosion-item] {
211+
opacity: 1;
212+
transform: translate3d(0, 0, 0) rotate(0deg) scale(1);
213+
filter: blur(0px);
214+
}</code></pre>
215+
</div>
216+
217+
<div>
218+
<h3 class="text-lg font-medium mb-3">3. Include the JavaScript</h3>
219+
<p class="text-gray-600 dark:text-gray-400 mb-4">
220+
Add this script at the end of your page (before <code class="px-1.5 py-0.5 bg-gray-200 dark:bg-gray-700 rounded text-sm">&lt;/body&gt;</code>):
221+
</p>
222+
<pre class="p-4 bg-gray-100 dark:bg-gray-800 rounded-lg overflow-x-auto text-sm"><code class="text-gray-800 dark:text-gray-200">&lt;script&gt;
223+
(function() {
224+
const container = document.querySelector('[data-reverse-explosion]');
225+
if (!container) return;
226+
227+
const items = Array.from(container.querySelectorAll('[data-reverse-explosion-item]'));
228+
const replay = container.querySelector('[data-reverse-explosion-replay]');
229+
if (items.length === 0) return;
230+
231+
const reducedMotion = matchMedia('(prefers-reduced-motion: reduce)').matches;
232+
if (reducedMotion) {
233+
container.classList.add('is-active');
234+
return;
235+
}
236+
237+
function getStrength(el) {
238+
const v = Number(el.dataset.reverseExplosionStrength);
239+
return (v &gt; 0) ? v : 1;
240+
}
241+
242+
function prepare() {
243+
items.forEach((item, i) =&gt; {
244+
const s = getStrength(item);
245+
const angle = Math.random() * Math.PI * 2;
246+
const spread = 260 + Math.random() * 120;
247+
const distance = spread * (0.6 + Math.random() * 0.5);
248+
const x = Math.cos(angle) * distance * s;
249+
const y = Math.sin(angle) * distance * s;
250+
const z = (120 + Math.random() * 320) * s;
251+
const rotation = (Math.random() * 2 - 1) * 16 * s;
252+
const scale = 0.78 + Math.random() * 0.45;
253+
const blur = 3 + Math.random() * 8;
254+
const delay = i * 120 + Math.random() * 160;
255+
256+
item.style.setProperty('--rx-x', x.toFixed(1) + 'px');
257+
item.style.setProperty('--rx-y', y.toFixed(1) + 'px');
258+
item.style.setProperty('--rx-z', z.toFixed(1) + 'px');
259+
item.style.setProperty('--rx-rot', rotation.toFixed(1) + 'deg');
260+
item.style.setProperty('--rx-scale', scale.toFixed(2));
261+
item.style.setProperty('--rx-blur', blur.toFixed(1) + 'px');
262+
item.style.setProperty('--rx-delay', delay.toFixed(0) + 'ms');
263+
item.style.setProperty('--rx-duration', '2800ms');
264+
});
265+
}
266+
267+
function play() {
268+
container.classList.remove('is-active');
269+
prepare();
270+
requestAnimationFrame(() =&gt; requestAnimationFrame(() =&gt; container.classList.add('is-active')));
271+
}
272+
273+
play();
274+
if (replay) replay.addEventListener('click', play);
275+
})();
276+
&lt;/script&gt;</code></pre>
277+
</div>
278+
279+
<div>
280+
<h3 class="text-lg font-medium mb-3">Per-Item Strength</h3>
281+
<p class="text-gray-600 dark:text-gray-400 mb-4">
282+
Use <code class="px-1.5 py-0.5 bg-gray-200 dark:bg-gray-700 rounded text-sm">data-reverse-explosion-strength</code> to adjust intensity per element.
283+
</p>
284+
<pre class="p-4 bg-gray-100 dark:bg-gray-800 rounded-lg overflow-x-auto text-sm"><code class="text-gray-800 dark:text-gray-200">&lt;!-- Subtle (less scatter) --&gt;
285+
&lt;div data-reverse-explosion-item data-reverse-explosion-strength="0.5"&gt;...&lt;/div&gt;
286+
287+
&lt;!-- Dramatic (more scatter) --&gt;
288+
&lt;div data-reverse-explosion-item data-reverse-explosion-strength="1.5"&gt;...&lt;/div&gt;</code></pre>
289+
</div>
290+
</div>
291+
</section>
292+
293+
<section class="mb-16">
294+
<h2 class="text-2xl font-semibold border-b border-gray-300 dark:border-gray-700 pb-2 mb-6">Accessibility</h2>
295+
<div class="p-4 rounded-md bg-green-50 border border-green-300 dark:bg-green-900/30 dark:border-green-700/50">
296+
<p class="text-sm font-medium text-green-800 dark:text-green-200">
297+
<strong>Respects prefers-reduced-motion:</strong> Elements appear immediately without animation for users who prefer reduced motion.
298+
</p>
299+
</div>
300+
</section>
301+
302+
</div>
303+
304+
<footer class="bg-gray-100 dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700 mt-16 py-8">
305+
<div class="container mx-auto px-4 text-center text-sm text-gray-600 dark:text-gray-400">
306+
Part of the <a href="../index.html" class="text-blue-600 dark:text-blue-400 hover:underline">Living Styleguide</a>
307+
</div>
308+
</footer>
309+
310+
<script>
311+
(function() {
312+
const container = document.querySelector('[data-reverse-explosion]');
313+
if (!container) return;
314+
315+
const items = Array.from(container.querySelectorAll('[data-reverse-explosion-item]'));
316+
const replay = container.querySelector('[data-reverse-explosion-replay]');
317+
if (items.length === 0) return;
318+
319+
const reducedMotion = matchMedia('(prefers-reduced-motion: reduce)').matches;
320+
if (reducedMotion) {
321+
container.classList.add('is-active');
322+
return;
323+
}
324+
325+
function getStrength(el) {
326+
const v = Number(el.dataset.reverseExplosionStrength);
327+
return (v > 0) ? v : 1;
328+
}
329+
330+
function prepare() {
331+
items.forEach((item, i) => {
332+
const s = getStrength(item);
333+
const angle = Math.random() * Math.PI * 2;
334+
const spread = 260 + Math.random() * 120;
335+
const distance = spread * (0.6 + Math.random() * 0.5);
336+
const x = Math.cos(angle) * distance * s;
337+
const y = Math.sin(angle) * distance * s;
338+
const z = (120 + Math.random() * 320) * s;
339+
const rotation = (Math.random() * 2 - 1) * 16 * s;
340+
const scale = 0.78 + Math.random() * 0.45;
341+
const blur = 3 + Math.random() * 8;
342+
const delay = i * 120 + Math.random() * 160;
343+
344+
item.style.setProperty('--rx-x', x.toFixed(1) + 'px');
345+
item.style.setProperty('--rx-y', y.toFixed(1) + 'px');
346+
item.style.setProperty('--rx-z', z.toFixed(1) + 'px');
347+
item.style.setProperty('--rx-rot', rotation.toFixed(1) + 'deg');
348+
item.style.setProperty('--rx-scale', scale.toFixed(2));
349+
item.style.setProperty('--rx-blur', blur.toFixed(1) + 'px');
350+
item.style.setProperty('--rx-delay', delay.toFixed(0) + 'ms');
351+
item.style.setProperty('--rx-duration', '2800ms');
352+
});
353+
}
354+
355+
function play() {
356+
container.classList.remove('is-active');
357+
prepare();
358+
requestAnimationFrame(() => requestAnimationFrame(() => container.classList.add('is-active')));
359+
}
360+
361+
play();
362+
if (replay) replay.addEventListener('click', play);
363+
})();
364+
</script>
365+
</body>
366+
367+
</html>

0 commit comments

Comments
 (0)