From f24f9412f1fa2f689a7ff503c1f103e90eb17cbd Mon Sep 17 00:00:00 2001 From: Kev Date: Thu, 16 Jul 2026 21:27:47 -0400 Subject: [PATCH] Rev 3 matchup chips: TeamChip primitive + board-row team context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Design Rev 3 anchors every matchup/context abbr with a 10-12px team tile. New reusable TeamChip renders the real TeamLogo (licensed ESPN logo where it resolves, team-colored monogram otherwise — the resolver is already built) at that size + the abbr, sitting inside the row so it inherits the ranked opacity ramp. First placement: StatStrip's player/team context (name → team-chip → archetype). ROW-GRAMMAR identity-run test updated to the chip marker. Remaining Rev 3 placements to thread TeamChip into (reusable, mechanical): parlay legs, grade-shift header, pitcher "vs", /u recent-settled, other matchup context lines. Game-card headers already carry TeamLogo (TeamLink). Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/unit/rowGrammar.test.js | 2 +- web/src/components/vyndr/StatStrip.tsx | 4 ++- web/src/components/vyndr/TeamChip.tsx | 37 ++++++++++++++++++++++++++ web/src/components/vyndr/index.ts | 1 + 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 web/src/components/vyndr/TeamChip.tsx diff --git a/tests/unit/rowGrammar.test.js b/tests/unit/rowGrammar.test.js index c7d56c9..071daf8 100644 --- a/tests/unit/rowGrammar.test.js +++ b/tests/unit/rowGrammar.test.js @@ -55,7 +55,7 @@ describe('ROW-GRAMMAR §2 — canonical prop-row slot order (snapshot mode)', () expect(base).toBeGreaterThan(-1); assertOrder(strip, [ '', + '', ], base); diff --git a/web/src/components/vyndr/StatStrip.tsx b/web/src/components/vyndr/StatStrip.tsx index 483edc9..6bbbd9d 100644 --- a/web/src/components/vyndr/StatStrip.tsx +++ b/web/src/components/vyndr/StatStrip.tsx @@ -7,6 +7,7 @@ import { nextRunLabelET } from '@/lib/pipelineSchedule'; // affiliate config flips a book on). rel MUST stay BOOK_LINK_REL. import { buildBookLink, BOOK_LINK_REL } from '@/lib/bookLinks'; import { bookInfo } from '@/lib/books'; +import TeamChip from '@/components/vyndr/TeamChip'; export interface StatCell { label: string; @@ -389,7 +390,8 @@ export default function StatStrip({ (never the gray silhouette). Team drives the accent color. */} {player} - {team} + {/* Rev 3 — team context anchored by a real team chip (logo / monogram). */} + {archetype && } {archetype?.secondary && ( <> diff --git a/web/src/components/vyndr/TeamChip.tsx b/web/src/components/vyndr/TeamChip.tsx new file mode 100644 index 0000000..b596ac7 --- /dev/null +++ b/web/src/components/vyndr/TeamChip.tsx @@ -0,0 +1,37 @@ +import type { CSSProperties } from 'react'; +import TeamLogo from '@/components/vyndr/TeamLogo'; + +/** + * TeamChip (Design Rev 3) — a small team tile anchoring an abbr on a matchup / + * context line. Design drew a 10-12px team-gradient chip before each abbr; + * per the handoff we swap in the real TeamLogo img at the same size (the + * resolver already renders the licensed ESPN logo where it resolves, and a + * team-colored monogram otherwise — never a gray box). + * + * Renders `[tile] ABBR`. Inherits the row's opacity ramp because it sits inside + * the row (no own opacity). Mono abbr, matching the matchup line. + */ +export default function TeamChip({ + team, + sport, + size = 12, + showAbbr = true, + style = {}, +}: { + team?: string | null; + sport?: string; + size?: number; + showAbbr?: boolean; + style?: CSSProperties; +}) { + if (!team) return null; + return ( + + + {showAbbr && String(team).toUpperCase()} + + ); +} diff --git a/web/src/components/vyndr/index.ts b/web/src/components/vyndr/index.ts index 9d1a35b..eff54e7 100644 --- a/web/src/components/vyndr/index.ts +++ b/web/src/components/vyndr/index.ts @@ -41,6 +41,7 @@ export { default as BookChip } from './BookChip'; /* DS0 (Design v2) — the Entity Layer: teams/players/books as themselves. */ export { default as TeamLogo } from './TeamLogo'; +export { default as TeamChip } from './TeamChip'; export { default as PlayerAvatar } from './PlayerAvatar'; export { default as BookWordmark } from './BookWordmark';