Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/coverage-acks.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,22 @@ coverage-ack: frontend/tests/PostExportContributionPrompt.spec.ts::Post-export c
coverage-ack: frontend/tests/GridSelectorModal.spec.ts::GridSelectorModal – JumpToVersion > submitting a valid option number selects that card and closes the modal — cardback flow round (SPEC-cardback-pdfwait.md §C.2): the toolbar cardback picker no longer auto-closes on select (the apply-all/set-default prompt renders inline instead), so the title changed to describe the new behaviour; the underlying selection coverage is preserved, not dropped.
coverage-ack: frontend/tests/GridSelectorModal.spec.ts::GridSelectorModal – JumpToVersion > submitting a valid identifier selects that card and closes the modal — same rename as the sibling "option number" test above, same reason.
coverage-ack: frontend/tests/GridSelectorModalVariants.spec.ts::GridSelectorModal - keyboard navigation > Tab reaches a result card and Enter selects it, same as a click would — cardback flow round (SPEC-cardback-pdfwait.md §C.2): same auto-close-removed rename as GridSelectorModal.spec.ts's JumpToVersion tests.

# WTC rebuild (2026-07-24, SPEC-wtc-rebuild.md, PR #446) - /whatsthat's visual/layout tree was
# rebuilt from scratch (container-first hero, Tokyo-11 tokens, owner rulings on BurstSvg/
# session-counter/WD3 phone compaction). Every ack below either (a) retires a test guarding a
# mechanism the rebuild deliberately deletes (sticky/bounded-height pinning, BurstSvg/HoverBurst,
# the gold/navy button treatment, the whatsthat-mark.svg glyph asset, the sliced-word pop
# animation) - not a coverage regression, since the underlying behavior no longer exists to test
# - or (b) covers a describe-block rename where the test's own assertions were kept/adapted, not
# dropped, under a new (still-covered, see the sibling test file) title. Full reasoning + the
# spec-section mapping live in PR #446's own body, not duplicated here.
coverage-ack: frontend/tests/QuestionFeedResponsive.spec.ts::question feed - Level 2 layout reconciliation (real-device regression guard) > * — describe renamed to "Level 2 layout containment" (byte-identical containment/overlap assertions kept, no sticky/burst mechanism left to describe as "reconciliation") - PR #446
coverage-ack: frontend/tests/QuestionFeedResponsive.spec.ts::question feed - mobile layout > * — WD4 retires the 100dvh-bounded hero + its own internal overflow-y:auto questions column entirely (ordinary scrolling document now); the axis-flip/mobile-top-edge invariants are kept, re-pointed at the new container-first DOM under a new "container-first hero layout" describe; the two scroll-pinning tests and the 1400x900 no-internal-scroll test are dropped outright (no bounded height left to assert against) - PR #446
coverage-ack: frontend/tests/QuestionFeedResponsive.spec.ts::question feed - mobile card/questions never overlap (owner live-review fix) > * — guarded a position:sticky overlap bug that can't recur once nothing on this page is position:sticky (WD4); the container-first fold (flex-wrap) structurally prevents the two columns from ever sharing a stacking position instead - PR #446
coverage-ack: frontend/tests/QuestionFeedResponsive.spec.ts::question feed - hover-zoom/hover-burst edge clipping (owner live report) > * — owner ruling 1: BurstSvg/HoverBurst retired outright, nothing left to clip - PR #446
coverage-ack: frontend/tests/QuestionFeedResponsive.spec.ts::question feed - portrait static top block (owner live-review) > * — WD4 retires the "everything above the fold, only the candidate row scrolls" invariant entirely; the page scrolls normally now - replaced by WD3-specific subject-compaction coverage under a new describe, not a same-shaped port - PR #446
coverage-ack: frontend/tests/QuestionFeedResponsive.spec.ts::question feed - question-mark motif + golden action buttons (owner review round 2) > * — WD1: retires the whatsthat-mark.svg gold-gradient glyph asset and the QUIZ_BUTTON_GOLD/_NAVY treatment; replaced by token-based equivalents under a new describe - PR #446
coverage-ack: frontend/tests/QuestionFeedResponsive.spec.ts::question feed - shared blue mystery card composition (owner review round 3) > * — the shared MysteryCard component is retinted onto tokens and its glyph becomes plain text (WD1); replacement coverage lives under the new "mystery-card glyph" describe - PR #446
coverage-ack: frontend/tests/WhatsThatWordsAnimation.spec.ts::What's That Card? - sliced-word pop + hero card pulse (issue #305) > * — retires the sliced WHAT'S/THAT/CARD? pop sequence and the card-pulse-in-sync-with-THAT effect entirely (WD1 kills the gold/navy identity these animations were built around; ANNEX C's animation inventory doesn't list either) - the file is re-purposed for ANNEX C's actual reduced-motion coverage, not a like-for-like port - PR #446
coverage-ack: frontend/tests/WhatsThatWordsAnimation.spec.ts::What's That Card? - narrow-width wordmark swap (owner live-review) > * — retires the WideWordmark/NarrowWordmark viewport-driven CSS-display fork (container-first policy); WhatsThatWords is now one static, single-tree <h1> - PR #446
39 changes: 36 additions & 3 deletions docs/features/printing-tags.md
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,35 @@ printings, artists, tags, and moderation from one screen.

## Frontend architecture

**SUPERSEDED (WTC rebuild, 2026-07-24,
[`docs/proposals/mockups/wtc-rebuild/SPEC-wtc-rebuild.md`](../proposals/mockups/wtc-rebuild/SPEC-wtc-rebuild.md),
owner rulings on that spec's three open questions — see PR #446)** — `/whatsthat`'s
visual/layout tree was rebuilt from scratch onto the
Tokyo-11 theme's ruled token layer (page-private `--wtc-*` tokens derived from `--accent`/
`--body`/`--conf`, defined in `whatsthat.tsx`'s `WtcTokenScope`), replacing the bespoke gold/
navy/starburst-blue/deep-blue-field identity the many "quiz-reveal hero" (issue #305) bullets
below describe. The old dual-layout mechanism (`HeroGrid`'s 768px `grid-template-areas` swap,
`MobileButtonRow`/`MobileCandidateScroller`/`MobileChipRow`'s horizontal scrollers,
`Level2NarrowGrid`'s narrow-only 2x2 action grid, `WideWordmark`/`NarrowWordmark`'s CSS-display
fork) is retired in favour of ONE `@container`-driven hero (`WtcHero`/`Subject`/`QPanel` in
`QuestionFeed.tsx`) that folds continuously via flex-wrap + `clamp()` + `auto-fill`/`auto-fit`
grids — no viewport breakpoint drives sizing (container-first policy, WTC = first consumer).
Also retired: `BurstSvg`/`HoverBurst`/`useStarburstFrame` (the starburst animation, owner
ruling — the token-derived `--wtc-reveal-glow` field glow replaces it; reveal reads through the
mystery-card flip only), `CardPulseWrapper`/the sliced WHAT'S/THAT/CARD? pop sequence
(`WhatsThatWords.tsx` is now a plain, static, single-tree `<h1>`), the `PageColumn`
`100dvh`-bounded hero + "portrait static top block" hack (the page is an ordinary scrolling
document now). Added: the quiet "N tagged this session" affordance (the only reward surface —
no streak/score/confetti) and the seven question-shapes-as-visually-distinct-modes framing
(confirm/shortlist/quick-negative/open-ended/artist/tag/follow-up) `SPEC-wtc-rebuild.md`
section 2 defines. The interaction contract (Level 1/2/3 flows, `getAutoTagChips`, no-re-
presentation, the singleton-NO terminal vote, per-item state reset, the rate-limit banner) is
unchanged — every bullet below describing THAT contract (not the retired visual mechanism) is
still accurate. The detailed "quiz-reveal hero"/starburst/gold-button narrative below is kept
for history (this doc's own established convention — see the `cardPanel.tsx` bullet's own prior
"SUPERSEDED" marker two bullets down) but no longer describes the current rendering; read it as
"how we got here," not "what's live."

- `frontend/src/pages/whatsthat.tsx` (renamed from `printingQueue.tsx`) +
`QuestionFeed.tsx` render the single unified feed; the old standalone
`PrintingTagQueue.tsx`/`GenericVoteQueue.tsx`/`ModerationQueue.tsx` tab
Expand Down Expand Up @@ -1513,9 +1542,13 @@ printings, artists, tags, and moderation from one screen.
`cardpicker/question_feed.py`, `cardpicker/attribute_tags.py` +
`seed_attribute_tags` management command.
- Frontend: `frontend/src/features/printingTags/`
(`PrintingTagPicker.tsx`, `starburstShape.ts`, `cardPanel.tsx`),
`frontend/src/features/questionFeed/WhatsThatWords.tsx` (quiz-reveal
hero's sliced-word teaser, issue #305),
(`PrintingTagPicker.tsx`, `starburstShape.ts` — kept only for its
`STARBURST_OUTER_COLOR` constant, `ChipCard.tsx`'s default/pre-rebuild
frame; `cardPanel.tsx` — WTC-rebuild-retinted, `BurstSvg`/`HoverBurst`/
`useStarburstFrame`/`CardPulseWrapper` deleted),
`frontend/src/features/questionFeed/WhatsThatWords.tsx` (WTC rebuild:
now a plain, static, token-coloured `<h1>` wordmark — no more sliced-
word pop sequence),
`frontend/src/features/filters/ResolvedAttributeFilter.tsx`,
`frontend/src/common/processing.ts::getPrintingMatchLabel`,
`frontend/src/features/attributeVoting/` (`ChipCard.tsx`,
Expand Down
23 changes: 23 additions & 0 deletions docs/proposals/mockups/wtc-rebuild/SPEC-wtc-rebuild.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,29 @@ Binding status (owner standing, 2026-07-23): the CSS token values below are
BINDING. A visual regression against `wtc-mockup.html` is a defect, not a nuance.
Every element on the affected page carries a sizing/coloring/spacing row.

**AMENDMENTS — owner rulings closing the three "Owner questions" at the bottom
of this spec (2026-07-24, relayed via the orchestrator ahead of implementation,
PR #446):**

1. **Owner Q1 (starburst burst)** — RETIRED. `BurstSvg`'s explosion animation is
dropped entirely; the calmer `--wtc-field` + `--wtc-reveal-glow` treatment
(WD5's own default) carries the reveal moment instead. The reveal reads
through the mystery-card flip only — no separate burst animation.
2. **Owner Q2 (reward surface)** — KEPT, quiet. The "N tagged this session"
count stays (WD6's own default) — volume-rewarding, direction-neutral (see
ANNEX A's soundness note); no streak/score/confetti added on top of it.
3. **Owner Q3 (subject prominence on phone)** — ACCEPTED as specified (WD3).
The subject compacts to ~132px horizontal below the hero's own 560px
`@container` fold point so the answer stays reachable near the top on a
phone; the open-ended shape (d) is the one shape that visually expands
(dashed "tricky one" framing) rather than compacting further, since it
needs more room for its own hint copy.

These three rulings resolve every open item this spec's "OWNER QUESTIONS"
section (bottom of this file) raised; nothing in this spec is still pending an
owner call as of this amendment. See PR #446's own body for the
section-by-section implementation mapping.

D-number scope note: D-numbers are per-proposal in this repo (proposal-h owns
its own D1–D19; the old WTC round used W4–W7). The decisions below are the
**WTC-rebuild round's** ledger, numbered WD1.. to avoid collision with either.
Expand Down
41 changes: 35 additions & 6 deletions frontend/src/features/attributeVoting/ChipCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
* picker a user just interacted with, rather than introducing a second unrelated chip style.
* Deliberately lighter than CandidateButton: no starburst/hover-zoom, since these chips are
* small and numerous rather than one large focal candidate.
*
* WTC rebuild (2026-07-24, SPEC-wtc-rebuild.md section 4/1c "reason chip") - the ONE caller
* this component has today, NoMatchReasonStrip, sits inside the rebuilt /whatsthat's
* quick-negative (shape c) surface, which the spec's binding per-element table frames in
* `--danger` (a visibly different mode from a confirm/pick, per WD7) rather than this
* component's own default accent/blue frame. `variant` is additive and optional (default
* unchanged) specifically so this doesn't touch ReportCardPanel.tsx's own, unrelated use of
* the same component - only NoMatchReasonStrip opts into "danger".
*/

import styled from "@emotion/styled";
Expand All @@ -14,8 +22,12 @@ import Button from "react-bootstrap/Button";

import { STARBURST_OUTER_COLOR } from "@/features/printingTags/starburstShape";

const StyledChipButton = styled(Button)`
border: 2px solid ${STARBURST_OUTER_COLOR};
const StyledChipButton = styled(Button)<{ $variant: "accent" | "danger" }>`
border: 2px solid
${(props) =>
props.$variant === "danger"
? "var(--bs-danger, #f7768e)"
: STARBURST_OUTER_COLOR};
border-radius: 0.5rem;
background-color: transparent;
color: inherit;
Expand All @@ -25,19 +37,31 @@ const StyledChipButton = styled(Button)`

&:hover,
&:focus {
background-color: rgba(77, 141, 223, 0.15);
border-color: ${STARBURST_OUTER_COLOR};
background-color: ${(props) =>
props.$variant === "danger"
? "color-mix(in srgb, var(--bs-danger, #f7768e) 15%, transparent)"
: "rgba(77, 141, 223, 0.15)"};
border-color: ${(props) =>
props.$variant === "danger"
? "var(--bs-danger, #f7768e)"
: STARBURST_OUTER_COLOR};
color: inherit;
}

&.highlighted {
background-color: ${STARBURST_OUTER_COLOR};
background-color: ${(props) =>
props.$variant === "danger"
? "var(--bs-danger, #f7768e)"
: STARBURST_OUTER_COLOR};
color: #000000;
}

&.highlighted:hover,
&.highlighted:focus {
background-color: ${STARBURST_OUTER_COLOR};
background-color: ${(props) =>
props.$variant === "danger"
? "var(--bs-danger, #f7768e)"
: STARBURST_OUTER_COLOR};
}

&:disabled {
Expand All @@ -52,6 +76,9 @@ interface ChipCardProps {
disabled?: boolean;
onClick: () => void;
"data-testid"?: string;
/** Additive, optional (own comment above) - "danger" is the WTC quick-negative frame;
* omitted (every other caller) keeps this component's original accent/blue frame. */
variant?: "accent" | "danger";
}

export function ChipCard({
Expand All @@ -61,10 +88,12 @@ export function ChipCard({
disabled = false,
onClick,
"data-testid": dataTestId,
variant = "accent",
}: ChipCardProps) {
return (
<StyledChipButton
variant="outline-secondary"
$variant={variant}
className={highlighted ? "highlighted" : ""}
disabled={disabled}
onClick={onClick}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ export function NoMatchReasonStrip({
disabled={submittingTagName != null}
onClick={() => choose(tagName)}
data-testid={`no-match-reason-${tagName}`}
variant="danger"
/>
</Col>
))}
Expand Down
Loading
Loading