Skip to content

style(schedule): add chrome density prototype variants - #216

Draft
chiptus wants to merge 8 commits into
mainfrom
claude/frontend-design-layout-br8y1f
Draft

style(schedule): add chrome density prototype variants#216
chiptus wants to merge 8 commits into
mainfrom
claude/frontend-design-layout-br8y1f

Conversation

@chiptus

@chiptus chiptus commented Jul 24, 2026

Copy link
Copy Markdown
Owner

Throwaway prototype answering "the schedule view feels packed on mobile": switchable chrome variants on the real schedule routes, flipped via the floating pill or ?variant=.
Draft on purpose — pick a winner, then it gets folded in properly and src/pages/EditionView/prototype/ deleted; NOTES.md there logs each iteration and the verdict placeholder.

Current variant set (iteration 6–8): the chrome verdict is the content-first "top nav + auto-hide" design (no boxed banners, no timezone bar, unboxed timeline, sticky day toolbar + date/time strip + day-spanning list headers with embedded filters, mobile bottom tab bar hides on scroll down). The pill compares header/status treatments on that shared chrome:

  • current — baseline, renders like main
  • autohide-countdown — slim identity row; "Schedule soon" / "N days to go", dot only when live
  • autohide-dates — identity row with a color-coded dot in every phase: slate "Schedule soon" / amber "Jul 1–3" / red pulsing "Live"
  • autohide-cta — dates + dot, but pre-schedule says "Vote now"
  • collapse — full hero (title, logo, Tickets/Website, phase sentence as subtitle) at rest; scrolled, a compact identity (logo + name + phase dot) takes over the top bar's center

Verification

  • Open /festivals/tomorrowland/editions/2026/schedule/timeline and flip variants with the floating pill or / keys; the choice survives navigation and reloads.
  • Non-live states: /festivals/anta (pre-schedule) and /festivals/reveal-playground/editions/days (planning) show the phase status per variant.
  • In all non-current variants on mobile, scroll down: the bottom tab bar slides away; scroll up brings it back.
  • In collapse, scroll past the hero: the top bar center switches to the compact festival identity.
  • Timeline: day toolbar and date/time strip stick below the fixed top bar; list day headers stick for their whole day and carry the Filters trigger.
  • Variant current renders identically to main.

🤖 Generated with Claude Code

https://claude.ai/code/session_017tH8MLLh9iywh4UHTMy42o

@vercel

vercel Bot commented Jul 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
upline Ready Ready Preview, Comment Jul 25, 2026 8:22am

claude added 3 commits July 24, 2026 11:03
… switcher

Four switchable chrome treatments (current / quiet / commandbar / compact)
on the real schedule routes to answer: how should the stacked banners,
switcher, timezone bar and filters consolidate so mobile feels less packed?
Throwaway — see src/pages/EditionView/prototype/NOTES.md for the verdict
placeholder; the folder and all PROTOTYPE-marked call sites get deleted
once a variant wins.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tH8MLLh9iywh4UHTMy42o
Iteration 2 from feedback (leaning compact, icon strip too wide, want the
date/time header sticky): compact tries a dropdown view switcher while
commandbar keeps the icon strip for width comparison; all non-current
variants lift the timeline date band + hour scale into a sticky strip
synced to the horizontal scroll.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tH8MLLh9iywh4UHTMy42o
Iteration 3 from feedback (content-first wins on density; the dropdown
hid the views and the bar changed shape per view): all variants now share
the content-first base and differ in navigation mechanism, each consistent
across Now/Timeline/List — underline top tabs, a unified sticky bar with
fixed slots, or a switcher docked above the bottom tab bar on mobile.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tH8MLLh9iywh4UHTMy42o
Fifth variant from feedback on the bottom dock: keep the current-style
segmented switcher at the top of the content-first base, and slide the
mobile Vote/Schedule/Explore bar away while scrolling down (back on
scroll up or near the top) so content gets the whole screen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tH8MLLh9iywh4UHTMy42o
Iteration 5: the list groups slots per festival day on non-current
variants, so the sticky day header's range spans the whole day (it
previously sat inside the day's first time slot and un-stuck after one
screen). On the autohide variant the standalone filters row is gone —
the filter trigger lives inside the sticky day header.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tH8MLLh9iywh4UHTMy42o
…atus

Iteration 6: only current + autohide remain (tabs/unibar/thumbbar
deleted). The identity row's Live-dot slot generalizes to all phases:
pre-schedule shows 'Schedule soon', planning shows the countdown, live
keeps the pulsing dot, post-festival shows nothing. The variant choice
persists in sessionStorage so router redirects can't drop it. Decisions
from review: auto-hide applies everywhere; Tickets/Website buttons are
dropped for now with a follow-up to move them to the info tab.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tH8MLLh9iywh4UHTMy42o
Iteration 7: the pill flips between countdown (baseline), dates + a
color-coded status dot in every phase, and a vote-CTA flavor where
pre-schedule says 'Vote now'. Chrome is identical across the three;
legacy ?variant=autohide maps to the countdown flavor.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tH8MLLh9iywh4UHTMy42o
Iteration 8: fifth pill option — the current-style hero (title, logo,
Tickets/Website, full phase sentence as a quiet subtitle) shows at rest;
once scrolled out of view a compact identity (logo + truncated name +
color-coded phase dot) takes over the top bar's center slot. Rest of the
chrome matches the auto-hide variants.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tH8MLLh9iywh4UHTMy42o

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a throwaway “chrome density” prototype for the Edition Schedule experience, enabling multiple header/chrome variants to be toggled on real schedule routes (via a floating pill, arrow keys, or ?variant=) to pick a mobile-friendly winner before folding it in properly.

Changes:

  • Add a ChromeVariantProvider + switcher UI and wire it into EditionLayout to persist/share the selected chrome variant.
  • Adjust Schedule Timeline/List UI (sticky offsets, framing, grouping) based on the selected variant.
  • Add prototype-only components/hooks to support the new chrome behaviors (e.g., list day sticky header, hide-on-scroll behavior).

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/pages/EditionView/tabs/ScheduleTab/TimelineTab.tsx Hides the time badge in non-current variants.
src/pages/EditionView/tabs/ScheduleTab/ScheduleFilterSheet.tsx Adds showLabel option to force “Filters” text visibility (prototype).
src/pages/EditionView/tabs/ScheduleTab/list/TimeSlotGroup.tsx Formatting-only change for formatTimeOnly call.
src/pages/EditionView/tabs/ScheduleTab/list/ListTab.tsx Uses useChromeVariant to simplify non-current list chrome.
src/pages/EditionView/tabs/ScheduleTab/list/ListSchedule.tsx Groups list schedule by festival day for non-current variants; adds prototype day header.
src/pages/EditionView/tabs/ScheduleTab/horizontal/TimelineToolbar.tsx Adjusts sticky top offset based on chrome variant.
src/pages/EditionView/tabs/ScheduleTab/horizontal/TimelineContainer.tsx Introduces sticky time scale header for non-current variants with horizontal sync.
src/pages/EditionView/tabs/ScheduleTab/horizontal/Timeline.tsx Drops the “framing box” around timeline in non-current variants.
src/pages/EditionView/tabs/ScheduleTab/horizontal/StageLabels.tsx Adds className to allow variant-specific label positioning.
src/pages/EditionView/TabNavigation/TabNavigation.tsx Adds “hide bottom bar on scroll down” behavior for non-current variants.
src/pages/EditionView/prototype/useHideOnScrollDown.ts New hook to detect scroll-down and hide fixed chrome (prototype).
src/pages/EditionView/prototype/NOTES.md Documents prototype iterations and intended cleanup/verdict.
src/pages/EditionView/prototype/ListDayHeader.tsx New sticky per-day list header that can host filters (prototype).
src/pages/EditionView/prototype/EditionHeaderVariants.tsx New per-variant edition header rendering (identity row / collapse hero).
src/pages/EditionView/prototype/chromeVariant.tsx New variant context/provider, URL/session persistence, and floating switcher UI.
src/pages/EditionView/PhaseBanner.tsx Exports bannerMessage for use by the prototype header variants.
src/pages/EditionView/EditionLayout.tsx Wraps edition view with ChromeVariantProvider and swaps in EditionHeaderVariants.
src/components/layout/AppHeader.tsx Adds collapsedIdentity slot to support the “collapse” header variant.
prototype-mobile-driver.mjs Adds a throwaway Playwright driver script for mobile viewport screenshots (prototype).

Comment on lines +32 to +34
<div className="ml-auto md:ml-0">
<ScheduleFilterSheet tab="list" />
</div>
Comment on lines +44 to +56
const [scrollLeft, setScrollLeft] = useState(0);

useEffect(() => {
if (!stickyHeader) return;
const container = scrollContainerRef.current;
if (!container) return;

function handleScroll() {
setScrollLeft(container?.scrollLeft ?? 0);
}
container.addEventListener("scroll", handleScroll);
return () => container.removeEventListener("scroll", handleScroll);
}, [stickyHeader]);
Comment on lines +105 to +121
useEffect(() => {
function handleKeyDown(event: KeyboardEvent) {
const target = event.target as HTMLElement | null;
if (
target &&
(target.tagName === "INPUT" ||
target.tagName === "TEXTAREA" ||
target.isContentEditable)
) {
return;
}
if (event.key === "ArrowLeft") step(-1);
if (event.key === "ArrowRight") step(1);
}
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
});
Comment on lines +86 to +93
// No production gate: this ships on a draft prototype PR so the preview
// deploy can flip variants too. The whole folder is deleted after the
// verdict — it must never reach main.
return (
<ChromeVariantContext.Provider value={variant}>
{children}
<VariantSwitcher variant={variant} onChange={setVariant} />
</ChromeVariantContext.Provider>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants