@@ -13,7 +13,7 @@ const backgroundClass = background === "light" ? light : dark;
1313---
1414
1515<div
16- class:list ={ [" flex flex-col" , backgroundClass ]}
16+ class:list ={ [" section-bg flex flex-col" , background ]}
1717 data-background ={ background }
1818 {... rest }
1919>
@@ -27,3 +27,98 @@ const backgroundClass = background === "light" ? light : dark;
2727 <slot />
2828 </section >
2929</div >
30+
31+ <style >
32+ @reference "../styles/global.css";
33+
34+ .light {
35+ @apply bg-light-20 text-brown-100;
36+ }
37+
38+ .dark {
39+ @apply bg-brown-90 text-white;
40+ }
41+ </style >
42+
43+ <script >
44+ function setupSectionAnimation() {
45+ // skip first section as it is the header
46+ const sections = [
47+ ...document.querySelectorAll<HTMLElement>(".section-bg"),
48+ ].slice(1);
49+
50+ let ticking = false;
51+
52+ function updateSectionVisibility(sectionIndex: number) {
53+ const section = sections[sectionIndex];
54+ const nextSection = sections.slice(sectionIndex + 1).find((section) => {
55+ return section.offsetHeight > 0;
56+ });
57+
58+ if (!nextSection) {
59+ return;
60+ }
61+
62+ const sectionBackground = section.dataset.background;
63+
64+ const rect = section.getBoundingClientRect();
65+
66+ const isBottomVisible = rect.bottom - window.innerHeight < 0;
67+
68+ const windowHeight = window.innerHeight * 0.35;
69+
70+ if (!isBottomVisible || section.offsetHeight === 0) {
71+ return;
72+ }
73+
74+ const progress = Math.max(
75+ Math.min((rect.bottom - windowHeight) / windowHeight, 1),
76+ 0,
77+ );
78+
79+ if (nextSection.dataset.background === sectionBackground) {
80+ return;
81+ }
82+
83+ const fromColor =
84+ sectionBackground === "light"
85+ ? "var(--color-light-20)"
86+ : "var(--color-brown-90)";
87+ const toColor =
88+ sectionBackground === "light"
89+ ? "var(--color-brown-90)"
90+ : "var(--color-light-20)";
91+
92+ section.dataset.progress = progress.toString();
93+ section.style.backgroundColor = `color-mix(in oklab, ${fromColor} ${Math.round(progress * 100)}%, ${toColor})`;
94+
95+ nextSection.dataset.progress = (1 - progress).toString();
96+ nextSection.style.backgroundColor = `color-mix(in oklab, ${toColor} ${Math.round((1 - progress) * 100)}%, ${fromColor})`;
97+ }
98+
99+ function handleScroll() {
100+ if (!ticking) {
101+ requestAnimationFrame(() => {
102+ sections.forEach((_, i) => {
103+ updateSectionVisibility(i);
104+ });
105+
106+ ticking = false;
107+ });
108+
109+ ticking = true;
110+ }
111+ }
112+
113+ handleScroll();
114+ window.addEventListener("scroll", handleScroll);
115+ window.addEventListener("resize", handleScroll);
116+ }
117+
118+ function setup() {
119+ setupSectionAnimation();
120+ }
121+
122+ document.addEventListener("DOMContentLoaded", setup);
123+ document.addEventListener("astro:page-load", setup);
124+ </script >
0 commit comments