Replace level-up text modal with confetti glass popover (L2+) #335

Closed
opened 2026-06-19 04:27:44 +00:00 by PlasticDigits · 15 comments
PlasticDigits commented 2026-06-19 04:27:44 +00:00 (Migrated from gitlab.com)

Parent

Gap analysis follow-up from #331.

Current codebase

  • Level-up detection in ArenaSimplePage.tsx (useEffect on playerLevelRaw) opens FeatureMechanicModal when level crosses 2–5 and tutorial not seen.
  • FeatureMechanicModal (frontend/src/components/FeatureMechanicModal.tsx) is a text-heavy <dialog> with multi-paragraph copy from podiumFeatureMechanicCopy.
  • Level 1 corresponds to first wallet connection / first buy — not a celebration moment per parent approval.
  • Progression matrix: featureKeyForUnlockLevel maps L2→time_booster, L3→defended_streak, L4→warbow, L5→warbow_flag.

Why needed

Approved replacement: confetti burst popover with concise "Level Up" headline and one short line naming the unlocked feature — only for Level 2+. Reduces modal fatigue while preserving progression feedback.

Constraints / guardrails

  • VISUAL: Cyberminimalist Glass System (INV-FRONTEND-290, frontend/src/index.css glass tokens). Confetti must be subtle — match sparse motion policy (INV-FRONTEND-297-ART-MOTION-AUDIO).
  • Level 2+ only — suppress celebration on L1 / first connect.
  • Upload screenshots (desktop, tablet, mobile) to this issue showing popover + confetti compliance.
  • Respect prefers-reduced-motion: confetti off, popover remains.
  • Keep manual "help" access to full mechanic copy (existing help buttons / openFeatureHelp) — do not delete long-form education entirely.
  • markFeatureTutorialSeen behavior preserved so repeats do not spam.

Relevant files

Path Role
frontend/src/components/FeatureMechanicModal.tsx Current level-up UI (replace for auto-trigger path)
frontend/src/pages/arena/ArenaSimplePage.tsx Level-up detection + modal mount
frontend/src/pages/arena/ArenaProtocolPage.tsx Also mounts FeatureMechanicModal
frontend/src/lib/arenaProgression.ts Feature keys, tutorial storage
frontend/src/pages/arena/podiumCopy.ts Mechanic copy source
frontend/src/index.css Modal / popover styling
  1. New LevelUpCelebrationPopover (or evolve FeatureMechanicModal with variant="celebration") — glass popover, confetti burst (CSS/canvas, ≤2s), title "Level Up", body ≤80 chars from feature short label.
  2. Wire auto-open from level-cross effect for unlock levels ≥2 only.
  3. Leave FeatureMechanicModal (text) for explicit help clicks, or consolidate with a mode prop.
  4. Add data-testid hooks for unit/E2E follow-ups.

Acceptance criteria

  • Crossing L1→L2 (and subsequent level-ups) shows confetti popover with concise unlock text.
  • L1 / wallet connect alone does not trigger celebration.
  • Reduced-motion path: no confetti animation.
  • Glass styling matches command-console primitives.
  • Screenshots on issue (desktop / tablet / mobile).
  • cd frontend && npm run typecheck && npm run lint && npm test passes.

Test plan

Command Path
cd frontend && npm run typecheck && npm run lint && npm test New component tests + ArenaSimplePage level-up effect tests
cd frontend && CI=1 npm run test:e2e -- --workers=5 e2e/anvil-arena-03-wallet-writes.spec.ts Post-buy level cross (when seeded)

Vitest: mock level transition 1→2 triggers popover; 1→1 does not; reduced-motion disables confetti class.

Attack / abuse test plan

  • Celebration is read-only UI; no new external URLs or script injection in confetti layer.
  • Tutorial localStorage keys unchanged in scope.

Verification criteria

  • Anvil buy that levels wallet 1→2 shows popover once.
  • Screenshots attached for three breakpoints.
  • Help modal still reachable for full mechanic text.
## Parent Gap analysis follow-up from [#331](https://gitlab.com/PlasticDigits/yieldomega/-/issues/331). ## Current codebase - Level-up detection in `ArenaSimplePage.tsx` (`useEffect` on `playerLevelRaw`) opens `FeatureMechanicModal` when level crosses 2–5 and tutorial not seen. - `FeatureMechanicModal` (`frontend/src/components/FeatureMechanicModal.tsx`) is a text-heavy `<dialog>` with multi-paragraph copy from `podiumFeatureMechanicCopy`. - Level 1 corresponds to first wallet connection / first buy — **not** a celebration moment per parent approval. - Progression matrix: `featureKeyForUnlockLevel` maps L2→time_booster, L3→defended_streak, L4→warbow, L5→warbow_flag. ## Why needed Approved replacement: **confetti burst popover** with concise "Level Up" headline and one short line naming the unlocked feature — only for **Level 2+**. Reduces modal fatigue while preserving progression feedback. ## Constraints / guardrails - **VISUAL**: Cyberminimalist Glass System (`INV-FRONTEND-290`, `frontend/src/index.css` glass tokens). Confetti must be **subtle** — match sparse motion policy (`INV-FRONTEND-297-ART-MOTION-AUDIO`). - **Level 2+ only** — suppress celebration on L1 / first connect. - Upload **screenshots** (desktop, tablet, mobile) to this issue showing popover + confetti compliance. - Respect `prefers-reduced-motion`: confetti off, popover remains. - Keep manual "help" access to full mechanic copy (existing help buttons / `openFeatureHelp`) — do not delete long-form education entirely. - `markFeatureTutorialSeen` behavior preserved so repeats do not spam. ## Relevant files | Path | Role | |------|------| | `frontend/src/components/FeatureMechanicModal.tsx` | Current level-up UI (replace for auto-trigger path) | | `frontend/src/pages/arena/ArenaSimplePage.tsx` | Level-up detection + modal mount | | `frontend/src/pages/arena/ArenaProtocolPage.tsx` | Also mounts `FeatureMechanicModal` | | `frontend/src/lib/arenaProgression.ts` | Feature keys, tutorial storage | | `frontend/src/pages/arena/podiumCopy.ts` | Mechanic copy source | | `frontend/src/index.css` | Modal / popover styling | ## Recommended direction 1. New `LevelUpCelebrationPopover` (or evolve `FeatureMechanicModal` with `variant="celebration"`) — glass popover, confetti burst (CSS/canvas, ≤2s), title "Level Up", body ≤80 chars from feature short label. 2. Wire auto-open from level-cross effect for unlock levels ≥2 only. 3. Leave `FeatureMechanicModal` (text) for explicit help clicks, or consolidate with a `mode` prop. 4. Add `data-testid` hooks for unit/E2E follow-ups. ## Acceptance criteria - [ ] Crossing L1→L2 (and subsequent level-ups) shows confetti popover with concise unlock text. - [ ] L1 / wallet connect alone does **not** trigger celebration. - [ ] Reduced-motion path: no confetti animation. - [ ] Glass styling matches command-console primitives. - [ ] Screenshots on issue (desktop / tablet / mobile). - [ ] `cd frontend && npm run typecheck && npm run lint && npm test` passes. ## Test plan | Command | Path | |---------|------| | `cd frontend && npm run typecheck && npm run lint && npm test` | New component tests + `ArenaSimplePage` level-up effect tests | | `cd frontend && CI=1 npm run test:e2e -- --workers=5 e2e/anvil-arena-03-wallet-writes.spec.ts` | Post-buy level cross (when seeded) | Vitest: mock level transition 1→2 triggers popover; 1→1 does not; reduced-motion disables confetti class. ## Attack / abuse test plan - Celebration is read-only UI; no new external URLs or script injection in confetti layer. - Tutorial localStorage keys unchanged in scope. ## Verification criteria - Anvil buy that levels wallet 1→2 shows popover once. - Screenshots attached for three breakpoints. - Help modal still reachable for full mechanic text.
PlasticDigits commented 2026-06-19 04:28:08 +00:00 (Migrated from gitlab.com)

mentioned in issue #331

mentioned in issue #331
PlasticDigits commented 2026-06-19 06:31:01 +00:00 (Migrated from gitlab.com)

mentioned in commit 859b4a9ff1

mentioned in commit 859b4a9ff1ed689d674407f536a9109043392217
PlasticDigits commented 2026-06-19 06:31:19 +00:00 (Migrated from gitlab.com)

mentioned in merge request !508

mentioned in merge request !508
PlasticDigits commented 2026-06-19 06:31:26 +00:00 (Migrated from gitlab.com)

Implementation note — MR !508

Auto level-up feedback on play / now uses a glass confetti popover (L2+ only). Full mechanic education remains on explicit ? help via FeatureMechanicModal.

Screenshots (desktop / tablet / mobile)

level-up-celebration-desktop

level-up-celebration-tablet

level-up-celebration-mobile

Verification

Check Command / step Result
Frontend unit/type/lint cd frontend && npm run typecheck && npm run lint && npm test PASS (706 tests)
L1→L2 popover Anvil + preview + node frontend/scripts/capture-level-up-celebration-screenshots.mjs PASS
L1 alone suppressed arenaLevelUpCelebration.test.ts PASS
Reduced motion LevelUpCelebrationPopover.test.tsx PASS
Help modal preserved FeatureMechanicModal still wired to openFeatureHelp PASS

MR: https://gitlab.com/PlasticDigits/yieldomega/-/merge_requests/138

## Implementation note — MR !508 Auto level-up feedback on play `/` now uses a glass confetti popover (**L2+** only). Full mechanic education remains on explicit `?` help via `FeatureMechanicModal`. ### Screenshots (desktop / tablet / mobile) ![level-up-celebration-desktop](/uploads/b5230d91677a2cfe2e17b0bd863666fb/level-up-celebration-desktop.png) ![level-up-celebration-tablet](/uploads/49d44e5002af3acb27e406999d5901e2/level-up-celebration-tablet.png) ![level-up-celebration-mobile](/uploads/65a05d3ab0644d1099759e0559c4fa4a/level-up-celebration-mobile.png) ### Verification | Check | Command / step | Result | |-------|----------------|--------| | Frontend unit/type/lint | `cd frontend && npm run typecheck && npm run lint && npm test` | **PASS** (706 tests) | | L1→L2 popover | Anvil + preview + `node frontend/scripts/capture-level-up-celebration-screenshots.mjs` | **PASS** | | L1 alone suppressed | `arenaLevelUpCelebration.test.ts` | **PASS** | | Reduced motion | `LevelUpCelebrationPopover.test.tsx` | **PASS** | | Help modal preserved | `FeatureMechanicModal` still wired to `openFeatureHelp` | **PASS** | MR: https://gitlab.com/PlasticDigits/yieldomega/-/merge_requests/138
PlasticDigits commented 2026-06-19 08:19:54 +00:00 (Migrated from gitlab.com)

mentioned in commit 0fdf405b4e

mentioned in commit 0fdf405b4e9b7ecc0400980cfe1ccabb798e0c32
PlasticDigits commented 2026-06-19 08:20:01 +00:00 (Migrated from gitlab.com)

mentioned in merge request !511

mentioned in merge request !511
PlasticDigits commented 2026-06-19 08:52:14 +00:00 (Migrated from gitlab.com)

Verification — issue #335 (agent:verify)

Verified MR !508 on main (1411dc49). No additional repo changes required.

Results

Criterion How verified Result
L1→L2+ shows glass confetti popover with concise unlock text Anvil :8545 + native Postgres indexer :3100 + ANVIL_E2E=1 preview :4173; mock wallet CRED buy → data-testid="level-up-celebration" visible with panel copy "Level Up / Time Booster unlocked" and confetti canvas present PASS
L1 / wallet connect alone does not trigger celebration frontend/src/lib/arenaLevelUpCelebration.test.ts — detectUnseenLevelUpFeature(undefined,1) and (1,1) return null PASS
prefers-reduced-motion: no confetti, popover remains frontend/src/components/LevelUpCelebrationPopover.test.tsx — omits confetti canvas, sets data-reduced-motion="true" PASS
Glass styling matches command-console primitives LevelUpCelebrationPopover uses GlassPanel tone="gold" + .level-up-celebration tokens in index.css PASS
Screenshots (desktop / tablet / mobile) on issue Implementation note attachments (level-up-celebration-{desktop,tablet,mobile}.png) PASS
cd frontend && npm run typecheck && npm run lint && npm test Ran locally — 137 files / 722 tests, 0 errors (3 pre-existing lint warnings) PASS
Help modal still reachable for full mechanic text ArenaSimplePage keeps openFeatureHelp → FeatureMechanicModal; auto path uses LevelUpCelebrationPopover only PASS
markFeatureTutorialSeen preserved (no repeat spam) Called on popover open (LevelUpCelebrationPopover) and help modal (FeatureMechanicModal) PASS
E2E e2e/anvil-arena-03-wallet-writes.spec.ts Not in acceptance checklist; spec covers buy writes/toasts, not level-up UI SKIP

Notes

  • Level-up detection is indexer-first via useArenaPlayerLevel (INV-FRONTEND-301); Anvil manual verification needs VITE_INDEXER_URL + running indexer (matches capture-level-up-celebration-screenshots.mjs / MR verification).
  • ArenaProtocolPage retains help-only FeatureMechanicModal (no auto celebration) — expected; play route / is the auto-trigger surface.
## Verification — issue #335 (agent:verify) Verified **MR !508** on `main` (`1411dc49`). No additional repo changes required. ### Results | Criterion | How verified | Result | |-----------|----------------|--------| | L1→L2+ shows glass confetti popover with concise unlock text | Anvil `:8545` + native Postgres indexer `:3100` + `ANVIL_E2E=1` preview `:4173`; mock wallet CRED buy → `data-testid="level-up-celebration"` visible with panel copy **"Level Up / Time Booster unlocked"** and confetti canvas present | **PASS** | | L1 / wallet connect alone does **not** trigger celebration | `frontend/src/lib/arenaLevelUpCelebration.test.ts` — `detectUnseenLevelUpFeature(undefined,1)` and `(1,1)` return null | **PASS** | | `prefers-reduced-motion`: no confetti, popover remains | `frontend/src/components/LevelUpCelebrationPopover.test.tsx` — omits confetti canvas, sets `data-reduced-motion="true"` | **PASS** | | Glass styling matches command-console primitives | `LevelUpCelebrationPopover` uses `GlassPanel tone="gold"` + `.level-up-celebration` tokens in `index.css` | **PASS** | | Screenshots (desktop / tablet / mobile) on issue | Implementation note attachments (`level-up-celebration-{desktop,tablet,mobile}.png`) | **PASS** | | `cd frontend && npm run typecheck && npm run lint && npm test` | Ran locally — 137 files / 722 tests, 0 errors (3 pre-existing lint warnings) | **PASS** | | Help modal still reachable for full mechanic text | `ArenaSimplePage` keeps `openFeatureHelp` → `FeatureMechanicModal`; auto path uses `LevelUpCelebrationPopover` only | **PASS** | | `markFeatureTutorialSeen` preserved (no repeat spam) | Called on popover open (`LevelUpCelebrationPopover`) and help modal (`FeatureMechanicModal`) | **PASS** | | E2E `e2e/anvil-arena-03-wallet-writes.spec.ts` | Not in acceptance checklist; spec covers buy writes/toasts, not level-up UI | **SKIP** | ### Notes - Level-up detection is **indexer-first** via `useArenaPlayerLevel` (`INV-FRONTEND-301`); Anvil manual verification needs `VITE_INDEXER_URL` + running indexer (matches `capture-level-up-celebration-screenshots.mjs` / MR verification). - `ArenaProtocolPage` retains help-only `FeatureMechanicModal` (no auto celebration) — expected; play route `/` is the auto-trigger surface.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-06-19 08:52:15 +00:00
PlasticDigits commented 2026-06-19 10:59:42 +00:00 (Migrated from gitlab.com)

mentioned in merge request !514

mentioned in merge request !514
PlasticDigits commented 2026-06-19 11:07:42 +00:00 (Migrated from gitlab.com)

mentioned in issue #339

mentioned in issue #339
PlasticDigits commented 2026-06-19 11:55:54 +00:00 (Migrated from gitlab.com)

mentioned in merge request !515

mentioned in merge request !515
PlasticDigits commented 2026-06-19 13:31:43 +00:00 (Migrated from gitlab.com)

mentioned in issue #340

mentioned in issue #340
PlasticDigits commented 2026-06-25 14:28:40 +00:00 (Migrated from gitlab.com)

mentioned in issue #342

mentioned in issue #342
PlasticDigits commented 2026-06-25 20:07:12 +00:00 (Migrated from gitlab.com)

mentioned in issue #343

mentioned in issue #343
PlasticDigits commented 2026-07-07 02:38:47 +00:00 (Migrated from gitlab.com)

mentioned in issue #365

mentioned in issue #365
PlasticDigits commented 2026-07-07 12:42:22 +00:00 (Migrated from gitlab.com)

mentioned in commit c4e9e34529

mentioned in commit c4e9e34529b4915956ce876a0f8b09c3491e5009
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
code/yieldomega#335
No description provided.