feat: Replaced compact creator header with full hero section: 96px avat…

- "frontend/src/pages/CreatorDetail.tsx"
- "frontend/src/App.css"

GSD-Task: S01/T02
This commit is contained in:
jlightner 2026-04-03 08:52:06 +00:00
parent 74a4f25402
commit bef8d5939d
5 changed files with 182 additions and 45 deletions

View file

@ -53,7 +53,7 @@
- Estimate: 25m
- Files: frontend/src/api/public-client.ts, frontend/src/pages/CreatorDetail.tsx
- Verify: cd frontend && npx tsc --noEmit
- [ ] **T02: Build hero section with large avatar, bio text, and genre pills** — Replace the compact `creator-detail__header` with a full hero section. Large avatar, prominent name, bio paragraph, and genre pills. Use existing `CreatorAvatar` component (supports `imageUrl` prop and arbitrary `size`), existing `.pill` class for genres, and CSS custom properties for theming.
- [x] **T02: Replaced compact creator header with full hero section: 96px avatar, 2rem name, bio paragraph, genre pills, separated stats bar** — Replace the compact `creator-detail__header` with a full hero section. Large avatar, prominent name, bio paragraph, and genre pills. Use existing `CreatorAvatar` component (supports `imageUrl` prop and arbitrary `size`), existing `.pill` class for genres, and CSS custom properties for theming.
## Steps

View file

@ -0,0 +1,24 @@
{
"schemaVersion": 1,
"taskId": "T01",
"unitId": "M017/S01/T01",
"timestamp": 1775206212614,
"passed": false,
"discoverySource": "task-plan",
"checks": [
{
"command": "cd frontend",
"exitCode": 0,
"durationMs": 5,
"verdict": "pass"
},
{
"command": "npx tsc --noEmit",
"exitCode": 1,
"durationMs": 817,
"verdict": "fail"
}
],
"retryAttempt": 1,
"maxRetries": 2
}

View file

@ -0,0 +1,77 @@
---
id: T02
parent: S01
milestone: M017
provides: []
requires: []
affects: []
key_files: ["frontend/src/pages/CreatorDetail.tsx", "frontend/src/App.css"]
key_decisions: ["Separated stats bar from hero into its own div below the hero border"]
patterns_established: []
drill_down_paths: []
observability_surfaces: []
duration: ""
verification_result: "npx tsc --noEmit passed with zero errors. npm run build produced clean production build (58 modules, zero warnings)."
completed_at: 2026-04-03T08:52:03.434Z
blocker_discovered: false
---
# T02: Replaced compact creator header with full hero section: 96px avatar, 2rem name, bio paragraph, genre pills, separated stats bar
> Replaced compact creator header with full hero section: 96px avatar, 2rem name, bio paragraph, genre pills, separated stats bar
## What Happened
---
id: T02
parent: S01
milestone: M017
key_files:
- frontend/src/pages/CreatorDetail.tsx
- frontend/src/App.css
key_decisions:
- Separated stats bar from hero into its own div below the hero border
duration: ""
verification_result: passed
completed_at: 2026-04-03T08:52:03.434Z
blocker_discovered: false
---
# T02: Replaced compact creator header with full hero section: 96px avatar, 2rem name, bio paragraph, genre pills, separated stats bar
**Replaced compact creator header with full hero section: 96px avatar, 2rem name, bio paragraph, genre pills, separated stats bar**
## What Happened
Replaced the old creator-detail__header block with a new creator-hero layout featuring a 96px CreatorAvatar (using avatar_url), prominent 2rem name, conditional bio paragraph, and genre pills. Stats moved to a separate stats-bar div below the hero border. Updated CSS with flex layout, responsive mobile stacking at 768px, and removed old unused rules. Fixed unused CreatorTechniqueItem import from T01 that caused tsc -b to fail.
## Verification
npx tsc --noEmit passed with zero errors. npm run build produced clean production build (58 modules, zero warnings).
## Verification Evidence
| # | Command | Exit Code | Verdict | Duration |
|---|---------|-----------|---------|----------|
| 1 | `npx tsc --noEmit` | 0 | ✅ pass | 1500ms |
| 2 | `npm run build` | 0 | ✅ pass | 3500ms |
## Deviations
Removed unused CreatorTechniqueItem import from T01 that caused tsc -b (used by npm run build) to fail with TS6133.
## Known Issues
None.
## Files Created/Modified
- `frontend/src/pages/CreatorDetail.tsx`
- `frontend/src/App.css`
## Deviations
Removed unused CreatorTechniqueItem import from T01 that caused tsc -b (used by npm run build) to fail with TS6133.
## Known Issues
None.

View file

@ -2659,32 +2659,51 @@ a.app-footer__repo:hover {
max-width: 64rem;
}
.creator-detail__header {
/* Creator Hero */
.creator-hero {
display: flex;
align-items: flex-start;
gap: 1.5rem;
margin-bottom: 1.5rem;
padding-bottom: 1.5rem;
border-bottom: 1px solid var(--color-border);
}
.creator-detail__name {
.creator-hero__info {
display: flex;
align-items: center;
gap: 0.75rem;
font-size: 1.75rem;
flex-direction: column;
gap: 0.5rem;
min-width: 0;
}
.creator-hero__name {
font-size: 2rem;
font-weight: 800;
letter-spacing: -0.02em;
margin-bottom: 0.5rem;
line-height: 1.2;
margin: 0;
}
.creator-detail__meta {
.creator-hero__bio {
color: var(--color-text-secondary);
font-size: 1rem;
line-height: 1.6;
max-width: 48rem;
margin: 0;
}
.creator-hero__genres {
display: flex;
flex-wrap: wrap;
gap: 0.375rem;
}
.creator-detail__stats-bar {
display: flex;
align-items: center;
gap: 0.75rem;
flex-wrap: wrap;
}
.creator-detail__genres {
display: inline-flex;
gap: 0.25rem;
flex-wrap: wrap;
margin-bottom: 0.5rem;
}
.creator-detail__stats {
@ -3164,10 +3183,20 @@ a.app-footer__repo:hover {
.creators-browse__title,
.topics-browse__title,
.creator-detail__name {
.creator-hero__name {
font-size: 1.375rem;
}
.creator-hero {
flex-direction: column;
align-items: center;
text-align: center;
}
.creator-hero__genres {
justify-content: center;
}
.topics-grid {
grid-template-columns: 1fr;
}

View file

@ -10,7 +10,6 @@ import { Link, useParams } from "react-router-dom";
import {
fetchCreator,
type CreatorDetailResponse,
type CreatorTechniqueItem,
} from "../api/public-client";
import CreatorAvatar from "../components/CreatorAvatar";
import SortDropdown from "../components/SortDropdown";
@ -110,39 +109,47 @@ export default function CreatorDetail() {
Creators
</Link>
{/* Header */}
<header className="creator-detail__header">
<h1 className="creator-detail__name"><CreatorAvatar creatorId={creator.id} name={creator.name} size={48} /> {creator.name}</h1>
<div className="creator-detail__meta">
{creator.genres && creator.genres.length > 0 && (
<span className="creator-detail__genres">
{creator.genres.map((g) => (
<span key={g} className="pill">
{g}
</span>
))}
</span>
{/* Hero */}
<header className="creator-hero">
<CreatorAvatar
creatorId={creator.id}
name={creator.name}
imageUrl={creator.avatar_url ?? undefined}
size={96}
/>
<div className="creator-hero__info">
<h1 className="creator-hero__name">{creator.name}</h1>
{creator.bio && (
<p className="creator-hero__bio">{creator.bio}</p>
)}
{creator.genres && creator.genres.length > 0 && (
<div className="creator-hero__genres">
{creator.genres.map((g) => (
<span key={g} className="pill">{g}</span>
))}
</div>
)}
<span className="creator-detail__stats">
{creator.video_count} video{creator.video_count !== 1 ? "s" : ""}
{Object.keys(creator.genre_breakdown).length > 0 && (
<>
<span className="queue-card__separator">·</span>
<span className="creator-detail__topic-pills">
{Object.entries(creator.genre_breakdown)
.sort(([, a], [, b]) => b - a)
.map(([cat, count]) => (
<span key={cat} className={`badge badge--cat-${catSlug(cat)}`}>
{cat}: {count}
</span>
))}
</span>
</>
)}
</span>
</div>
</header>
{/* Stats */}
<div className="creator-detail__stats-bar">
<span className="creator-detail__stats">
{creator.video_count} video{creator.video_count !== 1 ? "s" : ""}
</span>
{Object.keys(creator.genre_breakdown).length > 0 && (
<span className="creator-detail__topic-pills">
{Object.entries(creator.genre_breakdown)
.sort(([, a], [, b]) => b - a)
.map(([cat, count]) => (
<span key={cat} className={`badge badge--cat-${catSlug(cat)}`}>
{cat}: {count}
</span>
))}
</span>
)}
</div>
{/* Technique pages */}
<section className="creator-techniques">
<div className="creator-techniques__header">