From fcf6ed352309a8c049561a5e6b950998ea412a35 Mon Sep 17 00:00:00 2001 From: Patrik Simms Date: Tue, 18 Aug 2026 23:28:07 +0200 Subject: [PATCH] feat(layouts): add sunset arches and postcard frame backgrounds Summary: - add two ready-made page backgrounds to the layout background picker, built only from locked rectangles and circles - show the picker as a two-column grid so four options stay readable - derive the analytics background_id from BackgroundPresetId so it cannot drift from the offered presets - cover the new presets with unit and end-to-end assertions and add before/after evidence for issue 63 Rationale: - organizers previously had one decorated starting point, so pages were either bare or repeated the same collage - both presets are axis-aligned: the browser rotates shapes around their top-left corner and the PDF export around the bottom-left, so rotation-free compositions print the way they preview - rules are thin filled rectangles rather than stroked outlines because the PDF renderer paints a "transparent" fill as black - every element stays inside the media box, so neither preset triggers a bleed warning Tests: - bun run format:check, lint, typecheck - bun run test (216 passed) - SAKEKEEP_E2E_PORT=3100 bun run test:e2e (20 passed, 2 skipped) - bun run build, docker compose config, check-production-compose Related to #63 AI-Assisted-By: Codex AI-Assisted: true AI-Agent: claude-code AI-Model: anthropic/claude-opus-5 --- e2e/critical-workflows.spec.ts | 6 + src/components/layout-editor.tsx | 2 +- src/domain/layout-backgrounds.test.ts | 28 ++- src/domain/layout-backgrounds.ts | 188 +++++++++++++++++- src/lib/analytics.ts | 3 +- .../issues/63/after-background-picker.png | Bin 0 -> 193805 bytes .../issues/63/after-postcard-frame-page.png | Bin 0 -> 7383 bytes .../issues/63/after-sunset-arches-page.png | Bin 0 -> 12943 bytes .../issues/63/before-background-picker.png | Bin 0 -> 200611 bytes 9 files changed, 222 insertions(+), 5 deletions(-) create mode 100644 visual-artifacts/issues/63/after-background-picker.png create mode 100644 visual-artifacts/issues/63/after-postcard-frame-page.png create mode 100644 visual-artifacts/issues/63/after-sunset-arches-page.png create mode 100644 visual-artifacts/issues/63/before-background-picker.png diff --git a/e2e/critical-workflows.spec.ts b/e2e/critical-workflows.spec.ts index 7608f65..818a690 100644 --- a/e2e/critical-workflows.spec.ts +++ b/e2e/critical-workflows.spec.ts @@ -564,6 +564,12 @@ test.describe.serial("critical local prototype workflows", () => { await expect( page.getByRole("button", { name: "Create Geometric collage background" }) ).toBeVisible() + await expect( + page.getByRole("button", { name: "Create Sunset arches background" }) + ).toBeVisible() + await expect( + page.getByRole("button", { name: "Create Postcard frame background" }) + ).toBeVisible() await page.getByRole("button", { name: "Create Geometric collage background" }).click() await expect(page.getByRole("heading", { name: "Choose a background" })).not.toBeVisible() diff --git a/src/components/layout-editor.tsx b/src/components/layout-editor.tsx index b96e06e..95e713b 100644 --- a/src/components/layout-editor.tsx +++ b/src/components/layout-editor.tsx @@ -144,7 +144,7 @@ function BackgroundPicker({ onCreate }: { onCreate: (preset: BackgroundPreset) = Decorative elements start locked and can be unlocked in the editor. -
+
{BACKGROUND_PRESETS.map((preset) => (