Design: simple TimeCurve UX — timer + CL8Y→CHARM path (post-launch countdown) #40
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:open_issues
agents
agent:security_audit
agent:verify
area
timecurve
arena
arena-v2
audit
block:feature_review
block:security
bug
contracts
design
devops
docs
documentation
enhancement
epic
feature
frontend
indexer
low priority
megaeth
operations
ops
performance
QA
qa checklist
referrals
removal
security
smart-contracts
tech-debt
testing
time-arena
timecurve
visual-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
code/yieldomega#40
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Prioritize a simple, first-run path for the DOUB (TimeCurve) launch: after the pre-start countdown reaches zero and the sale timer is live, a typical user should immediately understand (1) how much time is left and (2) that they spend CL8Y between the contract’s live min and max to acquire CHARM weight—without needing WarBow, podiums, fee routing, or indexer detail.
Non-goals for the primary viewport: teaching the full game; surfacing every stat card; competing narrative threads at equal weight.
Repo context (implementation today):
frontend/src/pages/TimeCurvePage.tsx,frontend/src/pages/timecurve/TimeCurveSections.tsx, hero timer hookfrontend/src/pages/timecurve/useTimecurveHeroTimer.ts.Evaluation — current design (as of
main)What works well
timer-hero__countdown).deadline()read + block timestamp + refresh aligns with “trust the chain” QA goals.RawDataAccordionand some<details>blocks already signal “advanced / protocol”.Gaps vs. desired “simple CL8Y → CHARM” story
StatCards, optional latest BP breakdown—timer swing / battle / “what this can chase” compete with the core “deposit CL8Y, get CHARM” message.Checklist — design / UX acceptance criteria
A. Timer clarity (pre-start → live → end)
timerUrgencyClass, pills) supports the countdown rather than replacing it as the main signal.B. CL8Y → CHARM as the primary action
C. Progressive disclosure & advanced users
/timecurve,/timecurve/arena,/timecurve/protocol) or tabs so the default route matches the simple story.aria-livewhere appropriate).D. Content & brand
docs/product/primitives.md: CL8Y spend, CHARM weight, DOUB as launched token where relevant—without dumping all four podium rules in the hero.Recommendations
Define a “Simple path” layout variant — For
saleActive(and optionallysaleStartPending), reorder or collapse sections so the vertical order is: Timer (with one-line explanation) → CL8Y min/max + slider + CHARM preview → single primary CTA → “Learn more” / Advanced. Move What matters now stat grid and multi-card buy highlights below or into Advanced.Soften the global hero lede for the default audience — Replace or shorten the opening paragraph that lists four podiums + BP; use a progressive pattern: headline + “New here?” expander for mechanics, or route deep copy to Primitives / docs.
Visual hierarchy: one focal column — On desktop, consider a single-column hero+buy stack with standings/WarBow in a secondary column or lower page so the eye doesn’t scan three competing “primary” panels (
split-layout--hero).Explicit modes in UI chrome — Badges like “Pre-launch” | “Live” | “Ended” tied to
saleStartPending/saleActive/saleEndedwith mutually exclusive explanations reduce ambiguity vs. many simultaneous pills (guard, revenge, flag).“Advanced” hub — Aggregate WarBow + podiums + battle feed + charts behind one Arena / Leaderboard entry point; keeps the main page feeling like a launch participation surface, not a full game HUD.
User testing script — 5-minute test: “You want DOUB from this launch. Show how you’d buy before time runs out.” Success = user identifies timer + min/max spend + confirm without facilitator prompting podiums.
Deliverables
mentioned in commit
eac3d5f29b@brouie — implementation landed in
eac3d5fonmain. Summary + verification request below.What shipped (issue 40 acceptance criteria mapping)
Three-route surface sharing one sub-nav (
<TimeCurveSubnav />):/timecurveTimeCurveSimplePage(new)/timecurve/arenaTimeCurvePage(existing — no game-rule changes)/timecurve/protocolTimeCurveProtocolPage(new, read-only)The post-launch index (
/) also routes toTimeCurveSimplePageso the LaunchCountdownPage → Simple handoff lands on the friendly view.A — Timer clarity
TimeCurveSimplePageputs the state badge (Pre-launch | Live | Ended) and the hero countdown above the fold, followed by a one-sentence narrative pulled fromphaseNarrative()(e.g. “When this hits zero, the sale ends and buys stop.”). The countdown is the visual primary; urgency styling stays supporting.timeCurveSimplePhase.ts) shared between the simple page anduseTimeCurveSaleSession, so badge + narrative + buy-gating stay in lock-step.LaunchGate.tsxnow lazy-loads the simple page so the post-countdown layout swap is gentle (covered ine2e/launch-countdown.spec.ts+ manual probe).B — CL8Y → CHARM as the primary action
C — Progressive disclosure & advanced users
/timecurve/arenaand/timecurve/protocol. The<TimeCurveSubnav />advertises one-line hints per tab, so the secondary surfaces are discoverable without crowding the simple view.aria-livesemantics fromuseTimecurveHeroTimer. Sub-nav uses<NavLink>witharia-current="page"on the active tab.D — Content & brand
Single-source-of-truth invariants (preserved)
useWriteContractcall toTimeCurve.buy—useTimeCurveSaleSessionandTimeCurvePageshare the same write contract.TimeCurve/LinearCharmPrice/FeeRouter— no parallel game-rule code in the simple page.docs/frontend/timecurve-views.md(new),docs/frontend/design.md, anddocs/qa/YO-TimeCurve-QA-Checklist.md(items C7–C9).Tests
npm run lint— clean.npm run typecheck— clean.npm test— 105 pass / 18 files (addedtimeCurveSimplePhase.test.ts,TimeCurveSubnav.test.tsx).npm run test:e2e -- --workers=5— 11 pass / 5 skipped (skips are the launch-state-conditional scenarios inlaunch-countdown.spec.tsand a couple oftimecurve.spec.tspaths that legitimately require a differentVITE_LAUNCH_TIMESTAMP).VITE_LAUNCH_TIMESTAMP=now+90):<launch-countdown>visible, h1 = YieldOmega, sub-nav absent.TimeCurveSimplePageexactly as planned.Verification request
Please re-run against acceptance criteria A1–A4 / B1–B5 / C1–C4 / D1 and the new QA items C7 / C8 / C9 in
docs/qa/YO-TimeCurve-QA-Checklist.md:bash scripts/start-local-anvil-stack.sh SKIP_ANVIL_RICH_STATE=1 START_BOT_SWARM=1LAUNCH_OFFSET_SEC=90to watchLaunchCountdownPageflip into the simple view live.cd frontend && npm run dev, walk the simple view, click the sub-nav into Arena and Protocol, and confirm the dense PvP / podium / battle-feed surfaces are not shown above the fold on/timecurve.If the
Want more?tile copy / sub-nav hint copy needs another pass, happy to iterate — let me know.mentioned in issue #39
@brouie Follow-up for issue #40 (items 1, 2, 4, 6) is on
mainasfed6cd2.2 — Arena phase consistency:
TimeCurvePagenow derivessaleActive,saleEnded,saleStartPending, andtimerExpiredAwaitingEndfrom the samederivePhase()state machine as the Simple view, via newphaseFlags()intimeCurveSimplePhase.ts(with vitest coverage).4 — Launch-adaptive e2e: Added
frontend/e2e/launchState.ts(detectLaunchState).navigation.spec.ts,surface-shells.spec.ts,home.spec.ts,collection.spec.ts,rabbit-treasury.spec.ts,launch-countdown.spec.ts, andtimecurve.spec.tsuse it so builds locked behindVITE_LAUNCH_TIMESTAMPskip instead of failing; post-launch navigation starts from/homewhere needed.1 — Swarm QA: Ran
START_BOT_SWARM=1local stack; Simple/timecurveRecent buys ticker showed live indexer rows (amount, +timer, tx links) with no console errors.6 — First-buyer heuristic: Walkthrough documented as checklist C11 in
docs/qa/YO-TimeCurve-QA-Checklist.md; swarm/ticker steps as C10.docs/frontend/timecurve-views.mdinvariant #3 updated for Arena.CI locally: lint, typecheck, vitest, build,
playwright test --workers=5(11 passed, 5 skipped on post-launch build; anvil-heavy specs skipped as usual).Please verify when you can.
mentioned in issue #48
@PlasticDigits #40 verified on
eac3d5f+fed6cd2.Test results
Unit (vitest):
timeCurveSimplePhase.test.ts: 13/13 (derivePhase + phaseFlags + phaseBadge + phaseNarrative)TimeCurveSubnav.test.tsx: 3/3E2E (Playwright):
VITE_LAUNCH_TIMESTAMP): 9 passed, 6 skipped, 3 failedVITE_LAUNCH_TIMESTAMP=1700000000+ rerun the 3 failures: 3/3 pass, 2 correctly skippedstart-local-anvil-stack.shcould defaultVITE_LAUNCH_TIMESTAMP=<past>for QA servers since most verification work lands in post-launch state. Not filing as a separate issue — below noise floor.AC mapping
TimeCurveSimplePageplaces phase badge + hero countdown above the fold, pulls single-sentence narrative fromphaseNarrative().timeCurveSimplePhase.tsis the shared pure helper between Simple + Arena + useTimeCurveSaleSession — verified via grep: all three importderivePhase/phaseFlags/phaseBadgefrom the same source module./timecurve/arenaand/timecurve/protocol, accessible via<TimeCurveSubnav />. Router config (LaunchGate.tsx) confirms narrowly-scopedtimecurve/:timecurveSegmentdynamic route — no top-level catch-all.Phase consistency fix (
fed6cd2)Arena
TimeCurvePagenow derives phase via samederivePhase()+ newphaseFlags()helper as Simple — no parallel phase logic. Unit-tested.Known related
The sale-phase mis-detection I filed as #48 yesterday from #39 C1 testing is a separate runtime issue (contract says saleStart > 0 && !ended, but frontend reports 'pre-start') — tracked there and not a blocker for closing #40's design acceptance. The shipped three-view architecture is correct; the phase-read bug #48 would affect both Simple + Arena equally now that they share the helper, which is actually GOOD (fix once, fix both).
Closing as verified.
mentioned in issue #42
mentioned in issue #113