clone

a browser grid puzzle game where you push words around to rewrite the rules of each level

main
miau-is-true / openspec / changes / archive / 2026-09-24-fix-gift-card-layout / design.md
design.md 3.5K source

Context

Gift is rendered on a canvas from src/scenes/gift.js. The current card derives preview and action positions from fixed offsets inside a centered card, so a desktop shared-pack preview can consume the same vertical region as the action buttons. Mobile cards also need independent vertical placement because the available width and height are smaller.

Goals / Non-Goals

Goals:

  • Define separate content, preview, metadata, actions, and hint regions within the card.
  • Keep every action visible and inside the card at desktop and mobile sizes.
  • Keep button hit targets at least 44 CSS pixels high and preserve keyboard selection order.
  • Make collision mode use the same layout contract for Replace, Keep Both as a Copy, and Cancel.
  • Verify the shared URL Gift path and reduced-motion rendering.

Non-Goals:

  • Changing pack payloads, preview data, installation confirmation, or duplicate policy.
  • Reworking the designer's visual language, typography, or board art beyond placement needed to prevent overlap.
  • Adding a DOM layout fallback or a new UI dependency.

Decisions

Reserve the action region before sizing the preview

Compute card geometry from viewport size, reserve the action stack and footer hint first, then fit title, metadata, and board preview into the remaining content rectangle. This keeps actions stable as level titles and preview boards vary. A purely fixed preview height was rejected because it can still collide on shorter desktop windows.

Use one responsive layout contract with stacked mobile actions

Desktop may place the preview beside the action column when space allows; narrow cards SHALL stack preview above actions. Both modes use the same hit rectangles and minimum button height. Separate desktop and mobile implementations were rejected because they drift in keyboard and pointer behavior.

Keep preview clipping local to its content region

Clip or scale only the board preview to its assigned rectangle. Text metadata and action labels remain independently measurable and are never allowed to draw into the action region. Allowing the whole card to overflow was rejected because it hides controls and creates ambiguous pointer targets.

Test geometry as observable layout data

Expose or inspect the scene's rendered button rectangles and assert containment, non-overlap, and viewport margins in unit tests. Browser checks then verify the visible shared URL Gift card and actual pointer/keyboard activation. Screenshot-only coverage was rejected because it does not prove hit target geometry.

Risks / Trade-offs

  • [Risk] Long pack names or level titles reduce preview space. → Fit text to its content region and preserve the action region as the highest priority.
  • [Risk] Very short viewports may not fit all content simultaneously. → Keep the card within safe margins, allow the content preview to scale or clip, and keep actions reachable in the scroll-free canvas scene.
  • [Risk] Desktop and mobile hit rectangles diverge. → Share action construction and assert keyboard/pointer parity in both layouts.

Migration Plan

  1. Update Gift geometry and drawing/hit testing together.
  2. Add unit regressions for desktop, mobile, collision, and reduced-motion layout.
  3. Run browser shared URL Gift checks at desktop and mobile widths.
  4. Roll back by reverting the scene geometry and tests; no persisted data migration is required.

Open Questions

None for this focused fix. Final visual spacing remains subject to the existing designer reference review.