Skip to content

v1#221

Merged
yoannmoinet merged 183 commits intomasterfrom
yoann/v1
Mar 21, 2026
Merged

v1#221
yoannmoinet merged 183 commits intomasterfrom
yoann/v1

Conversation

@yoannmoinet
Copy link
Copy Markdown
Owner

@yoannmoinet yoannmoinet commented Feb 19, 2025

NippleJS v1 — Complete Rewrite

Infrastructure

  • Yarn 4 monorepo with workspaces: nipplejs, docs, tests, tools, assets
  • TypeScript throughout — branded types, strict mode, full type exports
  • Rollup bundler (ESM + CJS + types)
  • ESLint flat config + Prettier
  • Jest unit tests (196 tests) + Playwright e2e tests (50 tests)
  • CI: unit, e2e, lint, typecheck (including docs) on PRs
  • Release workflow: publish to NPM with OIDC provenance on GitHub release or manual dispatch

Core Library

  • Full class hierarchy: SuperFactory / Collection / Joystick
  • Event system: on/off/trigger with typed overloads, space/comma-separated multi-event strings
  • Single-argument event handler (evt) => { evt.type, evt.data } (breaking change from v0 two-arg style)
  • Pointer Events primary, Touch/Mouse fallback (removed IE MSPointer dead code)
  • SSR-safe: window access guarded with typeof checks

New Features

  • logLevel API: nipplejs.setLogLevel('debug'|'info'|'warning'|'error'|'none')
  • collection.reposition() — manual recalculation of zone/joystick positions
  • ResizeObserver on zone — automatic repositioning on zone resize
  • baseDelta in move event data when follow: true — per-frame base displacement
  • color: { front, back } — style thumb and base independently with gradients, images, any CSS background
  • Zone position warning — warns if zone has position: static
  • move event fires continuously on every pointermove (was direction-change only in v0)

Bug Fixes

  • preventDefault() on pointerdown broke multitouch — now only called on move events
  • addToDom() duplicate added event
  • cleanInactiveTouches spreading native event objects (prototype props lost)
  • Throttle closure leak in Factory resize/scroll handlers
  • trigger() handler Set mutation during iteration
  • Semi mode recursion guard
  • applyPosition treating undefined coords as 0

Documentation Website

  • Astro 6 + Tailwind CSS 4, "Aurora Neon" dark theme
  • 5 interactive canvas game demos showcasing options: mode: 'static', lockX, multitouch, follow + baseDelta, restJoystick: false
  • Carousel with perspective tilt, blur (Firefox-detected fallback), fullscreen mode
  • Code pane (Shiki), debug overlay, click-to-start
  • Mobile optimized: disabled particles/grid highlight on touch, game loops paused on non-active slides
  • GitHub Pages deployment

Breaking Changes (v0 → v1)

  • maxNumberOfNipplesmaxNumberOfJoysticks
  • destroyed event → joystickDestroyed
  • joystick.eljoystick.ui.el
  • show(), hide(), add(), remove() removed
  • manager.get()manager.getJoystickByUid() or manager.all
  • manager.idmanager.uid, manager.ids removed
  • Event handler: (evt, data)(evt) with evt.data

yoannmoinet and others added 29 commits March 20, 2026 14:23
… asteroid tilt

Performance:
- Skip shadowBlur on mobile (isMobile detection) across all 5 games
- Clear all game arrays in destroy() to prevent memory leaks

Snake (fog-explorer):
- Radial gradient head with eyes that follow heading direction
- Connecting gradient lines between segments for a body feel
- Pulsing glow trail behind body (desktop only)

Asteroid Dodge:
- Subtle canvas tilt (lerped) in direction of horizontal movement

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove z-10 from arrow buttons, add z-10 to the track wrapper instead.
The entire track (active slide + code pane) now stacks above the arrows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Snake (fog-explorer):
- Green/emerald color scheme (#10b981) — completely distinct from orbs
- Thick connected body path with dark border outline + highlight stripe
- Bigger head (12px), larger segments (9px), prominent white eyes
- Joystick color updated to match green theme

Space Observatory (endless-chase):
- Extract inline SVG scope to public/assets/scope.svg file
- Update code snippet to show file reference

Asteroid Dodge:
- Reverse tilt direction (counter-steer feel)
- Make background motion lines 2.5x more visible (0.06 → 0.15 opacity)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
15ms was too short to feel on most Android devices. Bumped collection
games to 50ms, dual-stick to 50ms*intensity, asteroid death to 100ms.
Note: navigator.vibrate is Android-only (not supported on iOS Safari).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Vibration:
- Prime navigator.vibrate(1) from joystick 'start' event handler
  (fires within pointerdown user activation context)
- Subsequent vibrate() calls from rAF now work because sticky
  activation was established from a real user gesture
- Wrapped in try/catch with optional chaining for safety

Code panel:
- Add touch-action: pan-y on .demo-code-inner so code can be scrolled
  on mobile when the panel is above the game

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…on, Firefox speed

- Close code pane automatically when switching games
- Fix code panel scroll on mobile: touch-action: pan-y + max-height on
  the actual scrollable element, not the wrapper
- Remove all navigator.vibrate code (unreliable across browsers)
- Add 1.3x speed multiplier on Firefox to compensate for lower Canvas2D
  frame rates

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
goTo() now closes all open code panes immediately when switching slides,
not just when games are destroyed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Sidebar/MobileNav: "Fog Explorer" → "Neon Snake", "Endless Chase" →
  "Space Observatory", fix anchor hrefs to match heading slugs
- Events page: update all code examples from (evt, data) to (evt) with
  evt.data (v1 single-argument signature)
- Migration page: fix "After (v1)" examples that still used (evt, data)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… border

Asteroid Dodge:
- Pre-clear canvas before tilt to hide edge artifacts
- Overdraw background by 40px padding for corner coverage
- More visible motion lines (0.25 opacity, 1.5px width)

Dual-Stick Arena:
- Move icon (4-way arrows) on left joystick thumb
- Shoot icon (crosshair) on right joystick thumb
- Uses SVG files layered over gradient backgrounds

Space Observatory:
- Joystick back ring more visible with harder-edge radial gradient
  that creates a visible border at 93% radius

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Space Drift:
- Exhaust particles spawn from the back of the ship while joystick
  is active. Quantity (1-3) and speed scale with joystick force.
  Colors alternate between violet and pink.

Dual-Stick Arena:
- Icons changed to white with full opacity for maximum visibility
- Icon size increased from 60% to 75% of thumb area
- Thicker strokes (3px lines, 2.5px crosshair)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The back element's gradient alpha values are multiplied by the
joystick's restOpacity (0.5), making them barely visible. Bumped
ring alpha to 0.8 and fill to 0.15-0.25 for clear visibility.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Speed 0.5-2 → 2-6 px/frame, length 10-40 → 15-55 px for a stronger
sense of downward velocity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Code snippets:
- Dual-stick: show SVG icon + gradient layering pattern
- Observatory: match actual radial gradient with border ring
- Keep snippets in sync with game files going forward

Space Observatory joystick:
- Back border now uses #38bdf8 at 100% alpha (93% radius) with
  transparent outer edge, creating a crisp visible ring even at
  restOpacity 0.5

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…s force

With restJoystick: false, the joystick retains its position after
release. Don't zero joystickForce on 'end' so exhaust particles
keep firing as long as the ship is drifting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Changed gradient border from #38bdf8 (cyan) to #ffffff (white) at 94%
radius for a crisp, clearly visible ring. Snippet updated to match.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use a 5% wide solid white band (91-96%) with a gap before it (87-90%)
to create a clearly visible ring that doesn't blend into the fill.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The back element had its own opacity: 0.5 in addition to the parent
el's restOpacity (also 0.5), resulting in 0.25 effective opacity. This
made custom back gradients nearly invisible. The parent el already
controls opacity via restOpacity — the back element shouldn't double it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The parent el's restOpacity (0.5) was making the gradient invisible.
Set restOpacity: 1 for this game since the scope is a permanent UI
element, and reduced gradient fill alpha to compensate. White ring at
92-95% is now fully visible. Verified with Playwright screenshot.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Capture hero section at three sizes:
- 1200x630 (Open Graph / Facebook / LinkedIn)
- 1200x600 (Twitter/X summary_large_image)
- 800x800 (square, WhatsApp/Slack fallback)

Add og:image, og:title, og:description, twitter:card meta tags to
BaseLayout so all pages inherit them.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Asteroid Dodge:
- Speed increment 0.25 → 0.4 per interval
- Interval every 150 → 120 frames (~2s)
- Spawn interval starts at 50 (was 60), decreases by 4 (was 3), min 10
- After 20s: speed ~8.6 (was ~5), spawn every ~10 frames (was ~24)

Dual-Stick Arena:
- Difficulty ramp every 400 frames (~6.5s, was 600/~10s)
- Spawn interval decreases by 10 per level (was 8), min 12 (was 20)
- Enemy speed +0.25 per level (was +0.15)
- After 30s: ~5 levels, speed 2.25 (was 1.75), spawn every 25 (was 50)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…g bar

Capture just the logo, title, and tagline using Playwright clip regions,
then composite centered onto exact-size backgrounds (#08081a).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add id to hero section for targeting. Capture by injecting extra
padding at screenshot time so the aurora background fills the full
image — no header, no buttons, no solid color bars.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CLAUDE.md now points to AGENTS.md. AGENTS.md updated with:
- 196 unit tests, release workflow, astro check in CI
- preventDefault only on move, user-select: none, SSR-safe constants
- Game architecture: mobile perf (no shadowBlur), speedScale, Firefox
  1.3x, particle effects, memory cleanup, difficulty ramp
- Game-specific: snake green theme, asteroid tilt, dual-stick SVG icons,
  observatory scope SVG + restOpacity, space drift exhaust
- JoystickDemo: z-index layering, code pane reposition, snippet sync
- Carousel: z-index, code pane close on navigate, Firefox blur skip
- OG images: Playwright capture process, three sizes, meta tags

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fog-explorer.ts → neon-snake.ts
endless-chase.ts → space-observatory.ts

Updated all references in JoystickDemo.astro, index.astro, examples.mdx,
options.mdx, and AGENTS.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add @astrojs/check to docs for CI typecheck
- Move build-only deps to devDependencies in docs and tests packages
- Only nipplejs remains as a runtime dependency
- Normalize package.json formatting (4-space indent)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@yoannmoinet yoannmoinet merged commit ecada8f into master Mar 21, 2026
3 checks passed
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.

1 participant