Cardback reminder gate + apply-all/set-default prompts + PDF-wait experience - #431
Merged
Conversation
…t experience (progress bar + What's That Card? embed) Implements SPEC-cardback-pdfwait.md PKG1 (no-cardback reminder gate, toolbar/rail apply-all + set-default prompts with affected-slot thumbnails, custom-cardback flip-icon indicator) and PKG2 (determinate/ indeterminate PDF generation progress bar, embedded What's That Card? game during PDF wait with teardown-to-outro). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…gress-bar text assertion, .modal-content bg after #425's theme-defaults pass PR #427 (landed after this branch's original base) un-skipped PDFGenerator.spec.ts/PagePreview.spec.ts/PostExportContributionPrompt.spec.ts onto the shared navigateToPrintPDFTab helper, which the new cardback reminder gate now intercepts; PR #425's theme-defaults pass separately re-routed every Modal's content background to $theme-raised-bg. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
WilfordGrimley
force-pushed
the
feat/cardback-pdfwait-flow
branch
from
July 24, 2026 16:52
46c8c68 to
6164559
Compare
4 tasks
WilfordGrimley
added a commit
that referenced
this pull request
Jul 24, 2026
…ty (#441) rail-delegacy, editor-polish, cardback-pdfwait, wtc-rebuild — each cited by filename in committed code comments (the first three now on master via PR #431) but previously living only in a session tmp dir that dies with the session. Verbatim copies + companion mockup HTML, same durability convention as reference/funnel-spec.md.
WilfordGrimley
added a commit
that referenced
this pull request
Jul 24, 2026
…I onto Tokyo-11 PR #431 landed after the original sweep with its own hardcoded #302-derived literals (CardbackApplyPrompt.tsx, useCardbackReminderGate.tsx, PDFWaitPanel.tsx, SlotCardbackControl.tsx, plus a new DisplayPage.tsx line) - migrated onto var(--bs-*)/var(--theme-*) tokens the same way the rest of the sweep was, including simplifying the primary/info/success at-rest button text to use the token directly (Tokyo-11's action colours are light enough, unlike #302's, so the separate hand-picked tint literals aren't needed any more). CardbackPdfWaitFidelity.spec.ts's own literal assertions updated to match, comment-linked per row. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
WilfordGrimley
added a commit
that referenced
this pull request
Jul 24, 2026
… Semi radius) (#438) * Re-theme site to Tokyo-11 (Tokyo Night base, orange action, purple accent, Semi radius) Owner-ruled palette swap (theme-options study, palette 11) on top of #425's token-layer pass: new colour/radius tokens in _theme-tokens.scss, Bootstrap variable + runtime var(--bs-*)/var(--theme-*) wiring in styles.scss (incl. the AAA button-ink flip and a WCAG/APCA audit fold-in: opaque accent focus ring, .btn-close/.fbtoggle target-size fixes, a lightened muted token), accent wiring across D14/chips/toggles/selection outlines, a sitewide sweep of hardcoded old-palette literals onto token references, and matching DisplayLeftRailFidelity.spec.ts updates. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Merge master (#427/#405/#440), re-theme PR #431's cardback+PDF-wait UI onto Tokyo-11 PR #431 landed after the original sweep with its own hardcoded #302-derived literals (CardbackApplyPrompt.tsx, useCardbackReminderGate.tsx, PDFWaitPanel.tsx, SlotCardbackControl.tsx, plus a new DisplayPage.tsx line) - migrated onto var(--bs-*)/var(--theme-*) tokens the same way the rest of the sweep was, including simplifying the primary/info/success at-rest button text to use the token directly (Tokyo-11's action colours are light enough, unlike #302's, so the separate hand-picked tint literals aren't needed any more). CardbackPdfWaitFidelity.spec.ts's own literal assertions updated to match, comment-linked per row. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Fix PagePreview.tsx CustomCardbackDot missed by #431 merge sweep Post-merge re-scan (coordinator's ask) caught one more #302-derived literal (#431's own PagePreview.tsx diff) - the flip-button custom-cardback indicator dot's warning colour wasn't yet routed to var(--bs-warning). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements
SPEC-cardback-pdfwait.md(both packages, including the 2026-07-24 owner amendments) end to end.PKG1 — cardback flow
useCardbackReminderGate), composed intousePrePrintSaveGate.startPrintFlowand independently intoPDFGenerator.tsx's classic direct Generate/Save-to-Drive buttons (spec's own coverage note — a user can reach/printwithout ever going through the editor's Finish footer). Amendment 1: dismiss (✕/Esc/backdrop) = "use current & continue", not cancel — implemented viaModal onHide. Fires once per print attempt; a per-projectsessionStoragesuppression (cardbackReminderSuppression.ts) makes a second attempt in the same session silent (CB1), shared by both call sites.CardbackApplyPrompt.tsx), one shared component for both entries: toolbar (project-wide, inline in the sameGridSelectorModalvia new additivecloseOnSelect/footerContentprops — never a stacked modal) and rail (new per-slotSlotCardbackControl.tsx, reusingGridSelectorResults's"embedded"variant — no modal at all). Amendment 2/OQ-B: override-with-count, plus front+current-custom-back thumbnails of every affected slot rendered above the count line, never pre-checked. NewapplyCardbackToAllSlotsreducer overrides every slot unconditionally (including custom ones); a newcardbackExplicitlySetflag onProject(set only by real user picks — theexplicit: truepayload flag — never bylistenerMiddleware.ts's own auto-seed effect) drives the gate's fire condition.cardbackDefaultPreference.ts's "Set as my default" write is an explicit, documented no-op seam (Annex A-2): the spec's own suggested anonymous-localStorage approach conflicts with this repo's standing "no localStorage for state that should survive clear-site-data" rule without a real backend contract to write the authenticated half against, so the UI/done-state is real but the persistence layer is deferred, not silently implemented against that rule.⟲flip icon (PagePreview.tsx) gains a small warning-token indicator dot whenever that slot's back differs from the deck default — same gating as the flip icon itself,aria-labelupdated, no new color role.PKG2 — PDF-generation wait experience
ProgressBar(PDFWaitPanel.tsx'sPDFProgressBox) replacing the old bare "Fetching images: N/M" text — determinate while fetching (capped 99%, never a false 100%), a hand-built indeterminate track for assembling (not<ProgressBar>— react-bootstrap always emits a realaria-valuenowfromnowwith no way to suppress it, which would have announced a false "100%" to a screen reader mid-assembly; caught by this round's own accessibility read of §G), green on done.PDFWaitGameEmbedrenders<QuestionFeed>verbatim (no forked component, no new voting mechanic) vianext/dynamic({ssr:false}), lazy-loaded only once generation starts, torn down the instant it finishes. Amendment 4/OQ-C: teardown-to-outro — the existingPostExportContributionPromptbecomes the embed's outro; the standalone bottom-of-settings mount is suppressed whenever the embed is already showing it (one nudge, not two).waitPhasestate machine initially misclassified the brief pre-first-callback window (imageFetchProgress == null) as "assembling" instead of "fetching" — fixed.Deviations from spec
Modal/Offcanvasprimitives are used throughout instead, per the repo's existing "shared components gain only additive props" discipline. Token values (color/border/spacing) are binding and verified (see below); the phone modal is a centered dialog, not a bottom sheet.docs/lessons.md's concurrent-worktree-port guidance — not part of this diff (temp config, deleted before commit).Verification
tsc --noEmit: clean.jest: 69 suites / 603 tests pass (14 new:cardbackApply.test.ts,cardbackReminderSuppression.test.ts,CardbackApplyPrompt.test.tsx,useCardbackReminderGate.test.tsx, plusPagePreview.test.tsx/projectSlice.test.tsadditions).prettier/eslinton every changed/new file: clean (pre-commit hook also ran clean).CardbackFlow.spec.ts(reminder gate incl. dismiss-continues + session suppression; rail per-slot entry with trapnote; toolbar entry with thumbnails+count; both apply-all and set-default flows),PDFWaitExperience.spec.ts(fetch→assemble→done phases; game embed lazy-mount/teardown/outro-suppression; classic-direct-path guard),CardbackPdfWaitFidelity.spec.ts(computed-style self-verification against the binding token table). Full suite run twice at 4 workers, isolated port: 294 passed both times; the only non-green items were (a) 3 pre-existing tests unrelated to this change that failed only under full-suite parallel contention and passed clean in isolation (AddCardToProjectForm.spec.ts,GeneralUIAccessibility.spec.ts,DisplayLeftRailFidelity.spec.ts,HomepagePanel.spec.ts,ImportCSV.spec.ts,QuestionFeed.spec.ts— confirmed flaky-under-load, not regressions) and (b)DynamicLogo.visual.spec.ts, which hardcodeslocalhost:3000for a favicon fetch and only fails because of the isolated port choice (confirmed by code inspection — untouched by this PR).CardbackPdfWaitFidelity.spec.tsat 1400px and 390px against a representative binding sample covering every distinct colour token the round introduces (.mdialog/.mfootprimary button,.cbprompt/.applybtn/.defbtnat rest + done state,.progressbox,.gameembed,.geband, ThumbButton's 44px floor) — 0 mismatches at both viewports.closeOnSelectchange caused (GridSelectorModal.spec.ts/GridSelectorModalVariants.spec.ts— 3 test titles renamed to describe the new stays-open behavior, acked in.github/coverage-acks.txt;DisplayPage.spec.ts's own cardback test updated the same way) and 2 existing spec files (DisplayFinishFooter.spec.ts,UnsavedWorkGuard.spec.ts) updated to click through the new reminder gate.Open items
Modal, fully reachable and legible (see 390px screenshots) but not the exact chrome shape shown.Wiki checklist
docs/user-guide.md(the wiki'sUser-Guidesource doc) updated in place with the new reminder-gate/apply-all/set-default/PDF-wait-game copy — wiki page itself needs the same update mirrored (cloud-session checklist item, no direct wiki push from this worktree).🤖 Generated with Claude Code