Skip to content

Commit 6d12d3f

Browse files
committed
style: tweak hero view for discover and worlds:id pages
1 parent 93376b5 commit 6d12d3f

2 files changed

Lines changed: 172 additions & 23 deletions

File tree

frontend/components/discover/FeaturedWorldHero.tsx

Lines changed: 163 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,27 +50,26 @@ export default function FeaturedWorldHero({ world }: FeaturedWorldHeroProps) {
5050
? world.image_url
5151
: world.portrait_url;
5252

53+
const currentImageType = world.active_image_type;
54+
5355
return (
54-
<section className="relative h-[500px] w-full overflow-hidden rounded-3xl">
55-
{/* Background Image with Overlay */}
56-
{displayImage && (
57-
<>
56+
<>
57+
{/* World Scene Layout - Full width with overlay */}
58+
{displayImage && currentImageType === "world_scene" && (
59+
<section className="relative h-[500px] w-full overflow-hidden rounded-3xl">
5860
<div className="absolute inset-0">
5961
<Image
6062
fill
6163
src={displayImage}
6264
alt={world.full_story.quest?.title || "Featured world"}
63-
className="h-full object-cover object-top"
65+
className="h-full object-cover object-center"
6466
priority
6567
/>
6668
</div>
67-
<div className="absolute inset-0 bg-gradient-to-r from-black/90 via-black/60 to-transparent" />
68-
<div className="absolute inset-0 bg-gradient-to-t from-black/90 via-transparent to-transparent" />
69-
</>
70-
)}
69+
<div className="absolute inset-0 bg-gradient-to-r from-black/70 via-black/40 to-transparent" />
70+
<div className="absolute inset-0 bg-gradient-to-t from-black/70 via-transparent to-transparent" />
7171

72-
{/* Content */}
73-
<div className="relative z-10 flex h-full flex-col justify-between p-6 md:p-8">
72+
<div className="relative z-10 flex h-full flex-col justify-between p-6 md:p-8">
7473
{/* Featured Badge - Top */}
7574
<div className="flex items-center gap-2">
7675
<Sparkles className="text-primary h-4 w-4" />
@@ -129,7 +128,158 @@ export default function FeaturedWorldHero({ world }: FeaturedWorldHeroProps) {
129128
Explore This World
130129
</PrimaryButton>
131130
</div>
132-
</div>
133-
</section>
131+
</div>
132+
</section>
133+
)}
134+
135+
{/* Portrait Layout - Responsive: Stack on mobile, split on desktop */}
136+
{displayImage && currentImageType === "portrait" && (
137+
<section className="relative w-full overflow-hidden rounded-3xl">
138+
{/* Mobile: Stacked layout */}
139+
<div className="flex flex-col md:hidden">
140+
{/* Portrait on top */}
141+
<div className="relative aspect-[4/3] w-full">
142+
<Image
143+
fill
144+
src={displayImage}
145+
alt={world.full_story.quest?.title || "Featured world"}
146+
className="object-cover object-center"
147+
priority
148+
/>
149+
</div>
150+
151+
{/* Content below */}
152+
<div className="bg-background flex flex-col gap-4 p-6">
153+
{/* Featured Badge */}
154+
<div className="flex items-center gap-2">
155+
<Sparkles className="text-primary h-4 w-4" />
156+
<span className="text-primary text-xs font-semibold tracking-wider uppercase">
157+
Featured World
158+
</span>
159+
</div>
160+
161+
{/* Theme Badge */}
162+
{themeOption && (
163+
<Badge variant="outline" className="w-fit">
164+
{themeOption.label}
165+
</Badge>
166+
)}
167+
168+
{/* Title */}
169+
<h1 className="text-2xl leading-tight font-bold">
170+
{world.full_story.quest?.title || "Untitled World"}
171+
</h1>
172+
173+
{/* Description */}
174+
<p className="line-clamp-3 text-sm text-muted-foreground">
175+
{world.full_story.quest?.description || "No description available"}
176+
</p>
177+
178+
{/* Meta Info */}
179+
<div className="flex flex-wrap items-center gap-4 text-xs text-muted-foreground">
180+
<div className="flex items-center gap-1">
181+
<span>by {world.user_name || "Unknown"}</span>
182+
</div>
183+
<div className="flex items-center gap-1">
184+
<Star className="h-3 w-3 fill-amber-400 text-amber-400" />
185+
<span>{world.rating?.toFixed(1)}</span>
186+
</div>
187+
{world.active_sessions !== undefined &&
188+
world.active_sessions > 0 && (
189+
<div className="flex items-center gap-1">
190+
<Users className="h-3 w-3 text-green-400" />
191+
<span className="text-green-400">
192+
{world.active_sessions} Active
193+
</span>
194+
</div>
195+
)}
196+
</div>
197+
198+
{/* CTA */}
199+
<PrimaryButton
200+
onClick={() => router.push(`/worlds/${world.theme}/${world.id}`)}
201+
className="w-fit text-sm"
202+
>
203+
Explore This World
204+
</PrimaryButton>
205+
</div>
206+
</div>
207+
208+
{/* Desktop: Split layout */}
209+
<div className="relative hidden h-[500px] md:block">
210+
{/* Background gradient */}
211+
<div className="from-background via-background/95 to-muted/90 absolute inset-0 bg-gradient-to-r" />
212+
213+
{/* Portrait on left side */}
214+
<div className="absolute top-0 bottom-0 left-0 w-1/2">
215+
<Image
216+
fill
217+
src={displayImage}
218+
alt={world.full_story.quest?.title || "Featured world"}
219+
className="object-cover object-center"
220+
priority
221+
/>
222+
<div className="to-background absolute inset-0 bg-gradient-to-r from-transparent" />
223+
</div>
224+
225+
{/* Content on right side */}
226+
<div className="absolute inset-y-0 right-0 flex w-1/2 flex-col justify-center gap-4 px-8 lg:px-12">
227+
{/* Featured Badge */}
228+
<div className="flex items-center gap-2">
229+
<Sparkles className="text-primary h-4 w-4" />
230+
<span className="text-primary text-xs font-semibold tracking-wider uppercase">
231+
Featured World
232+
</span>
233+
</div>
234+
235+
{/* Theme Badge */}
236+
{themeOption && (
237+
<Badge variant="outline" className="w-fit">
238+
{themeOption.label}
239+
</Badge>
240+
)}
241+
242+
{/* Title */}
243+
<h1 className="text-2xl leading-tight font-bold lg:text-3xl">
244+
{world.full_story.quest?.title || "Untitled World"}
245+
</h1>
246+
247+
{/* Description */}
248+
<p className="line-clamp-3 text-sm text-muted-foreground">
249+
{world.full_story.quest?.description || "No description available"}
250+
</p>
251+
252+
{/* Meta Info */}
253+
<div className="flex flex-wrap items-center gap-4 text-xs text-muted-foreground">
254+
<div className="flex items-center gap-1">
255+
<span>by {world.user_name || "Unknown"}</span>
256+
</div>
257+
<div className="flex items-center gap-1">
258+
<Star className="h-3 w-3 fill-amber-400 text-amber-400" />
259+
<span>{world.rating?.toFixed(1)}</span>
260+
</div>
261+
{world.active_sessions !== undefined &&
262+
world.active_sessions > 0 && (
263+
<div className="flex items-center gap-1">
264+
<Users className="h-3 w-3 text-green-400" />
265+
<span className="text-green-400">
266+
{world.active_sessions} Active
267+
</span>
268+
</div>
269+
)}
270+
</div>
271+
272+
{/* CTA */}
273+
<PrimaryButton
274+
onClick={() => router.push(`/worlds/${world.theme}/${world.id}`)}
275+
className="w-fit text-sm lg:text-base"
276+
>
277+
Explore This World
278+
</PrimaryButton>
279+
</div>
280+
</div>
281+
</section>
282+
)}
283+
</>
134284
);
135285
}

frontend/components/single-world/SingleWorldHero.tsx

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,8 @@ export default function SingleWorldHero({
198198
</div>
199199

200200
{/* Dark gradient overlays for text readability */}
201-
<div className="absolute inset-0 bg-gradient-to-r from-black/90 via-black/60 to-transparent" />
202-
<div className="absolute inset-0 bg-gradient-to-t from-black/90 via-transparent to-transparent" />
201+
<div className="absolute inset-0 bg-gradient-to-r from-black/70 via-black/40 to-transparent" />
202+
<div className="absolute inset-0 bg-gradient-to-t from-black/70 via-transparent to-transparent" />
203203

204204
{/* Title overlaid on image */}
205205
<div className="relative z-10 flex h-full flex-col justify-end p-6 md:p-8">
@@ -213,17 +213,16 @@ export default function SingleWorldHero({
213213
{displayImage && currentImageType === "portrait" && (
214214
// Split layout for character portraits
215215
<div className="hero-animate border-primary/20 relative aspect-[21/9] overflow-hidden rounded-xl border-2 shadow-2xl">
216-
{imageLoading && (
217-
<div className="bg-muted/30 absolute inset-0 flex items-center justify-center">
218-
<Loader2 className="text-muted-foreground h-12 w-12 animate-spin" />
219-
</div>
220-
)}
221-
222216
{/* Background gradient */}
223217
<div className="from-background via-background/95 to-muted/90 absolute inset-0 bg-gradient-to-r" />
224218

225219
{/* Portrait on left side */}
226220
<div className="absolute top-0 bottom-0 left-0 w-1/2">
221+
{imageLoading && (
222+
<div className="bg-muted/30 absolute inset-0 flex items-center justify-center">
223+
<Loader2 className="text-muted-foreground h-12 w-12 animate-spin" />
224+
</div>
225+
)}
227226
<Image
228227
key={displayImage}
229228
src={displayImage}
@@ -241,7 +240,7 @@ export default function SingleWorldHero({
241240

242241
{/* Title on right side */}
243242
<div className="absolute inset-y-0 right-0 flex w-1/2 items-center px-8 md:px-12">
244-
<h1 className="font-heading text-foreground text-3xl font-bold md:text-4xl lg:text-5xl">
243+
<h1 className="font-heading text-foreground text-xl font-bold md:text-3xl lg:text-4xl">
245244
{parsedStory.quest?.title}
246245
</h1>
247246
</div>
@@ -263,7 +262,7 @@ export default function SingleWorldHero({
263262
{/* Image toggle - show only if world scene exists */}
264263
{isOwner && currentWorldImageUrl && (
265264
<div className="border-border bg-background flex items-center gap-2 rounded-md border px-3 py-2">
266-
<ImageIcon className="text-muted-foreground h-4 w-4" />
265+
<ImageIcon className="h-4 w-4" />
267266
<Label
268267
htmlFor="image-toggle"
269268
className="cursor-pointer text-sm"

0 commit comments

Comments
 (0)