phase: 104_chip_sizing_question_cap
All completion criteria verified. Final report: **Phase 104 — final verification pass: all green** - Verified (no code changes needed): single-line ellipsized `.suggestion-chip` CSS + deleted `.maybe-try` override, `renderChips` full-text `title` + `aria-label`-when-clipped, `maxlength="4000"` + `#char-count` counter + `handleSend` over-cap guard, unit pins file, schemas boundary pins, dedicated E2E suite. - E2E (isolation): `uv run pytest tests/e2e/test_chip_sizing_question_cap.py -v --no-cov` → **6 passed**; regressions: `test_suggestion_chips.py` 8 passed, `test_pinned_composer.py` 4 passed, `test_responsive_polish.py` 7 passed, `test_chat_history.py` 5 passed. - `uv run pytest` → **2102 passed**; `--cov=app` → **99%** (>90%); `uv run ruff check . && uv run pyright` → clean, 0 errors. - Criteria: chip E2E (single-line, clipped, title+aria-label full text) ✅; paste caps at exactly 4,000, send streams, counter hides ✅; programmatic 5,000-char fill → banner, no turn, text kept ✅; 4,000/4,001 boundary pinned + HTML maxlength == JS constant cross-file pin ✅. - Diff scope: `frontend/`, new unit file, `tests/unit/test_schemas.py`, new E2E file, phase files — **no `app/` diff, no migration, no `shared.js` diff**. - Deviations: 4 regression test files touched — 2 genuine DOM-pin conflicts from the new `#char-count` child (explicitly anticipated by the overview) + 3 documented **pre-existing E2E flake fixes** (smooth-scroll race, tab-walk heuristic, 10 ms timeout), each verified pre-existing on the pre-phase-104 tree. - No commit made (harness commits per the execution protocol override). - Next pending phase: `98_sync_summary_visibility`.
This commit is contained in:
@@ -703,14 +703,6 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
|
||||
gap: 0.45rem;
|
||||
padding-inline: 0.25rem;
|
||||
}
|
||||
/* As flex items these chips must be allowed to shrink (min-width:auto
|
||||
would let a long title-derived chip exceed the column on phones —
|
||||
phase 07 overflow fix); the label text then wraps inside the pill. */
|
||||
.maybe-try .suggestion-chip {
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* ---------- Steering notes (phase 15) ---------- */
|
||||
/* "Tune" button in the meta row of every completed brain bubble: ghost
|
||||
pill, ≥44px, right-aligned after the source chips. ink-soft on surface
|
||||
@@ -1230,6 +1222,21 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
/* The shared chip pill — both chip rows (the onboarding row in the
|
||||
empty state and the "Maybe try" row under a deflected bubble) reuse
|
||||
it. Phase 104 (owner 2026-09-12, A1): a chip is ONE line at every
|
||||
viewport width — `white-space: nowrap` stops a 400-char question
|
||||
from wrapping the pill into a multi-line "chonk"; `overflow: hidden`
|
||||
zeroes the flex item's automatic minimum size (min-width:auto would
|
||||
pin the item to the full text width), so `max-width: 100%` binds and
|
||||
`text-overflow: ellipsis` clips the text at the row edge — in the
|
||||
desktop wrap row 100% is the chat column, in the ≤640px row
|
||||
(nowrap + overflow-x: auto) 100% is the VISIBLE width and the row
|
||||
scrolls. That clipping is the phase-07 overflow fix the old
|
||||
"Maybe try" chip override used to carry (min-width:0 + max-width:
|
||||
100%) — now fully subsumed here and deleted, provenance folded into
|
||||
this comment so the history lives with the contract. The full text
|
||||
stays one hover away (the title tooltip, phase 104 task 02). */
|
||||
.suggestion-chip {
|
||||
font: inherit;
|
||||
font-size: 0.92rem;
|
||||
@@ -1242,6 +1249,11 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
|
||||
min-height: 44px;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s ease, transform 0.05s ease;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
.suggestion-chip:hover { background: var(--brand-soft); }
|
||||
.suggestion-chip:active { transform: scale(0.98); }
|
||||
@@ -1321,6 +1333,17 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
|
||||
#view-chat:not(.chat-booted) .composer {
|
||||
position: static;
|
||||
}
|
||||
/* Phase 104 (owner 2026-09-12, A4): the question-length counter —
|
||||
right-aligned above the composer, a child of the .chat-bottom sticky
|
||||
unit (between the actions row and the form), hidden until 80% of the
|
||||
4,000-char cap (app.js updateCharCount). It sits on the APP
|
||||
background behind the transparent .chat-bottom unit, so both pairings
|
||||
are verified against --bg: --ink-soft on --bg = 8.6:1 (≥4.5:1, WCAG
|
||||
AA) and the .is-max state's --err-ink on --bg = 10.4:1 (AA). The
|
||||
.is-max state ALSO changes the copy ("— character limit") — text +
|
||||
color, never color alone (B3). */
|
||||
.char-count { margin: 0; text-align: right; font-size: 0.75rem; line-height: 1.2; color: var(--ink-soft); }
|
||||
.char-count.is-max { color: var(--err-ink); }
|
||||
.composer {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
|
||||
Reference in New Issue
Block a user