feat: growing token rate + floating +N pop animation on total counter - #76
Conversation
- Add getDynamicRate() to death-clock-core.js with 30% annual growth after BASE_DATE - Add RATE_GROWTH_PER_YEAR constant (0.30) - Update getCurrentTokens() to integrate the exponential rate for accuracy - Use getDynamicRate() in 02-counter.js for rate display and session tokens - Update rate subtitle to show "and growing" beyond BASE_DATE - Add spawnTokenPop(): spawns a "+N" floating element on the total counter every second - Add .token-pop CSS with @Keyframes tokenPopFloat (float up 56px, fade out over 1.5s) - Change .counter-box overflow to visible so pops can float above the box - Add 9 unit tests for getDynamicRate and RATE_GROWTH_PER_YEAR - All 262 unit tests pass at 100% coverage; all 68 E2E tests pass Agent-Logs-Url: https://github.com/nitrocode/token-deathclock/sessions/1579b618-82e8-4125-b282-8ddddafa27eb Co-authored-by: nitrocode <7775707+nitrocode@users.noreply.github.com>
- Extract POP_LEFT_BASE/POP_LEFT_SPREAD named constants - Rename k → continuousGrowthRate for clarity - Add source citation comment for RATE_GROWTH_PER_YEAR - Add explanatory comment on counter-box overflow: visible change Agent-Logs-Url: https://github.com/nitrocode/token-deathclock/sessions/1579b618-82e8-4125-b282-8ddddafa27eb Co-authored-by: nitrocode <7775707+nitrocode@users.noreply.github.com>
📝 WalkthroughWalkthroughUpdates site version to 1.4.0, prepends structured changelog entries for v1.4.0–v1.1.0, adds an exponential dynamic token-rate model and exported growth constant, switches token accumulation to continuous exponential growth, updates counter UI to use dynamic rates and spawn a floating token increment, and adds tests for the new rate API. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Counter as Counter (02-counter.js)
participant State as State (00-state.js)
participant Core as Core (death-clock-core.js)
participant DOM as DOM/UI
User->>Counter: Tick / interval
Counter->>State: getCurrentTokens()
State->>Core: getDynamicRate(now)
Core->>Core: Compute exponential rate from BASE_DATE
Core-->>State: Return dynamic rate
State->>Counter: Return total tokens
Counter->>Counter: Compute increment since last
Counter->>DOM: Update display
Counter->>DOM: Spawn .token-pop with +increment
DOM->>DOM: Animate float & fade, then remove
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
nitrocode
commented
Apr 26, 2026
@copilot merge main to this branch and regenerate styles.css |
…visualization # Conflicts: # styles.css Co-authored-by: nitrocode <7775707+nitrocode@users.noreply.github.com>
Merge origin/main (mobile fixes from #74, #75) into branch, then rebuild styles.css from source so it contains both the mobile layout fixes and the token-pop animation styles. Agent-Logs-Url: https://github.com/nitrocode/token-deathclock/sessions/aedeb8a9-2599-40ef-a1a4-aa6d47261123 Co-authored-by: nitrocode <7775707+nitrocode@users.noreply.github.com>
👁️ PR Preview
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@## main #76 +/- ##
=========================================
Coverage 100.00% 100.00% =========================================
Files 1 1 Lines 233 242 +9 Branches 107 109 +2 =========================================
+ Hits 233 242 +9
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
src/js/02-counter.js (1)
51-53: Avoid cloning/reversingRATE_SCHEDULEon every frame.I pity the fool who burns cycles in
requestAnimationFrame— precompute a reversed schedule once outsideupdateCounters()and reuse it.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/js/02-counter.js` around lines 51 - 53, The code currently clones and reverses RATE_SCHEDULE inside updateCounters() every frame when computing rateEntry; move the reversed schedule creation out of the hot path by computing a single reversed array (e.g., REVERSED_RATE_SCHEDULE) once at module load time and then use REVERSED_RATE_SCHEDULE.find(...) inside updateCounters() instead of [...RATE_SCHEDULE].reverse(), ensuring any code that mutates RATE_SCHEDULE is instead done by replacing the array reference so the precomputed reversed copy stays correct.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@changelog-data.js`:
- Around line 5-133: You edited the generated artifact changelog-data.js
(contains SITE_VERSION and CHANGELOG_RELEASES) directly; instead update the
source CHANGELOG.md with your v1.4.0 release notes, then run the changelog
generator (npm run build:changelog) to regenerate changelog-data.js so
SITE_VERSION and CHANGELOG_RELEASES are produced correctly, and commit both the
updated CHANGELOG.md and the regenerated changelog-data.js together.
In `@src/js/02-counter.js`:
- Line 19: The current cleanup relies solely on
el.addEventListener('animationend', () => el.remove(), { once: true }) which can
leave .token-pop nodes if animations are interrupted; update the token-pop
teardown to also listen for 'animationcancel' and schedule a fallback timeout
(e.g., animationDuration + small buffer) that removes el if still in the DOM,
and ensure both the event listeners and the timeout clear each other to avoid
double removals; target the existing el variable and the addEventListener call
so you add an additional listener for 'animationcancel' and a cleanup timeout
alongside the existing 'animationend' handler.
In `@styles/counter-milestones.css`:
- Around line 64-83: The new .token-pop rule fails stylelint: change the
font-family value in .token-pop (currently 'Orbitron', monospace) to use the
project-preferred quoting (e.g. "Orbitron", monospace) to satisfy
font-family-name-quotes, and rename the `@keyframes` tokenPopFloat to a
lint-compliant kebab-case name (e.g. token-pop-float) and update the animation
reference in .token-pop (animation: token-pop-float 1.5s ease-out forwards;) so
the keyframes-name-pattern rule is satisfied; ensure both the `@keyframes`
declaration and any usages (animation/animation-name) use the new kebab-case
identifier.
---
Nitpick comments:
In `@src/js/02-counter.js`:
- Around line 51-53: The code currently clones and reverses RATE_SCHEDULE inside
updateCounters() every frame when computing rateEntry; move the reversed
schedule creation out of the hot path by computing a single reversed array
(e.g., REVERSED_RATE_SCHEDULE) once at module load time and then use
REVERSED_RATE_SCHEDULE.find(...) inside updateCounters() instead of
[...RATE_SCHEDULE].reverse(), ensuring any code that mutates RATE_SCHEDULE is
instead done by replacing the array reference so the precomputed reversed copy
stays correct.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 569eff41-ad09-4fb9-a9c9-950e77e85777
📒 Files selected for processing (8)
changelog-data.jsdeath-clock-core.jsscript.jssrc/js/00-state.jssrc/js/02-counter.jsstyles.cssstyles/counter-milestones.csstests/death-clock.test.js
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
…ata.js - changelog-data.js: reset to base and regenerate via npm run build:changelog so the file is properly derived from CHANGELOG.md, not edited directly - spawnTokenPop: add animationcancel listener + fallback timeout (1500+200ms) with a shared 'removed' flag so cleanup never double-fires - styles/counter-milestones.css: use double-quotes for "Orbitron" font-family and rename @Keyframes tokenPopFloat → token-pop-float (kebab-case) - updateCounters: hoist [...RATE_SCHEDULE].reverse() to module-level REVERSED_RATE_SCHEDULE constant, out of the per-frame hot path Agent-Logs-Url: https://github.com/nitrocode/token-deathclock/sessions/fedaea6d-9cc7-4df9-a304-fbde3025a7ec Co-authored-by: nitrocode <7775707+nitrocode@users.noreply.github.com>
There was a problem hiding this comment.
♻️ Duplicate comments (1)
styles/counter-milestones.css (1)
64-68:⚠️ Potential issue | 🟠 MajorDrop the quotes from Orbitron at Line 67 to clear stylelint.
I pity the fool who ships a red lint check — Line 67 still violates
font-family-name-quotes.🛠️ Suggested patch
.token-pop { position: absolute; bottom: 55%; - font-family: "Orbitron", monospace;+ font-family: Orbitron, monospace; font-size: 0.8rem; font-weight: 700;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@styles/counter-milestones.css` around lines 64 - 68, The .token-pop CSS rule uses a quoted font-family token "Orbitron" which triggers stylelint's font-family-name-quotes; remove the quotes so the declaration reads font-family: Orbitron, monospace; to satisfy the font-family-name-quotes rule and clear the lint error in the .token-pop selector.
🧹 Nitpick comments (1)
src/js/02-counter.js (1)
4-4: Precompute schedule timestamps to trim frame-loop churn.I pity the fool who reparses dates every frame — Line 66 can use precomputed epoch values.
♻️ Suggested refactor
-const REVERSED_RATE_SCHEDULE = [...RATE_SCHEDULE].reverse();+const REVERSED_RATE_SCHEDULE = [...RATE_SCHEDULE]+ .map((r) => ({ ...r, epochMs: new Date(r.date).getTime() }))+ .reverse(); ... -const rateEntry = REVERSED_RATE_SCHEDULE.find(- (r) => now >= new Date(r.date).getTime()-);+const rateEntry = REVERSED_RATE_SCHEDULE.find(+ (r) => now >= r.epochMs+);Also applies to: 65-67
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/js/02-counter.js` at line 4, Precompute epoch timestamps for the rate schedule to avoid reparsing dates each frame: extend the existing REVERSED_RATE_SCHEDULE (created from RATE_SCHEDULE) to map each entry to include a numeric epoch (e.g., timestamp or startEpoch) once at module init, then update the frame-loop code that currently calls Date.parse/new Date/getTime each frame (the code referenced around line 66) to use the precomputed epoch field instead of reparsing; keep the original RATE_SCHEDULE/REVERSED_RATE_SCHEDULE identifiers and only change consumers to read the new epoch property.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@styles/counter-milestones.css`:
- Around line 64-68: The .token-pop CSS rule uses a quoted font-family token
"Orbitron" which triggers stylelint's font-family-name-quotes; remove the quotes
so the declaration reads font-family: Orbitron, monospace; to satisfy the
font-family-name-quotes rule and clear the lint error in the .token-pop
selector.
---
Nitpick comments:
In `@src/js/02-counter.js`:
- Line 4: Precompute epoch timestamps for the rate schedule to avoid reparsing
dates each frame: extend the existing REVERSED_RATE_SCHEDULE (created from
RATE_SCHEDULE) to map each entry to include a numeric epoch (e.g., timestamp or
startEpoch) once at module init, then update the frame-loop code that currently
calls Date.parse/new Date/getTime each frame (the code referenced around line
66) to use the precomputed epoch field instead of reparsing; keep the original
RATE_SCHEDULE/REVERSED_RATE_SCHEDULE identifiers and only change consumers to
read the new epoch property.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: bda68672-d2ae-4809-9d05-1455bd612ac6
📒 Files selected for processing (4)
script.jssrc/js/02-counter.jsstyles.cssstyles/counter-milestones.css
- Resolve add/add conflicts for all 11 conflicted files - Use origin/main base for workflow files, .gitignore, AGENTS.md, package.json - Merge our branch additions into death-clock-core.js: RATE_GROWTH_PER_YEAR, getDynamicRate(), exponential getCurrentTokens() integration - Merge our branch additions into src/js/02-counter.js: REVERSED_RATE_SCHEDULE, spawnTokenPop() with animationend/animationcancel/fallback cleanup - Merge our branch .token-pop CSS into styles/counter-milestones.css - Merge our getDynamicRate unit tests into tests/death-clock.test.js - Run git rm --cached for 5 generated files now excluded by .gitignore - All 262 tests pass with 100% coverage Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: nitrocode <7775707+nitrocode@users.noreply.github.com>
Uh oh!
There was an error while loading. Please reload this page.
git rm --cached