From 19ee00f14adedde33efd8bd6876db7aa9e24599d Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Thu, 21 May 2026 22:40:41 -0400 Subject: [PATCH] Tighten Artstr Stacks spec after review pass - Aspect-ratio changes now re-fit cards via the existing import-letterbox remap instead of stranding layers off-canvas; imports target the stack's aspect, not a hardcoded 16:9. - Clarify how the shared deck renderer is fed for stacks (dims from stack, background from card) and startCard deletion fallback. - Viewer: action regions are focusable buttons (Tab/Enter, screen readers); empty-space clicks are no-ops; goto-card keywords clamp at the ends; touch taps act as clicks; persist the edited card before launching; encrypted-stack locked state on the /p/ route. - Fix the hit-testing risk note (rotation is exact; only clip-masked layers fall back to a bounding box) and add an accessibility row. Co-Authored-By: Claude Opus 4.7 --- docs/STACKS_FEATURE.md | 64 ++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/docs/STACKS_FEATURE.md b/docs/STACKS_FEATURE.md index 25a4a5f..b68afd3 100644 --- a/docs/STACKS_FEATURE.md +++ b/docs/STACKS_FEATURE.md @@ -143,8 +143,14 @@ wholesale. An `isDeckLike(mode)` helper covers both `'deck'` and drops `notes`, and its `layers` may carry `action`s. Canvas dimensions live at the **stack** level (every card shares the aspect) rather than per-card — all cards in a stack are the same size. -- The deck's render-time theme composition (`composeSlideForDeck`) is - reused as-is (`ignoreStackTheme` mirrors `ignoreDeckTheme`). +- **Feeding the shared renderer:** the deck's renderer / theme composition + read a per-entry `{ slide: {width,height,background}, layers }` shape. + For a stack, the engine synthesises that on the fly — `width`/`height` + from `stack`, `background` from the card — so `renderCustomArtPreviewDOM` + and `composeSlideForDeck` are reused untouched. (`ignoreStackTheme` + mirrors `ignoreDeckTheme`.) +- **`startCard`** holds a card `id`; if that card is deleted it falls back + to the first card. ### The `action` on a layer @@ -191,11 +197,15 @@ The Deck Builder sorter, reused. A new **Stack** option in the Template- tab Layout panel (beside Case cover / Disc labels / Slide deck). The sidebar adds a **Stack** panel: -- **Aspect ratio** — 16:9 / 9:16 / 1:1 / 4:3 / custom. Chosen up front; - changing it resizes every card's canvas (layers keep their inch - positions; a warning notes some may need nudging). +- **Aspect ratio** — 16:9 / 9:16 / 1:1 / 4:3 / custom. Chosen up front. + Changing it later **re-fits every card** by reusing the deck's existing + import-letterbox remap (`deckSlideFromImport`'s scale-to-fit + centre + math) — layers scale and centre into the new aspect instead of being + stranded off-canvas. The user confirms before a re-fit runs. - **Add card** (blank / import a design / import from Nostr), duplicate, - delete, drag-reorder, inline-rename — all from the deck sorter. + delete, drag-reorder, inline-rename — all from the deck sorter. Imports + letterbox onto the **stack's** aspect, not a hardcoded 16:9 — the + existing remap is generalised to take a target width/height. - **Start card** — which card the viewer opens on (default: first). - A **Stack theme** panel (font + background), reused from the deck. @@ -224,16 +234,27 @@ The fullscreen runtime, built on the Presenter Mode engine: - Renders the current card full-screen, letterboxed to the stack aspect, themed (`composeSlideForDeck` reused), via `renderCustomArtPreviewDOM`. - An **action overlay** sits above the card: for each layer with an - `action`, a positioned, pointer-enabled hit region (matching the - layer's box). A hovered actionable region shows a pointer cursor. -- **Click routing:** `goto-card` → navigate (resolving keywords / - ids); `open-url` → a confirm dialog showing the destination, then open - in a new tab. + `action`, a positioned hit region matching the layer's (transformed) + box. The regions are real **`