Skip to content

Commit 8d74f24

Browse files
author
nedtwigg
committed
Claude Code simplify: extract clamp01 helper, flatten icon-rise/hook-fade logic, trim verbose comments
1 parent 910f264 commit 8d74f24

1 file changed

Lines changed: 25 additions & 42 deletions

File tree

website/src/pages/Home.tsx

Lines changed: 25 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ const ASTERISK_THRESHOLD = 0.65;
1919
* The video keeps scrubbing underneath. */
2020
const UNPIN_THRESHOLD = 0.8;
2121

22+
/** Clamp a value to 0–1. */
23+
const clamp01 = (v: number) => Math.min(1, Math.max(0, v));
24+
2225
const PILL =
2326
"inline-block px-4 py-1.5 rounded-md border border-[var(--color-caramel)]/30 text-[var(--color-caramel)] text-sm font-display hover:bg-[var(--color-caramel)]/10 hover:border-[var(--color-caramel)]/60 hover:-translate-y-0.5 active:translate-y-0 transition-all duration-150";
2427

@@ -99,13 +102,10 @@ function Home() {
99102
const runwayScroll = -rect.top;
100103
const runwayHeight = runway.offsetHeight - window.innerHeight;
101104
const fraction = runwayHeight > 0
102-
? Math.min(1, Math.max(0, runwayScroll / runwayHeight))
105+
? clamp01(runwayScroll / runwayHeight)
103106
: 0;
104107

105-
// Compute rendered video content height (object-contain fits within container
106-
// while preserving the video's native aspect ratio). This is the icon's actual
107-
// on-screen size and drives the icon rise distance, the hook fade timing, and
108-
// the video scrub start point.
108+
// Rendered icon height (object-contain preserves aspect ratio within container).
109109
const naturalAspect = video.videoWidth && video.videoHeight
110110
? video.videoWidth / video.videoHeight
111111
: 1.22; // fallback before metadata loads
@@ -115,16 +115,13 @@ function Home() {
115115
: video.offsetHeight; // height-limited
116116
const initialOffset = iconHeight * ICON_INITIAL_HIDE_FRAC;
117117

118-
// Scrub video: hold on frame 0 while the icon is still rising into position.
119-
// Once the icon reaches its static position (runwayScroll >= initialOffset),
120-
// scrub the remaining scroll range across the video's duration.
118+
// Scrub video: hold frame 0 during icon rise, then scrub remaining range.
121119
if (video.duration && isFinite(video.duration)) {
122120
if (runwayScroll < initialOffset) {
123121
video.currentTime = 0;
124122
} else {
125-
const videoRunway = runwayHeight - initialOffset;
126-
const videoProgress = videoRunway > 0
127-
? Math.min(1, (runwayScroll - initialOffset) / videoRunway)
123+
const videoProgress = (runwayHeight - initialOffset) > 0
124+
? clamp01((runwayScroll - initialOffset) / (runwayHeight - initialOffset))
128125
: 0;
129126
video.currentTime = videoProgress * video.duration;
130127
}
@@ -134,26 +131,24 @@ function Home() {
134131
for (let i = 0; i < WORD_THRESHOLDS.length; i++) {
135132
const el = wordRefs[i].current;
136133
if (!el) continue;
137-
const progress = Math.min(1, Math.max(0,
134+
const progress = clamp01(
138135
(fraction - WORD_THRESHOLDS[i]) / 0.08
139-
));
136+
);
140137
el.style.opacity = String(progress);
141138
el.style.transform = `translateY(${(1 - progress) * 12}px)`;
142139
}
143140

144141
// Asterisk + footnote
145-
const astProgress = Math.min(1, Math.max(0,
142+
const astProgress = clamp01(
146143
(fraction - ASTERISK_THRESHOLD) / 0.08
147-
));
144+
);
148145
if (asteriskRef.current) asteriskRef.current.style.opacity = String(astProgress);
149146
if (footnoteRef.current) footnoteRef.current.style.opacity = String(astProgress * 0.7);
150147

151-
// (Hook fade handled below, after iconHeight is computed for the icon rise.)
152-
153148
// Header: reveal brand + background at unpin threshold
154-
const headerProgress = Math.min(1, Math.max(0,
149+
const headerProgress = clamp01(
155150
(fraction - UNPIN_THRESHOLD) / 0.08
156-
));
151+
);
157152
if (headerBrandRef.current) {
158153
headerBrandRef.current.style.opacity = String(headerProgress);
159154
}
@@ -169,35 +164,23 @@ function Home() {
169164
const slideAmount = Math.max(0, runwayScroll - contentEnterScroll);
170165

171166
// Video transform combines two behaviors:
172-
// 1. Icon-rise (runwayScroll 0 → initialOffset px): 1:1 with scroll.
173-
// At load the icon is translated +initialOffset so only the top third
174-
// is visible; each pixel of scroll lifts it by one pixel until fully
175-
// in view.
176-
// 2. Existing unpin slide (fraction > UNPIN_THRESHOLD): translate up with
177-
// content as hero unpins.
178-
let videoTranslateY = 0;
179-
let iconCurrentOffset = 0;
180-
if (runwayScroll < initialOffset) {
181-
iconCurrentOffset = initialOffset - runwayScroll;
182-
videoTranslateY = iconCurrentOffset;
183-
} else if (slideAmount > 0) {
184-
videoTranslateY = -Math.round(slideAmount);
185-
}
167+
// 1. Icon-rise (runwayScroll 0 → initialOffset): translate down so only
168+
// the top third is visible; scroll lifts it 1:1 until fully in view.
169+
// 2. Unpin slide (fraction > UNPIN_THRESHOLD): translate up with content.
170+
const iconCurrentOffset = Math.max(0, initialOffset - runwayScroll);
171+
const videoTranslateY = iconCurrentOffset > 0
172+
? iconCurrentOffset
173+
: slideAmount > 0 ? -Math.round(slideAmount) : 0;
186174
video.style.transform = videoTranslateY !== 0
187175
? `translateY(${Math.round(videoTranslateY)}px)`
188176
: '';
189177

190-
// Hook text: holds visible until the bottom ~10% of the icon enters the
191-
// viewport, then fades out as the icon completes its rise. Tied to icon
192-
// position (not scroll fraction) so the timing matches 1:1 icon motion.
178+
// Hook text: visible until the icon nearly finishes rising, then fades out.
193179
if (hookRef.current) {
194180
const remainingHidden = iconHeight > 0 ? iconCurrentOffset / iconHeight : 0;
195-
let fadeProgress = 0;
196-
if (runwayScroll >= initialOffset) {
197-
fadeProgress = 1;
198-
} else if (remainingHidden < HOOK_FADE_REMAINING) {
199-
fadeProgress = 1 - remainingHidden / HOOK_FADE_REMAINING;
200-
}
181+
const fadeProgress = iconCurrentOffset === 0
182+
? 1
183+
: clamp01(1 - remainingHidden / HOOK_FADE_REMAINING);
201184
hookRef.current.style.opacity = String(1 - fadeProgress);
202185
hookRef.current.style.transform = `translateY(${-fadeProgress * 24}px)`;
203186
}

0 commit comments

Comments
 (0)