Skip to content

Commit ca16fbb

Browse files
ryo-manbaclaude
andcommitted
feat(docs): move animation showcase above features with continuous auto-play
Move the animation showcase section to right after the hero for immediate visual impact. Animations now auto-loop continuously (1.8s interval) using IntersectionObserver, making them visible on mobile without hover. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 43fbf0e commit ca16fbb

2 files changed

Lines changed: 262 additions & 188 deletions

File tree

docs/src/pages/index.astro

Lines changed: 131 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -94,90 +94,8 @@ const categories = [
9494
</div>
9595
</section>
9696

97-
<!-- Features -->
98-
<section class="py-20 px-4 sm:px-6 border-t border-border">
99-
<div class="max-w-5xl mx-auto">
100-
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6" data-anim-stagger="100ms">
101-
<div class="glass-card p-6" data-anim="fadeInUp">
102-
<div class="w-10 h-10 rounded-lg bg-accent/10 flex items-center justify-center mb-4">
103-
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#6366f1" stroke-width="2">
104-
<path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" />
105-
</svg>
106-
</div>
107-
<h3 class="text-lg font-heading font-semibold mb-2">No JS to Write</h3>
108-
<p class="text-sm text-text-secondary">Pure CSS animations triggered by HTML attributes. Just add data attributes.</p>
109-
</div>
110-
111-
<div class="glass-card p-6" data-anim="fadeInUp">
112-
<div class="w-10 h-10 rounded-lg bg-accent/10 flex items-center justify-center mb-4">
113-
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#6366f1" stroke-width="2">
114-
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
115-
</svg>
116-
</div>
117-
<h3 class="text-lg font-heading font-semibold mb-2">Anti-FOUC Built-in</h3>
118-
<p class="text-sm text-text-secondary">3-layer defense against Flash of Unstyled Content. No manual CSS workarounds needed.</p>
119-
</div>
120-
121-
<div class="glass-card p-6" data-anim="fadeInUp">
122-
<div class="w-10 h-10 rounded-lg bg-accent/10 flex items-center justify-center mb-4">
123-
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#6366f1" stroke-width="2">
124-
<circle cx="12" cy="12" r="10" />
125-
<polyline points="12 6 12 12 16 14" />
126-
</svg>
127-
</div>
128-
<h3 class="text-lg font-heading font-semibold mb-2">Under 3KB</h3>
129-
<p class="text-sm text-text-secondary">Tiny footprint. No dependencies. Loads in under 5ms. Smaller than most favicons.</p>
130-
</div>
131-
132-
<div class="glass-card p-6" data-anim="fadeInUp">
133-
<div class="w-10 h-10 rounded-lg bg-accent/10 flex items-center justify-center mb-4">
134-
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#6366f1" stroke-width="2">
135-
<path d="M3 3h18v18H3z M3 9h18 M9 3v18" />
136-
</svg>
137-
</div>
138-
<h3 class="text-lg font-heading font-semibold mb-2">TypeScript Support</h3>
139-
<p class="text-sm text-text-secondary">Full autocomplete for all data-anim attributes in React and Vue. Just import and go.</p>
140-
</div>
141-
</div>
142-
</div>
143-
</section>
144-
145-
<!-- Quick Start -->
146-
<section class="py-20 px-4 sm:px-6 border-t border-border">
147-
<div class="max-w-3xl mx-auto">
148-
<h2 class="text-3xl font-heading font-bold text-center mb-4" data-anim="fadeInUp">
149-
Three lines. That's it.
150-
</h2>
151-
<p class="text-center text-text-secondary mb-8" data-anim="fadeInUp" data-anim-delay="100ms">
152-
No config files. No build step. No framework required.
153-
</p>
154-
155-
<div data-anim="fadeInUp" data-anim-delay="200ms">
156-
<CodeBlock
157-
code={`<!-- 1. Add the script -->
158-
<script src="https://unpkg.com/data-anim@latest/dist/data-anim.js"></script>
159-
160-
<!-- 2. Add the attribute -->
161-
<div data-anim="fadeInUp">
162-
Your content animates on scroll
163-
</div>
164-
165-
<!-- 3. There is no step 3 -->`}
166-
lang="html"
167-
filename="index.html"
168-
/>
169-
</div>
170-
171-
<div class="text-center mt-8" data-anim="fadeInUp" data-anim-delay="300ms">
172-
<a href={`${import.meta.env.BASE_URL.replace(/\/?$/, '/')}docs/getting-started`} class="text-accent-readable hover:text-[#c4b5fd] font-semibold text-lg">
173-
Read the full docs &rarr;
174-
</a>
175-
</div>
176-
</div>
177-
</section>
178-
17997
<!-- Animation Showcase -->
180-
<section class="py-20 px-4 sm:px-6 border-t border-border">
98+
<section id="showcase-section" class="py-20 px-4 sm:px-6 border-t border-border">
18199
<div class="max-w-5xl mx-auto">
182100
<p class="text-center text-xs font-semibold tracking-widest text-text-muted uppercase mb-4" data-anim="fadeInUp">Animation Library</p>
183101
<h2 class="text-3xl md:text-4xl font-heading font-bold text-center mb-4" data-anim="fadeInUp">
@@ -269,6 +187,88 @@ const categories = [
269187
</div>
270188
</section>
271189

190+
<!-- Features -->
191+
<section class="py-20 px-4 sm:px-6 border-t border-border">
192+
<div class="max-w-5xl mx-auto">
193+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6" data-anim-stagger="100ms">
194+
<div class="glass-card p-6" data-anim="fadeInUp">
195+
<div class="w-10 h-10 rounded-lg bg-accent/10 flex items-center justify-center mb-4">
196+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#6366f1" stroke-width="2">
197+
<path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" />
198+
</svg>
199+
</div>
200+
<h3 class="text-lg font-heading font-semibold mb-2">No JS to Write</h3>
201+
<p class="text-sm text-text-secondary">Pure CSS animations triggered by HTML attributes. Just add data attributes.</p>
202+
</div>
203+
204+
<div class="glass-card p-6" data-anim="fadeInUp">
205+
<div class="w-10 h-10 rounded-lg bg-accent/10 flex items-center justify-center mb-4">
206+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#6366f1" stroke-width="2">
207+
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
208+
</svg>
209+
</div>
210+
<h3 class="text-lg font-heading font-semibold mb-2">Anti-FOUC Built-in</h3>
211+
<p class="text-sm text-text-secondary">3-layer defense against Flash of Unstyled Content. No manual CSS workarounds needed.</p>
212+
</div>
213+
214+
<div class="glass-card p-6" data-anim="fadeInUp">
215+
<div class="w-10 h-10 rounded-lg bg-accent/10 flex items-center justify-center mb-4">
216+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#6366f1" stroke-width="2">
217+
<circle cx="12" cy="12" r="10" />
218+
<polyline points="12 6 12 12 16 14" />
219+
</svg>
220+
</div>
221+
<h3 class="text-lg font-heading font-semibold mb-2">Under 3KB</h3>
222+
<p class="text-sm text-text-secondary">Tiny footprint. No dependencies. Loads in under 5ms. Smaller than most favicons.</p>
223+
</div>
224+
225+
<div class="glass-card p-6" data-anim="fadeInUp">
226+
<div class="w-10 h-10 rounded-lg bg-accent/10 flex items-center justify-center mb-4">
227+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#6366f1" stroke-width="2">
228+
<path d="M3 3h18v18H3z M3 9h18 M9 3v18" />
229+
</svg>
230+
</div>
231+
<h3 class="text-lg font-heading font-semibold mb-2">TypeScript Support</h3>
232+
<p class="text-sm text-text-secondary">Full autocomplete for all data-anim attributes in React and Vue. Just import and go.</p>
233+
</div>
234+
</div>
235+
</div>
236+
</section>
237+
238+
<!-- Quick Start -->
239+
<section class="py-20 px-4 sm:px-6 border-t border-border">
240+
<div class="max-w-3xl mx-auto">
241+
<h2 class="text-3xl font-heading font-bold text-center mb-4" data-anim="fadeInUp">
242+
Three lines. That's it.
243+
</h2>
244+
<p class="text-center text-text-secondary mb-8" data-anim="fadeInUp" data-anim-delay="100ms">
245+
No config files. No build step. No framework required.
246+
</p>
247+
248+
<div data-anim="fadeInUp" data-anim-delay="200ms">
249+
<CodeBlock
250+
code={`<!-- 1. Add the script -->
251+
<script src="https://unpkg.com/data-anim@latest/dist/data-anim.js"></script>
252+
253+
<!-- 2. Add the attribute -->
254+
<div data-anim="fadeInUp">
255+
Your content animates on scroll
256+
</div>
257+
258+
<!-- 3. There is no step 3 -->`}
259+
lang="html"
260+
filename="index.html"
261+
/>
262+
</div>
263+
264+
<div class="text-center mt-8" data-anim="fadeInUp" data-anim-delay="300ms">
265+
<a href={`${import.meta.env.BASE_URL.replace(/\/?$/, '/')}docs/getting-started`} class="text-accent-readable hover:text-[#c4b5fd] font-semibold text-lg">
266+
Read the full docs &rarr;
267+
</a>
268+
</div>
269+
</div>
270+
</section>
271+
272272
<Footer />
273273
</BaseLayout>
274274

@@ -466,14 +466,16 @@ const categories = [
466466
}, 2000);
467467
});
468468

469-
// Showcase card hover → animate child dots
470-
document.querySelectorAll('.showcase-card').forEach(function(card) {
471-
var dots = card.querySelectorAll('[data-gallery-anim]');
472-
if (!dots.length) return;
473-
var animating = false;
474-
card.addEventListener('mouseenter', function() {
475-
if (animating) return;
476-
animating = true;
469+
// Showcase card continuous auto-play (motion.dev style)
470+
(function() {
471+
var cards = Array.from(document.querySelectorAll('.showcase-card'));
472+
if (!cards.length) return;
473+
474+
function playCard(card) {
475+
var dots = card.querySelectorAll('[data-gallery-anim]');
476+
if (!dots.length) return;
477+
if (card._animating) return;
478+
card._animating = true;
477479
var done = 0;
478480
dots.forEach(function(dot, i) {
479481
var name = dot.getAttribute('data-gallery-anim');
@@ -484,10 +486,45 @@ const categories = [
484486
dot.addEventListener('animationend', function() {
485487
dot.style.animation = '';
486488
done++;
487-
if (done >= dots.length) animating = false;
489+
if (done >= dots.length) card._animating = false;
488490
}, { once: true });
489491
}, i * 80);
490492
});
491-
});
492-
});
493+
}
494+
495+
// Each card loops independently with staggered start
496+
var intervals = [];
497+
498+
function startAutoPlay() {
499+
if (intervals.length) return;
500+
cards.forEach(function(card, idx) {
501+
// Stagger initial start so they don't all fire at once
502+
setTimeout(function() {
503+
playCard(card);
504+
var id = setInterval(function() { playCard(card); }, 1800);
505+
intervals.push(id);
506+
}, idx * 400);
507+
});
508+
}
509+
510+
function stopAutoPlay() {
511+
intervals.forEach(function(id) { clearInterval(id); });
512+
intervals = [];
513+
}
514+
515+
var showcaseSection = document.getElementById('showcase-section');
516+
if (!showcaseSection) return;
517+
518+
var observer = new IntersectionObserver(function(entries) {
519+
entries.forEach(function(entry) {
520+
if (entry.isIntersecting) {
521+
startAutoPlay();
522+
} else {
523+
stopAutoPlay();
524+
}
525+
});
526+
}, { threshold: 0.1 });
527+
528+
observer.observe(showcaseSection);
529+
})();
493530
</script>

0 commit comments

Comments
 (0)