Skip to content

Commit 8138c60

Browse files
authored
docs: page transitions (#1136)
## 📜 Description Added animated transitions to documentation. ## 💡 Motivation and Context Inspired by mrousavy/nitro#901 I like animated transitions more than instant one (even on web), so in this PR I add them 👀 ## 📢 Changelog <!-- High level overview of important changes --> <!-- For example: fixed status bar manipulation; added new types declarations; --> <!-- If your changes don't affect one of platform/language below - then remove this platform/language --> ### Docs - added scroll animation; - added cross-page transition between pages (opacity) ## 🤔 How Has This Been Tested? Tested manually on `localhost:3000` ## 📸 Screenshots (if appropriate): https://github.com/user-attachments/assets/6007441b-6f3a-4df2-a1e3-ebb9110655c8 ## 📝 Checklist - [x] CI successfully passed - [x] I added new mocks and corresponding unit-tests if library API was changed
1 parent f2d74b3 commit 8138c60

File tree

3 files changed

+87
-0
lines changed

3 files changed

+87
-0
lines changed

docs/docusaurus.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ const config = {
2121
onBrokenMarkdownLinks: "warn",
2222
favicon: "favicon.ico",
2323

24+
// Runs animations on page change
25+
clientModules: ["./src/modules/page-transitions.ts"],
26+
2427
// GitHub pages deployment config.
2528
// If you aren't using GitHub pages, you don't need these.
2629
organizationName: "kirillzyusko",

docs/src/css/custom.css

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,3 +325,22 @@ h3 .label {
325325
height: 400px;
326326
margin-bottom: 24px;
327327
}
328+
329+
html {
330+
scroll-behavior: smooth;
331+
}
332+
333+
@media (prefers-reduced-motion: no-preference) {
334+
.doc-fade--run {
335+
animation: doc-fade-in 250ms ease-in-out;
336+
will-change: opacity, transform, filter;
337+
}
338+
@keyframes doc-fade-in {
339+
from {
340+
opacity: 0;
341+
}
342+
to {
343+
opacity: 1;
344+
}
345+
}
346+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import type { ClientModule } from "@docusaurus/types";
2+
3+
function getDocsMain(): HTMLElement | null {
4+
// match "docMainContainer_<hash>" no matter where it appears in class attr
5+
return document.querySelector(
6+
'main[class^="docMainContainer_"], main[class*=" docMainContainer_"]',
7+
);
8+
}
9+
10+
function scrollIntoView(element: HTMLElement) {
11+
// let layout settle first
12+
requestAnimationFrame(() => {
13+
element.scrollIntoView({ behavior: "smooth", block: "start" });
14+
});
15+
}
16+
17+
function runFadeInAnimation(element: HTMLElement) {
18+
element.classList.remove("doc-fade--run");
19+
void element.offsetWidth; // reflow
20+
requestAnimationFrame(() => {
21+
element.classList.add("doc-fade--run");
22+
});
23+
}
24+
25+
const client: ClientModule = {
26+
onRouteDidUpdate({ location, previousLocation }) {
27+
if (!previousLocation) {
28+
// first mount should not play an animation
29+
return;
30+
}
31+
const pathChanged = location.pathname !== previousLocation.pathname;
32+
const hashChanged = location.hash !== previousLocation.hash;
33+
34+
if (!hashChanged && !pathChanged) {
35+
// nothing changed, do nothing
36+
return;
37+
}
38+
39+
const mainElement = getDocsMain();
40+
41+
if (!mainElement) {
42+
// we're not on our docs page
43+
return;
44+
}
45+
46+
if (hashChanged && !pathChanged) {
47+
// anchor changed - smoothly scroll to new anchor
48+
const id = decodeURIComponent(location.hash.replace(/^#/, ""));
49+
const target = id ? document.getElementById(id) : null;
50+
51+
if (target) {
52+
scrollIntoView(target);
53+
}
54+
55+
return;
56+
}
57+
58+
if (pathChanged) {
59+
// page changed - run fade-in animation
60+
runFadeInAnimation(mainElement);
61+
}
62+
},
63+
};
64+
65+
export default client;

0 commit comments

Comments
 (0)