2.7 KiB
2.7 KiB
Task 01 — Sticky Bottom Composer
Phase: 52_pinned_composer · Source: TODO.md:3 — "The message input text box needs to be pinned to the bottom of the screen so it doesn't "run away" from the user as they try to click "stop""
Story: n/a (TODO-derived)
Objective
The composer stays pinned to the bottom of the viewport at every scroll position — a CSS-only change inside the existing chat column.
Work
frontend/assets/styles.css— in the/* ---------- Composer ---------- */block (.composer, ~L1133): addposition: sticky;andbottom: env(safe-area-inset-bottom);to.composer. The page scrolls at the document level and.chat-shellis the composer's containing column, so the box sticks to the viewport's bottom edge (offset by the mobile safe-area inset) while.messagesscrolls behind it; at the document bottom it settles back into its normal flow position above the footer. Keep the existing solidbackground: var(--surface), border, radius andbox-shadow: var(--shadow)— messages must never show through the pinned box.frontend/index.html— verify NO change needed: the composer is already the LAST child of.chat-shell(the sticky context), and the#message-input/#send-btn/#send-statusmarkup is untouched.- Do NOT touch
frontend/assets/app.js— the pin must not add any scroll call site (phase-42 invariant; the one page scroll in the file staysscrollReveal). tests/unit/test_pinned_composer.py(new, house pin style — seetests/unit/test_frontend_scroll.py): assertstyles.cssdeclaresposition: stickyAND abottom:offset on.composer(the sticky-bottom pair, matched inside the.composerrule); assertapp.jsis unchanged in its scroll surface (the phase-42 single-scrollRevealpin still holds — reuse the same assertion approachtest_no_reply_autoscroll.py's companion pins use).
- ASSUMPTION:
bottom: env(safe-area-inset-bottom)(notbottom: 0+ extra padding) — the standard notch-aware inset; on desktopenv()resolves to 0, so the box sits flush with the viewport bottom. - ASSUMPTION: no
z-indexadded — DOM order already stacks the composer above.messages; the sticky header (z 20) and doc modal (z 1000) are unaffected.
Testing & Quality
- Unit:
tests/unit/test_pinned_composer.py(the pins above) —uv run pytest tests/unit/test_pinned_composer.py -vgreen. - Coverage: >90% — no
app/change; the gate stays green.
Completion Criteria
.composerinstyles.csscarriesposition: sticky+ thebottomsafe-area offset; thefrontend/diff contains no JS change.uv run pytestgreen;uv run ruff check . && uv run pyrightclean.