Skip to content

Full M4 responsive builder scope: multi-scene + layer editing - #6

Merged
reshimu merged 1 commit into
mainfrom
full-m4-builder-scope
Jul 28, 2026
Merged

reshimu merged 1 commit into
mainfrom
full-m4-builder-scope

Conversation

@reshimu

@reshimu reshimu commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Summary

  • Brought SceneBuilder.tsx from the round-trip minimum up to the scope named across multiple sessions in NEXT_TASK.md: "drag/drop layer editing" and "multi-scene management."
  • Added src/components/builderState.ts: pure, unit-tested helpers (createLayer, removeLayer, moveLayer, reorderLayers, createScene, duplicateScene) plus localStorage-backed loadBuilderState/saveBuilderState (SSR-guarded, validates stored scenes through validateScene).
  • Rewrote SceneBuilder.tsx: scene switcher (new/switch/duplicate/delete, persisted across reloads), Title/Eyebrow text fields, and a generic per-layer editor — any layer type can be added/removed/reordered via native drag-and-drop or keyboard-accessible ↑/↓ buttons (drag alone isn't keyboard-operable; AGENTS.md requires keyboard access).
  • 27 new tests (18 pure-logic, 9 component-level via Testing Library).

Real bug found and fixed during verification

src/react.ts imports the whole styles.css, and CSS isn't tree-shaken — .builder/.demo-format rules (dev-tool only, never exported) were bundled into the public react.css, inflating it for every consumer. Caught by watching it grow to 12.98 kB. Fixed by splitting into src/styles.css (public) and a new src/demo.css (demo-only, imported only by src/main.tsx) — react.css dropped to 10.08 kB, smaller than before this slice even started.

This resolves RISK_PERFORMANCE_AUDIT.md's R-009 — the last item in the risk register with an open resolution path. Every item (R-001–R-009) is now resolved or an explicitly-accepted Low/Informational item.

Test plan

  • pnpm typecheck / pnpm lint / pnpm test (15 files/70 tests, up from 13/43) / pnpm build / pnpm test:consumer / pnpm test:react-consumer / pnpm test:nextjs-consumer / pnpm check:bundle-size — all pass
  • Live-verified in a real browser: add/remove/move/drag-and-drop layer reordering, full multi-scene lifecycle, localStorage persistence across an actual reload, and correct responsive collapsing with no horizontal overflow at 320px

🤖 Generated with Claude Code

Brought SceneBuilder.tsx from the round-trip minimum up to the scope
named in ROADMAP.md's original M4 outcome and repeated across
NEXT_TASK.md for multiple sessions: "drag/drop layer editing" and
"multi-scene management," neither of which existed before this.

Added src/components/builderState.ts: pure, unit-tested helpers
(createLayer, removeLayer, moveLayer, reorderLayers, createScene,
duplicateScene) plus loadBuilderState/saveBuilderState
(localStorage-backed, guarded for typeof window === 'undefined',
validates every stored scene through the existing validateScene so
corrupted/old-shape localStorage data can't crash the builder -- it's
silently dropped instead). 18 new unit tests, no DOM needed.

Rewrote SceneBuilder.tsx: a scene switcher (select + New/Duplicate/
Delete, persisted to localStorage), Title/Eyebrow text fields
(previously only editable via raw JSON import -- a real gap), and a
generic per-layer editor replacing the old three hardcoded sliders --
any layer type can now be added (only offering types not already
present), removed, and reordered via either native HTML5 drag-and-drop
(mouse/touch) or keyboard-accessible up/down buttons (drag-and-drop
alone isn't keyboard-operable, and AGENTS.md requires keyboard access).

Added 9 new SceneBuilder.test.tsx tests: add/remove a particles layer,
move-up/move-down with correct disabled-state at the boundaries,
new/switch/duplicate/delete scene flows (including that edits to one
scene don't leak into another), state persisting across a component
remount, and that the existing export->import round-trip still works
end-to-end with the new generic layer model.

Real bug found and fixed during verification, not before: src/react.ts
imports the whole styles.css file, and CSS isn't tree-shaken the way JS
is -- the .builder/.demo-format rules (used only by this repo's own dev
tooling, never exported) were being bundled into the public react.css
regardless, inflating it for every consumer. Caught by watching
react.css's size grow to 12.98 kB while adding builder-only styles.
Fixed by splitting into src/styles.css (public design-system styles,
imported by src/react.ts) and a new src/demo.css (demo-only builder/
gallery chrome, imported only by src/main.tsx) -- dist/lib/react.css
dropped to 10.08 kB, smaller than its size before this slice even
started, since the split removed styles that had been silently along
for the ride all along.

Live-verified in a real browser: add/remove/move/drag-and-drop layer
reordering, new/switch/duplicate/delete scenes, and localStorage
persistence surviving an actual page reload -- all confirmed via direct
DOM/state inspection. Confirmed no horizontal overflow and correct
responsive collapsing (scenes bar to a column, builder layout to one
column) at 320px width.

This resolves RISK_PERFORMANCE_AUDIT.md's R-009 -- the last item in the
risk register with an open resolution path. Every item (R-001-R-009) is
now resolved or an explicitly-accepted Low/Informational item.

Validated: typecheck, lint, test (15 files/70 tests, up from 13/43),
build, test:consumer, test:react-consumer, test:nextjs-consumer,
check:bundle-size all pass.
@reshimu
reshimu merged commit a70d283 into main Jul 28, 2026
1 check passed
@reshimu
reshimu deleted the full-m4-builder-scope branch July 28, 2026 16:40
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.

2 participants