Skip to content

Commit d72f176

Browse files
committed
Improve story detail pages UX: add scroll-to-top, other stories suggestions, and connect CTA sections. Update story card overlays with transparent backgrounds. Fix Rocky Mountain story category to National Parks.
1 parent 9caf28a commit d72f176

5 files changed

Lines changed: 195 additions & 27 deletions

File tree

src/components/pages/Impact.tsx

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -127,17 +127,19 @@ export function Impact() {
127127
>
128128
<div className="surface-elevated rounded-2xl overflow-hidden transition-all duration-300 hover:shadow-xl hover:scale-[1.02]">
129129
{/* Thumbnail */}
130-
<div className="relative aspect-video overflow-hidden bg-gradient-to-br from-gray-100 to-gray-200">
131-
<img
132-
src={story.thumbnail}
133-
alt={`${story.title} - Story thumbnail`}
134-
className="relative z-0 w-full h-full object-cover group-hover:scale-110 transition-transform duration-500"
135-
/>
136-
<div className="absolute inset-0 z-10 bg-gradient-to-t from-black/60 via-black/20 to-transparent" />
137-
<div className="absolute bottom-4 left-4 z-50 pointer-events-none">
138-
<div className="flex items-center gap-2 bg-black/95 backdrop-blur-sm px-4 py-2 rounded-full shadow-2xl pointer-events-auto border border-yellow-400/40">
139-
<story.icon size={18} className="text-yellow-300 flex-shrink-0 drop-shadow-[0_0_6px_rgba(253,224,71,0.9)]" />
140-
<span className="text-yellow-300 text-sm font-bold drop-shadow-[0_0_6px_rgba(253,224,71,0.9)]">{story.date}</span>
130+
<div className="relative aspect-video bg-gradient-to-br from-gray-100 to-gray-200">
131+
<div className="absolute inset-0 overflow-hidden">
132+
<img
133+
src={story.thumbnail}
134+
alt={`${story.title} - Story thumbnail`}
135+
className="relative z-0 w-full h-full object-cover group-hover:scale-110 transition-transform duration-500"
136+
/>
137+
<div className="absolute inset-0 z-10 bg-gradient-to-t from-black/40 via-black/10 to-transparent pointer-events-none" />
138+
</div>
139+
<div className="absolute top-4 right-4 z-[100]" style={{ zIndex: 100 }}>
140+
<div className="flex items-center gap-2 px-3 py-2 bg-black/40 backdrop-blur-sm rounded-lg">
141+
<Calendar size={16} className="text-white" />
142+
<span className="text-sm font-normal text-white">{story.date}</span>
141143
</div>
142144
</div>
143145
</div>

src/components/pages/StoriesOfAdventure.tsx

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -227,17 +227,19 @@ export function StoriesOfAdventure() {
227227
>
228228
<div className="surface-elevated rounded-2xl overflow-hidden transition-all duration-300 hover:shadow-xl hover:scale-[1.02]">
229229
{/* Thumbnail */}
230-
<div className="relative aspect-video overflow-hidden bg-gradient-to-br from-gray-100 to-gray-200">
231-
<img
232-
src={getImageUrl(story.thumbnail)}
233-
alt={`${story.title} - Story thumbnail`}
234-
className="relative z-0 w-full h-full object-cover group-hover:scale-110 transition-transform duration-500"
235-
/>
236-
<div className="absolute inset-0 z-10 bg-gradient-to-t from-black/60 via-black/20 to-transparent" />
237-
<div className="absolute bottom-4 left-4 z-50 pointer-events-none">
238-
<div className="flex items-center gap-2 bg-black/95 backdrop-blur-sm px-4 py-2 rounded-full shadow-2xl pointer-events-auto border border-yellow-400/40">
239-
<story.icon size={18} className="text-yellow-300 flex-shrink-0 drop-shadow-[0_0_6px_rgba(253,224,71,0.9)]" />
240-
<span className="text-yellow-300 text-sm font-bold drop-shadow-[0_0_6px_rgba(253,224,71,0.9)]">{story.date}</span>
230+
<div className="relative aspect-video bg-gradient-to-br from-gray-100 to-gray-200">
231+
<div className="absolute inset-0 overflow-hidden">
232+
<img
233+
src={getImageUrl(story.thumbnail)}
234+
alt={`${story.title} - Story thumbnail`}
235+
className="relative z-0 w-full h-full object-cover group-hover:scale-110 transition-transform duration-500"
236+
/>
237+
<div className="absolute inset-0 z-10 bg-gradient-to-t from-black/40 via-black/10 to-transparent pointer-events-none" />
238+
</div>
239+
<div className="absolute top-4 right-4 z-[100]" style={{ zIndex: 100 }}>
240+
<div className="flex items-center gap-2 px-3 py-2 bg-black/40 backdrop-blur-sm rounded-lg">
241+
<Calendar size={16} className="text-white" />
242+
<span className="text-sm font-normal text-white">{story.date}</span>
241243
</div>
242244
</div>
243245
</div>

src/components/pages/StoryDetail.tsx

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,11 @@ export function StoryDetail() {
7575
useEffect(() => {
7676
if (!selectedStory) {
7777
navigate('/impact');
78+
return;
7879
}
79-
}, [selectedStory, navigate]);
80+
// Scroll to top when story loads
81+
window.scrollTo({ top: 0, behavior: 'instant' });
82+
}, [selectedStory, navigate, storyId]);
8083

8184
// Update meta tags for social sharing
8285
useMetaTags({
@@ -238,8 +241,83 @@ export function StoryDetail() {
238241
)}
239242
</motion.article>
240243

244+
{/* Other Stories Section */}
245+
{stories.filter(story => story.id !== storyId).length > 0 && (
246+
<section className="py-16 lg:py-24 mt-16 border-t">
247+
<div className="max-w-7xl mx-auto px-6 lg:px-12">
248+
<motion.div
249+
initial={{ opacity: 0, y: 30 }}
250+
whileInView={{ opacity: 1, y: 0 }}
251+
viewport={{ once: true }}
252+
transition={{ duration: 0.8 }}
253+
className="mb-12"
254+
>
255+
<h2 className="text-3xl lg:text-4xl tracking-tight mb-4">
256+
Other Stories of Impact
257+
</h2>
258+
<p className="text-lg text-muted-foreground">
259+
Explore more stories of meaningful change
260+
</p>
261+
</motion.div>
262+
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
263+
{stories
264+
.filter(story => story.id !== storyId)
265+
.slice(0, 3)
266+
.map((story, index) => (
267+
<Link
268+
key={story.id}
269+
to={`/impact/${story.id}`}
270+
className="group"
271+
>
272+
<motion.div
273+
initial={{ opacity: 0, y: 30 }}
274+
whileInView={{ opacity: 1, y: 0 }}
275+
viewport={{ once: true }}
276+
transition={{ duration: 0.6, delay: index * 0.1 }}
277+
className="cursor-pointer"
278+
>
279+
<div className="surface-elevated rounded-2xl overflow-hidden transition-all duration-300 hover:shadow-xl hover:scale-[1.02]">
280+
{/* Thumbnail */}
281+
<div className="relative aspect-video bg-gradient-to-br from-gray-100 to-gray-200">
282+
<div className="absolute inset-0 overflow-hidden">
283+
<img
284+
src={story.thumbnail}
285+
alt={`${story.title} - Story thumbnail`}
286+
className="relative z-0 w-full h-full object-cover group-hover:scale-110 transition-transform duration-500"
287+
/>
288+
<div className="absolute inset-0 z-10 bg-gradient-to-t from-black/40 via-black/10 to-transparent pointer-events-none" />
289+
</div>
290+
<div className="absolute top-4 right-4 z-[100]" style={{ zIndex: 100 }}>
291+
<div className="flex items-center gap-2 px-3 py-2 bg-black/40 backdrop-blur-sm rounded-lg">
292+
<Calendar size={16} className="text-white" />
293+
<span className="text-sm font-normal text-white">{story.date}</span>
294+
</div>
295+
</div>
296+
</div>
297+
298+
{/* Content */}
299+
<div className="p-6 space-y-3">
300+
<h3 className="text-xl font-semibold tracking-tight group-hover:text-blue-600 transition-colors">
301+
{story.title}
302+
</h3>
303+
<p className="text-muted-foreground line-clamp-3">
304+
{story.excerpt}
305+
</p>
306+
<div className="flex items-center gap-2 text-sm text-muted-foreground pt-2">
307+
<span className="group-hover:text-blue-600 transition-colors">{labels.readMore}</span>
308+
</div>
309+
</div>
310+
</div>
311+
</motion.div>
312+
</Link>
313+
))}
314+
</div>
315+
</div>
316+
</section>
317+
)}
318+
241319
{/* Connect CTA Section */}
242-
<section className="py-16 lg:py-24 bg-gradient-to-b from-white to-blue-50/20 mt-16">
320+
<section className="py-16 lg:py-24 bg-gradient-to-b from-white to-blue-50/20">
243321
<div className="max-w-4xl mx-auto px-6 lg:px-12 text-center">
244322
<motion.div
245323
initial={{ opacity: 0, y: 30 }}

src/components/pages/StoryOfAdventureDetail.tsx

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ export function StoryOfAdventureDetail() {
9090
return;
9191
}
9292

93+
// Scroll to top when story loads
94+
window.scrollTo({ top: 0, behavior: 'instant' });
95+
9396
// Update meta tags immediately for better crawler support
9497
const baseUrl = window.location.origin;
9598
const storyImage = selectedStory.content.images && selectedStory.content.images.length > 0
@@ -132,7 +135,7 @@ export function StoryOfAdventureDetail() {
132135
updateMeta('twitter:description', selectedStory.excerpt, false);
133136
updateMeta('twitter:image', imageUrl, false);
134137
updateMeta('description', selectedStory.excerpt, false);
135-
}, [selectedStory, navigate]);
138+
}, [selectedStory, navigate, storyId]);
136139

137140
// Also use the hook for React-based updates
138141
useMetaTags({
@@ -334,8 +337,91 @@ export function StoryOfAdventureDetail() {
334337
<Comments storyId={storyId || ''} />
335338
</motion.article>
336339

340+
{/* Other Stories Section */}
341+
{stories.filter(story => story.id !== storyId).length > 0 && (
342+
<section className="py-16 lg:py-24 mt-16 border-t">
343+
<div className="max-w-7xl mx-auto px-6 lg:px-12">
344+
<motion.div
345+
initial={{ opacity: 0, y: 30 }}
346+
whileInView={{ opacity: 1, y: 0 }}
347+
viewport={{ once: true }}
348+
transition={{ duration: 0.8 }}
349+
className="mb-12"
350+
>
351+
<h2 className="text-3xl lg:text-4xl tracking-tight mb-4">
352+
Other Stories of Adventure
353+
</h2>
354+
<p className="text-lg text-muted-foreground">
355+
Explore more adventures and stories
356+
</p>
357+
</motion.div>
358+
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
359+
{stories
360+
.filter(story => story.id !== storyId)
361+
.slice(0, 3)
362+
.map((story, index) => {
363+
const storyImages = story.content.images || [];
364+
const firstImage = storyImages.length > 0
365+
? (typeof storyImages[0] === 'string' ? storyImages[0] : storyImages[0].url)
366+
: null;
367+
const thumbnail = firstImage || story.thumbnail;
368+
369+
return (
370+
<Link
371+
key={story.id}
372+
to={`/storiesofadventure/${story.id}`}
373+
className="group"
374+
>
375+
<motion.div
376+
initial={{ opacity: 0, y: 30 }}
377+
whileInView={{ opacity: 1, y: 0 }}
378+
viewport={{ once: true }}
379+
transition={{ duration: 0.6, delay: index * 0.1 }}
380+
className="cursor-pointer"
381+
>
382+
<div className="surface-elevated rounded-2xl overflow-hidden transition-all duration-300 hover:shadow-xl hover:scale-[1.02]">
383+
{/* Thumbnail */}
384+
<div className="relative aspect-video bg-gradient-to-br from-gray-100 to-gray-200">
385+
<div className="absolute inset-0 overflow-hidden">
386+
<img
387+
src={getImageUrl(thumbnail)}
388+
alt={`${story.title} - Story thumbnail`}
389+
className="relative z-0 w-full h-full object-cover group-hover:scale-110 transition-transform duration-500"
390+
/>
391+
<div className="absolute inset-0 z-10 bg-gradient-to-t from-black/40 via-black/10 to-transparent pointer-events-none" />
392+
</div>
393+
<div className="absolute top-4 right-4 z-[100]" style={{ zIndex: 100 }}>
394+
<div className="flex items-center gap-2 px-3 py-2 bg-black/40 backdrop-blur-sm rounded-lg">
395+
<Calendar size={16} className="text-white" />
396+
<span className="text-sm font-normal text-white">{story.date}</span>
397+
</div>
398+
</div>
399+
</div>
400+
401+
{/* Content */}
402+
<div className="p-6 space-y-3">
403+
<h3 className="text-xl font-semibold tracking-tight group-hover:text-blue-600 transition-colors">
404+
{story.title}
405+
</h3>
406+
<p className="text-muted-foreground line-clamp-3">
407+
{story.excerpt}
408+
</p>
409+
<div className="flex items-center gap-2 text-sm text-muted-foreground pt-2">
410+
<span className="group-hover:text-blue-600 transition-colors">{labels.readMore}</span>
411+
</div>
412+
</div>
413+
</div>
414+
</motion.div>
415+
</Link>
416+
);
417+
})}
418+
</div>
419+
</div>
420+
</section>
421+
)}
422+
337423
{/* Connect CTA Section */}
338-
<section className="py-16 lg:py-24 bg-gradient-to-b from-white to-blue-50/20 mt-16">
424+
<section className="py-16 lg:py-24 bg-gradient-to-b from-white to-blue-50/20">
339425
<div className="max-w-4xl mx-auto px-6 lg:px-12 text-center">
340426
<motion.div
341427
initial={{ opacity: 0, y: 30 }}

src/data/content.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1171,7 +1171,7 @@ const contentData = {
11711171
"excerpt": "Some dreams begin quietly over conversations, borrowed imaginations, and the courage of someone who goes first.",
11721172
"date": "Dec 2025",
11731173
"icon": "Heart",
1174-
"theme": "yellow",
1174+
"theme": "green",
11751175
"content": {
11761176
"description": [
11771177
"Some dreams begin quietly over conversations. They come from borrowed imaginations and the courage of someone who goes first.",

0 commit comments

Comments
 (0)