From 4e28650329290c0f15673a566389e47812c18c83 Mon Sep 17 00:00:00 2001 From: Jack Yao <105488074+StarsExpress@users.noreply.github.com> Date: Wed, 28 Oct 2026 21:00:29 -0400 Subject: [PATCH] Removed roster cap off Linemates card. Co-Authored-By: Claude --- frontend/card-export.js | 21 +- frontend/cards-base.js | 5 +- frontend/config.js | 13 +- frontend/index.html | 5 +- frontend/linemate-card.js | 137 +++-- frontend/style.css | 800 ++++++++++++++++++++------- playbook/DECISIONS.md | 1 + playbook/architecture/CARDS.md | 25 +- playbook/tests/TEST_LINEMATE_CARD.md | 5 +- tests/test_linemate_card.py | 118 +++- 10 files changed, 815 insertions(+), 315 deletions(-) diff --git a/frontend/card-export.js b/frontend/card-export.js index d644a3f..f60a31d 100644 --- a/frontend/card-export.js +++ b/frontend/card-export.js @@ -32,10 +32,8 @@ const CARD_EXPORT_BG = "#16301f"; // extra right-edge background is harmless, clipping the content isn't. const CARD_HORIZONTAL_PADDING = 40; -// Every card's own close/fold/resize chrome, this Save button itself, and -// Linemate Card's "See more" toggle (meaningless once buildExportClone below -// force-expands the roster to its full length — see linemate-card.js's -// prepareClone) shouldn't appear in the exported image. html2canvas's +// Every card's own close/fold/resize chrome and this Save button itself +// shouldn't appear in the exported image. html2canvas's // ignoreElements is the standard way to exclude specific nodes from a // capture without a hide-then-restore choreography. function shouldIgnoreForExport(el) { @@ -48,7 +46,7 @@ function shouldIgnoreForExport(el) { el.classList.contains("merge-mode-switch") || el.classList.contains("merge-card-scroll-hint") || el.classList.contains("linemate-card-scroll-hint") || - el.classList.contains("linemate-see-more")) + el.classList.contains("linemate-card-size-reminder")) ); } @@ -76,16 +74,19 @@ function fitCloneToContent(clone) { // sidesteps that entirely — with nothing scrolling underneath them in the // export, sticky was only ever pinning them to their own already-correct // flow position anyway. - clone.querySelectorAll(".merge-table-frozen, .linemate-table-frozen, .merge-read-frozen").forEach((cell) => { - cell.style.position = "static"; - cell.style.left = ""; - }); + clone + .querySelectorAll(".merge-table-frozen, .linemate-table-frozen, .merge-read-frozen, .linemate-read-label") + .forEach((cell) => { + cell.style.position = "static"; + cell.style.left = ""; + }); // Lays every column flat in one row instead of clipping to whatever was // scrolled into view, then widens the card itself to fit. let requiredWidth = 0; clone.querySelectorAll(".merge-table-wrap, .linemate-table-wrap, .linemate-summary-wrap").forEach((scrollEl) => { scrollEl.style.overflow = "visible"; + scrollEl.style.maxHeight = "none"; requiredWidth = Math.max(requiredWidth, scrollEl.scrollWidth); }); if (requiredWidth > 0) { @@ -120,7 +121,7 @@ function buildExportClone(cardEl) { // layout — a detached node always reports 0. document.body.appendChild(clone); - clone.classList.remove("is-folded", "is-dragging", "is-resizing"); + clone.classList.remove("is-folded", "is-dragging", "is-resizing", "is-wide"); const panelEl = clone.querySelector(".scout-card-panel"); // The panel's own 2px rounded border is dropped here: compositeFooterCanvas draws one diff --git a/frontend/cards-base.js b/frontend/cards-base.js index 1d77a6b..88a614b 100644 --- a/frontend/cards-base.js +++ b/frontend/cards-base.js @@ -133,8 +133,9 @@ export function cascadeScoutCardPosition(cardEl) { // hides the metric body via CSS (.is-folded); a card the user has edge- // resized taller would otherwise leave a tall dead gap under the header once // that body disappears, so its inline panel height is stashed here and -// restored on unfold rather than lost. `onUnfold` lets a Linemate Card reset -// its "See more" state back to collapsed every time it re-expands (§2.5). +// restored on unfold rather than lost. `onUnfold`, when given, lets a card +// refresh something that has no layout while folded (the Comparison Card's +// sticky-column offsets) every time it re-expands. export function applyCardFoldVisual(cardEl, state, onUnfold) { cardEl.classList.toggle("is-folded", state.folded); const foldBtn = cardEl.querySelector(".scout-fold"); diff --git a/frontend/config.js b/frontend/config.js index 0590087..b9e71e6 100644 --- a/frontend/config.js +++ b/frontend/config.js @@ -46,13 +46,14 @@ export const LABEL_ALPHA = 1; export const MERGE_CARD_MAX_MEMBERS = 5; export const MERGE_QUOTA = 8; -// Position-group pulled into a Linemate Card's roster and the per-category -// cap on how many can be shown — both keyed by category, not position, -// since a Linemate Card spans every position within its anchor's category -//. +// Position-group pulled into a Linemate Card's roster, keyed by category, +// not position, since a Linemate Card spans every position within its +// anchor's category. The roster itself has no size limit — the threshold is +// the only gate — so LINEMATE_SIZE_REMINDER_AT is only where the card starts +// telling the user that a higher threshold keeps it compact (more linemates +// than that, per category: the point where the old roster cap used to cut). export const LINEMATE_POSITIONS = { pass_block: ["T", "G", "C"], pass_rush: ["ED", "DI"] }; -export const LINEMATE_CAP = { pass_block: 5, pass_rush: 7 }; -export const LINEMATE_VISIBLE_DEFAULT = 5; +export const LINEMATE_SIZE_REMINDER_AT = { pass_block: 5, pass_rush: 7 }; // Mirrors config.py's DISPLAY_DECIMALS — keep in sync. UI-display rounding // only: plots (render.js's xVals/yVals, drawn straight from record[key]) diff --git a/frontend/index.html b/frontend/index.html index 219eaae..e5e8bdc 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -577,6 +577,7 @@

Player Comparisons