Status 2026-07-13: implemented on feature/130-report-builder (#608) — as-built notes in the #130 status section.
Parent: #130 (Report Builder — bands + bricks). Phase 2 (needs Phase 1: #521, #528). Part of epic #506, Track A.
Scope
Moving a brick between bands (e.g. move the client phone from Header into Footer) happens through a "Move to band…" action on the placed brick — not by dragging across canvases. Since each band is its own Mason canvas (#523), cross-canvas dragging is deliberately out of scope; the action approach is deterministic and testable.
- The action lists only the target bands allowed by the brick's
allowedBands().
- Moving preserves the brick's config and width; the brick is appended to the target band.
- The original v1 ask ("move the client's phone number to the company information block") is covered at brick-config level too: field-level visibility toggles in the Company/Client brick configs.
Acceptance criteria
Test scenarios (PHPUnit + Livewire, #[Test], no Pest)
- Move a
header_client brick from header to footer; assert bands.json reflects source removal + target append with config intact.
- Assert a details-only brick offers no move targets.
Status 2026-07-13: implemented on
feature/130-report-builder(#608) — as-built notes in the #130 status section.Parent: #130 (Report Builder — bands + bricks). Phase 2 (needs Phase 1: #521, #528). Part of epic #506, Track A.
Scope
Moving a brick between bands (e.g. move the client phone from Header into Footer) happens through a "Move to band…" action on the placed brick — not by dragging across canvases. Since each band is its own Mason canvas (#523), cross-canvas dragging is deliberately out of scope; the action approach is deterministic and testable.
allowedBands().Acceptance criteria
bands.jsonand is gone from the source band.allowedBands()is a single band shows no move targets.Test scenarios (PHPUnit + Livewire,
#[Test], no Pest)header_clientbrick from header to footer; assertbands.jsonreflects source removal + target append with config intact.