Skip to content

Commit 5ed8aec

Browse files
committed
scroll animations in Showcase page
1 parent dc9d4a3 commit 5ed8aec

File tree

1 file changed

+155
-35
lines changed

1 file changed

+155
-35
lines changed

src/pages/showcase/index.tsx

Lines changed: 155 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, {useState, useMemo, useEffect} from 'react';
1+
import React, { useState, useMemo, useEffect } from 'react';
22
import Layout from '@theme/Layout';
33
import clsx from 'clsx';
44

@@ -21,10 +21,10 @@ import {
2121
import ShowcaseTooltip from './_components/ShowcaseTooltip';
2222

2323
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
24-
import Translate, {translate} from '@docusaurus/Translate';
25-
import {useHistory, useLocation} from '@docusaurus/router';
26-
import {usePluralForm} from '@docusaurus/theme-common';
27-
24+
import Translate, { translate } from '@docusaurus/Translate';
25+
import { useHistory, useLocation } from '@docusaurus/router';
26+
import { usePluralForm } from '@docusaurus/theme-common';
27+
import { motion } from "framer-motion";
2828
import styles from './styles.module.css';
2929

3030
const TITLE =
@@ -40,13 +40,13 @@ type UserState = {
4040
};
4141

4242
function restoreUserState(userState: UserState | null) {
43-
const {scrollTopPosition, focusedElementId} = userState ?? {
43+
const { scrollTopPosition, focusedElementId } = userState ?? {
4444
scrollTopPosition: 0,
4545
focusedElementId: undefined,
4646
};
4747
// @ts-expect-error: if focusedElementId is undefined it returns null
4848
document.getElementById(focusedElementId)?.focus();
49-
window.scrollTo({top: scrollTopPosition});
49+
window.scrollTo({ top: scrollTopPosition });
5050
}
5151

5252
export function prepareUserState(): UserState | undefined {
@@ -116,24 +116,57 @@ function useFilteredUsers() {
116116
function ShowcaseHeader() {
117117
return (
118118
<section className="margin-top--lg margin-bottom--lg text--center">
119-
<h1>{TITLE}</h1>
120-
<p>{DESCRIPTION}</p>
121-
<a
122-
className="button button--primary"
123-
href={EDIT_URL}
124-
target="_blank"
125-
rel="noreferrer"
119+
<motion.h1
120+
initial={{ opacity: 0, x: -150 }}
121+
whileInView={{ opacity: 1, x: 0 }}
122+
viewport={{ once: true }}
123+
transition={{
124+
duration: 1,
125+
type: "spring",
126+
stiffness: 100,
127+
delay: 0.5,
128+
}}
129+
>{TITLE}</motion.h1>
130+
<motion.p
131+
initial={{ opacity: 0, y: 150 }}
132+
whileInView={{ opacity: 1, y: 0 }}
133+
viewport={{ once: true }}
134+
transition={{
135+
duration: 1,
136+
type: "spring",
137+
stiffness: 100,
138+
delay: 0.8,
139+
}}
140+
>{DESCRIPTION}</motion.p>
141+
142+
<motion.div
143+
initial={{ opacity: 0, y: 150 }}
144+
whileInView={{ opacity: 1, y: 0 }}
145+
viewport={{ once: true }}
146+
transition={{
147+
duration: 1,
148+
type: "spring",
149+
stiffness: 100,
150+
delay: 1.1,
151+
}}
126152
>
127-
<Translate id="showcase.header.button">
128-
🌟 Join the CodeHarbarHub Community
129-
</Translate>
130-
</a>
153+
<a
154+
className="button button--primary"
155+
href={EDIT_URL}
156+
target="_blank"
157+
rel="noreferrer"
158+
>
159+
<Translate id="showcase.header.button">
160+
🌟 Join the CodeHarbarHub Community
161+
</Translate>
162+
</a>
163+
</motion.div>
131164
</section>
132165
);
133166
}
134167

135168
function useSiteCountPlural() {
136-
const {selectMessage} = usePluralForm();
169+
const { selectMessage } = usePluralForm();
137170
return (sitesCount: number) =>
138171
selectMessage(
139172
sitesCount,
@@ -144,7 +177,7 @@ function useSiteCountPlural() {
144177
'Pluralized label for the number of sites found on the showcase. Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',
145178
message: '1 site|{sitesCount} sites',
146179
},
147-
{sitesCount},
180+
{ sitesCount },
148181
),
149182
);
150183
}
@@ -156,16 +189,49 @@ function ShowcaseFilters() {
156189
<section className="container margin-top--l margin-bottom--lg">
157190
<div className={clsx('margin-bottom--sm', styles.filterCheckbox)}>
158191
<div>
159-
<h2>
192+
<motion.h2
193+
initial={{ opacity: 0, x: -150 }}
194+
whileInView={{ opacity: 1, x: 0 }}
195+
viewport={{ once: true }}
196+
transition={{
197+
duration: 1,
198+
type: "spring",
199+
stiffness: 100,
200+
delay: 1.4,
201+
}}
202+
>
160203
<Translate id="showcase.filters.title">Filters</Translate>
161-
</h2>
162-
<span>{siteCountPlural(filteredUsers.length)}</span>
204+
</motion.h2>
205+
<motion.div
206+
initial={{ opacity: 0, x: -150 }}
207+
whileInView={{ opacity: 1, x: 0 }}
208+
viewport={{ once: true }}
209+
transition={{
210+
duration: 1,
211+
type: "spring",
212+
stiffness: 100,
213+
delay: 1.4,
214+
}}
215+
>
216+
<span>{siteCountPlural(filteredUsers.length)}</span>
217+
</motion.div>
163218
</div>
164219
<ShowcaseFilterToggle />
165220
</div>
166-
<ul className={clsx('clean-list', styles.checkboxList)}>
221+
<motion.ul
222+
initial={{ opacity: 0}}
223+
whileInView={{ opacity: 1}}
224+
viewport={{ once: true }}
225+
transition={{
226+
duration: 4,
227+
type: "spring",
228+
stiffness: 100,
229+
delay: 1.4,
230+
}}
231+
className={clsx('clean-list', styles.checkboxList)}
232+
>
167233
{TagList.map((tag, i) => {
168-
const {label, description, color} = Tags[tag];
234+
const { label, description, color } = Tags[tag];
169235
const id = `showcase_checkbox_id_${tag}`;
170236

171237
return (
@@ -199,7 +265,7 @@ function ShowcaseFilters() {
199265
</li>
200266
);
201267
})}
202-
</ul>
268+
</motion.ul>
203269
</section>
204270
);
205271
}
@@ -276,32 +342,86 @@ function ShowcaseCards() {
276342
styles.showcaseFavoriteHeader,
277343
)}
278344
>
279-
<h2>
345+
<motion.h2
346+
initial={{ opacity: 0, x: -150 }}
347+
whileInView={{ opacity: 1, x: 0 }}
348+
viewport={{ once: true }}
349+
transition={{
350+
duration: 1,
351+
type: "spring",
352+
stiffness: 100,
353+
delay: 1.4,
354+
}}
355+
>
280356
<Translate id="showcase.favoritesList.title">
281357
Our favorites
282358
</Translate>
283-
</h2>
284-
<FavoriteIcon svgClass={styles.svgIconFavorite} />
359+
</motion.h2>
360+
<motion.h2
361+
initial={{ opacity: 0, x: -150 }}
362+
whileInView={{ opacity: 1, x: 0 }}
363+
viewport={{ once: true }}
364+
transition={{
365+
duration: 1,
366+
type: "spring",
367+
stiffness: 100,
368+
delay: 1.4,
369+
}}
370+
>
371+
<FavoriteIcon svgClass={styles.svgIconFavorite} />
372+
</motion.h2>
285373
<SearchBar />
286374
</div>
287-
<ul
375+
<motion.ul
376+
initial={{ opacity: 0}}
377+
whileInView={{ opacity: 1}}
378+
viewport={{ once: true }}
379+
transition={{
380+
duration: 4,
381+
type: "spring",
382+
stiffness: 100,
383+
delay: 1,
384+
}}
288385
className={clsx('container', 'clean-list', styles.showcaseList)}
289386
>
387+
290388
{favoriteUsers.map((user) => (
291389
<ShowcaseCard key={user.title} user={user} />
292390
))}
293-
</ul>
391+
</motion.ul>
294392
</div>
295393
</div>
296394
<div className="container margin-top--lg">
297-
<h2 className={styles.showcaseHeader}>
395+
<motion.h2
396+
initial={{ opacity: 0, x: -150 }}
397+
whileInView={{ opacity: 1, x: 0 }}
398+
viewport={{ once: true }}
399+
transition={{
400+
duration: 1,
401+
type: "spring",
402+
stiffness: 100,
403+
delay: 0.5,
404+
}}
405+
className={styles.showcaseHeader}
406+
>
298407
<Translate id="showcase.usersList.allUsers">All sites</Translate>
299-
</h2>
300-
<ul className={clsx('clean-list', styles.showcaseList)}>
408+
</motion.h2>
409+
<motion.ul
410+
initial={{ opacity: 0}}
411+
whileInView={{ opacity: 1}}
412+
viewport={{ once: true }}
413+
transition={{
414+
duration: 4,
415+
type: "spring",
416+
stiffness: 100,
417+
delay: 0.8,
418+
}}
419+
className={clsx('clean-list', styles.showcaseList)}
420+
>
301421
{otherUsers.map((user) => (
302422
<ShowcaseCard key={user.title} user={user} />
303423
))}
304-
</ul>
424+
</motion.ul>
305425
</div>
306426
</>
307427
) : (

0 commit comments

Comments
 (0)