Repository navigation
[3271 by Claude Opus 5.5] Mobile task-card metadata overflows at 320px despite no document overflow - #3275
Conversation
…d can't fit everything, it now wraps onto a second line instead of making the list scroll sideways. Nothing is hidden or clipped, and tap targets are the same size. The fix (`propr-ui/src/components/TaskList/MobileTaskCard.tsx`): - Wrapping: the first line (entity chip, attachment badge, repository, status, age) can now wrap. When it doesn't fit, the age drops beneath and stays at the right edge. If there still isn't room, the status drops down too. - Repository: the name still never shows fewer than 10 characters. It only grows as wide as the name itself, so on wider screens the status still sits right after it as before. When the line wraps, the repository uses the space the age and status left. - Line height: chips are 22px tall but sit in a 20px slot, so a first line that fits stays 20px as it always was. - Unchanged: the title, the third line and what happens when you tap a card. New browser test (`propr-ui/e2e/task-list-mobile-card-geometry.pw.ts`): it uses mocked task data built from the measurements in the issue, not the real production UI or a real account. The cards include: - PR #46 with 12 attachments and three runs, and PR #49 (Cancelled) with two runs - two tasks with no issue, which show a task-id chip (I took these to be the "report-task chips"); one has an attachment - a 32-character repository name - Completed and Cancelled statuses, and ages of "12 mins ago", "14 mins ago" and "58 mins ago" At 320, 360 and 390px the test checks that: - neither the card list nor the ledger is wider than its visible area (`scrollWidth` ≤ `clientWidth`), and no card is either - the entity chip, attachment badge, status, age and run track are all inside the card and not cut off by a clipping parent - at least the repository's first 10 characters are visible - tapping a card still opens its task A separate 768px case checks that the wider layout hasn't changed: one 20px first line, status 8px after the repository, age at the right edge. Test results: - Old layout: the new tests fail at 320, 360 and 390px; the list was 400px wide in each case. - New layout: they pass. - Other suites: all 49 tests in the other task-list browser suites (desktop, split pane, assignees, mobile cards and others) pass, as do the 116 TaskList unit tests. - Lint and typecheck: both are clean, after I fixed four type errors in the new spec. The 320px screenshot also shows the "All Repos" filter button in the page header cut off at the right edge. That's outside this issue, so I didn't touch it.
|
/review gpt-6-astra |
|
✅ AI Code Review Complete requested by @integry Posted 1 review: |
🔍 AI Code Review — gpt-6-astraOverall EvaluationThe PR makes task-card headings wrap when metadata cannot fit, while preserving the compact layout when space permits. Static review found no introduced merge blocker. It is ready to merge within scope, conditional on the pending checks completing successfully. ✅ Localized layout change — Wrapping is confined to the heading; title rendering, lower metadata, and task-selection handling remain unchanged. ✅ Targeted regression coverage — The new tests cover three phone widths, attachment counts, long repository names, card navigation, and the single-line layout at 768px. This review used the supplied diff and context only; no commands or tests were run. The authoritative check summary reports six pending checks and no failures. Merge blockersNo merge blockers. SuggestionsThese are optional follow-ups and are not sent to S1: 🟢 Measure visible repository charactersIn S2: 🟢 Inspect rendered chip boundsThe geometry helper measures entity and status wrappers, whose new fixed height is 20px, while their rendered chips can extend beyond those wrappers. Measuring the inner chips would strengthen future clipping detection. This is optional test hardening: the supplied layout permits that overflow and leaves spacing between wrapped rows, so no actual clipping regression is demonstrated. ScoreThe change is focused and supported by useful geometry and interaction tests, with no verified introduced defect. Pending checks leave final automated validation outstanding. Score: 9/10 🤖 Review Details
Copy and edit to choose records from this review: 🤖 Review by ProPR |
…indow, the changed file can now be scrolled into view with a finger or the mouse wheel, tapped, its diff opened and closed. I tested this in headless Chromium against stubbed task data. It has not been run against real API data or on a real phone. Cause. From 640px wide up, the task page uses the desktop layout. It pins the task header and gives only the area below it its own scroll. In a short window that area was too thin: about 100px in my reproduction, 58px in your measurement. The pinned Timeline and Files headings and the log bar covered nearly all of it, so the file row could never be tapped. Fix. - New `useShortWorkspace.ts`: it measures how much height the header leaves for the timeline/files area. It counts the collapsed log bar and the pinned headings, and allows about 184px for rows. It also respects the visible area when an on-screen keyboard shrinks it, but ignores pinch zoom. The measurement doesn't depend on which layout is active, so it can't flip back and forth. - In `TaskDetails/index.tsx`, when there isn't enough room: - the whole task scrolls as one page, the way phones already do. - the header scrolls away with it, but all its metadata and actions are still there when you scroll back up. - the Timeline and Files headings still pin, now to the top of the page. - the execution-log bar stays pinned at the bottom, and opening it keeps its normal height. - extra scroll padding keeps a focused or revealed row clear of the pinned headings and the log bar. - Unchanged: tall desktop windows, portrait phones, how the timeline heading sits above its content, and returning focus to the file row when the diff closes. The diff dialog's existing scroll lock still holds the page in place. Tests. The new `e2e/task-details-short-viewport.pw.ts` covers 844×390 touch landscape, 880×480 desktop, 320×640 and 390×844 portrait, and 1280×820 desktop. Each uses a completed PR task with a long two-line title and subtitle, 8 runs and one modified 121-line Markdown file. It: - scrolls only with real touch swipes or wheel input. - checks that a tap at the row's centre actually reaches the row and that the visible area is usable. - opens and closes the diff, then checks focus and scroll position are restored. - opens and closes the execution log. - scrolls back up and opens the header's "More task actions" menu. On the old code the two short cases fail the way the issue describes: at 844×390 the row can't be scrolled to a tappable spot, and at 880×480 only 51px of the area is visible. One existing test changed behaviour. In `task-timeline-heading-layering.pw.ts`, the case that docks the task beside the list at 1280×820 with 150% text now uses the new page-scroll layout. There, the enlarged header is 423px tall and leaves only about 97px for rows, the same problem as the issue. The test now scrolls the whole page and still checks that nothing paints over the Timeline heading. Results. All 270 tests in the `task-*` browser suites pass, as do 424 TaskDetails unit tests, eslint with zero warnings and tsc. The new spec passed 3 times in a row. I didn't touch any files from #3273, #3274 or #3275, and added no dependencies. The 844×390 and 880×480 previews show the revealed file row and the opened diff. Separately, Gmail, Google Calendar and Google Drive need authorizing in your claude.ai connector settings before they can be used. This task didn't need them.
…d files covered and untappable (#3277) * I fixed #3276. At 844×390 touch landscape and in an 880×480 desktop window, the changed file can now be scrolled into view with a finger or the mouse wheel, tapped, its diff opened and closed. I tested this in headless Chromium against stubbed task data. It has not been run against real API data or on a real phone. Cause. From 640px wide up, the task page uses the desktop layout. It pins the task header and gives only the area below it its own scroll. In a short window that area was too thin: about 100px in my reproduction, 58px in your measurement. The pinned Timeline and Files headings and the log bar covered nearly all of it, so the file row could never be tapped. Fix. - New `useShortWorkspace.ts`: it measures how much height the header leaves for the timeline/files area. It counts the collapsed log bar and the pinned headings, and allows about 184px for rows. It also respects the visible area when an on-screen keyboard shrinks it, but ignores pinch zoom. The measurement doesn't depend on which layout is active, so it can't flip back and forth. - In `TaskDetails/index.tsx`, when there isn't enough room: - the whole task scrolls as one page, the way phones already do. - the header scrolls away with it, but all its metadata and actions are still there when you scroll back up. - the Timeline and Files headings still pin, now to the top of the page. - the execution-log bar stays pinned at the bottom, and opening it keeps its normal height. - extra scroll padding keeps a focused or revealed row clear of the pinned headings and the log bar. - Unchanged: tall desktop windows, portrait phones, how the timeline heading sits above its content, and returning focus to the file row when the diff closes. The diff dialog's existing scroll lock still holds the page in place. Tests. The new `e2e/task-details-short-viewport.pw.ts` covers 844×390 touch landscape, 880×480 desktop, 320×640 and 390×844 portrait, and 1280×820 desktop. Each uses a completed PR task with a long two-line title and subtitle, 8 runs and one modified 121-line Markdown file. It: - scrolls only with real touch swipes or wheel input. - checks that a tap at the row's centre actually reaches the row and that the visible area is usable. - opens and closes the diff, then checks focus and scroll position are restored. - opens and closes the execution log. - scrolls back up and opens the header's "More task actions" menu. On the old code the two short cases fail the way the issue describes: at 844×390 the row can't be scrolled to a tappable spot, and at 880×480 only 51px of the area is visible. One existing test changed behaviour. In `task-timeline-heading-layering.pw.ts`, the case that docks the task beside the list at 1280×820 with 150% text now uses the new page-scroll layout. There, the enlarged header is 423px tall and leaves only about 97px for rows, the same problem as the issue. The test now scrolls the whole page and still checks that nothing paints over the Timeline heading. Results. All 270 tests in the `task-*` browser suites pass, as do 424 TaskDetails unit tests, eslint with zero warnings and tsc. The new spec passed 3 times in a row. I didn't touch any files from #3273, #3274 or #3275, and added no dependencies. The 844×390 and 880×480 previews show the revealed file row and the opened diff. Separately, Gmail, Google Calendar and Google Drive need authorizing in your claude.ai connector settings before they can be used. This task didn't need them. * feat(ai): Your exact-head failures didn't reproduce in this container, but while ruling out a product cause I found and fixed a real restoration defect in the short layout. That defect plausibly explains the 6px landscape failure. The 1280×820 failure is still unconfirmed: my best explanation is that the wheel scroll hadn't finished when the baseline was measured, and the new wait now covers that. Your exact-head failures didn't reproduce in this container, but while ruling out a product cause I found and fixed a real restoration defect in the short layout. That defect plausibly explains the 6px landscape failure. The 1280×820 failure is still unconfirmed: my best explanation is that the wheel scroll hadn't finished when the baseline was measured, and the new wait now covers that. **Product defect.** In the short layout, the bottom scroll padding was `scroll-pb-12` (48px), but the pinned log bar is 37px (36px plus a 1px top border). When a file row sat fully visible within about 12px above the bar, putting focus back on it as the diff closed counted it as covered and scrolled the page. A diagnostic run placed the row at fixed distances from each edge, then opened and closed the diff: | Row's gap above log bar | 0px | 2px | 5px | 10px | 20px+ | |---|---|---|---|---|---| | Scroll movement, 844×390 and 880×480 | 11px | 9px | 6px | 1px | 0 | The top edge and every position at 1280×820 moved 0px. I set the padding in `useShortWorkspace.ts` to exactly the bar's height (`scroll-pb-[calc(2.25rem+1px)]`). After that change, every position moved 0px in all three sizes. The 1280×820 layout has no such padding, so its 4px isn't explained by this defect. **Test changes** (`e2e/task-details-short-viewport.pw.ts`): - **Waiting for the scroll to end:** the old check was three animation frames without movement. It now waits for the scroll's `scrollend` event and then 300ms with nothing moving. If `scrollend` never fires, it falls back to 5s. - **Baseline position:** it is now measured where the row rests just before it is tapped: after the swipe's momentum, after the preview capture, with a fresh tap point. - **New check in the 880×480 case:** the mouse wheel moves the row to 1–6px above the log bar, then the diff is opened and closed. With the old padding this fails with an 8px difference; with the fix it passes. - **Timing:** I removed a duplicate wait inside the scroll-into-view step and gave these five cases a 60s timeout. Each case does many swipes and each now waits for its momentum to end, so landscape takes about 14s on an idle host and 30–32s under full CPU load, which is over the default 30s. - The 1px limit, the focus and tap-target checks, and real touch/wheel input are unchanged. There are no forced clicks, and the test never sets the scroll position itself. **Results:** - **Repeat runs:** the five viewport cases plus the nine timeline-heading cases passed three times with preview capture and three times without, 84/84. - **Under full CPU load:** the five viewport cases passed once with capture and once without. - **Unit tests, lint and type check:** all 424 TaskDetails unit tests pass, and eslint (zero warnings) and tsc are clean. - **One failure along the way:** before the 60s timeout, an overloaded run timed out in the landscape case and in the unchanged timeline-heading enlarged-text case. **Limits:** - **Old wait never failed here.** It never returned before the scroll ended in this container: not with the CPU slowed, not under load, not with smooth-scrolling Chromium. The 1280×820 explanation therefore comes from your 24-frame result, not from a failure I reproduced. - **Edge diagnostic was not real input.** It set the scroll position directly, and it is not committed. - **Remaining gates:** a real phone, real API data, and signed-native integration are still your release gates. There are no visual previews because the change isn't visible in a still image. Separately, Gmail, Google Calendar and Google Drive need authorizing in your claude.ai connector settings before they can be used; this task didn't need them. PR: #3277 Comment by: @integry (ID: 6279336708) Model: Claude Opus 5.5 * feat(ai): I fixed the Validate Changes failure. The cause was a race in this PR, not the logs dialog: the listener-leak check in `e2e/dialog-keyboard-viewport.pw.ts` measured its baseline before the task page had finished loading. I fixed the Validate Changes failure. The cause was a race in this PR, not the logs dialog: the listener-leak check in `e2e/dialog-keyboard-viewport.pw.ts` measured its baseline before the task page had finished loading. **What went wrong.** The new `useShortWorkspace` hook adds a resize listener on the browser's visual viewport once the task header mounts. The test records the starting (`idle`) listener count right after `page.goto`, before the task data has loaded. So that count is 0, and after the dialog closes the count is 1, the hook's listener for the page itself. The dialogs weren't leaking anything. Locally, this failed every time in the Follow Up test and in both Logs tests (fonts loaded and blocked), not only the one CI reported. **Fix (tests only, no product code changed):** - `e2e/task-logs.fixture.ts`: a new `taskShown(page)` helper waits until the task page has rendered. It reuses the "more actions" button lookup that `openTaskAction` already uses. - `e2e/dialog-keyboard-viewport.pw.ts`: the Follow Up and Logs tests now call `taskShown(page)` before measuring `idle`. The baseline therefore includes the task page's own listeners. The check still fails if a dialog leaves a listener behind. **Verification:** - `dialog-keyboard-viewport`, `task-logs-*` and `task-details-short-viewport` pass, each run twice with retries off (46 passed, 0 failed). Before the fix, `dialog-keyboard-viewport` failed 9 of 15 runs. - ESLint (`--max-warnings 0`) and `tsc --noEmit` pass on the changed files. This change isn't visible in the UI, so there are no previews. PR: #3277 Comment by: @propr-dev[bot] (ID: 6280778125) Comment by: @github-actions[bot] (ID: 6280778384) Model: Claude Opus 5.5 --------- Co-authored-by: propr-dev[bot] <1316198+propr-dev[bot]@users.noreply.github.com>
AI Implementation Summary
Addresses #3271
Branch:
3271/claude-opus-5-5-mobile-task-card-metadata-20261019-2153-p51Commits: ✅ Changes committed (5b08ba1)
AI Processing Incomplete
Execution Details:
Warning
This implementation may be incomplete. The agent stopped producing output and the stall watchdog ended the run before it could confirm that all requested work was complete. Partial changes were preserved instead of discarded.
Work completed before interruption:
I fixed the task-card overflow at 320px. When the first line of a card can't fit everything, it now wraps onto a second line instead of making the list scroll sideways. Nothing is hidden or clipped, and tap targets are the same size.
The fix (
propr-ui/src/components/TaskList/MobileTaskCard.tsx):New browser test (
propr-ui/e2e/task-list-mobile-card-geometry.pw.ts): it uses mocked task data built from the measurements in the issue, not the real production UI or a real account. The cards include:At 320, 360 and 390px the test checks that:
scrollWidth≤clientWidth), and no card is eitherA separate 768px case checks that the wider layout hasn't changed: one 20px first line, status 8px after the repository, age at the right edge.
Test results:
The 320px screenshot also shows the "All Repos" filter button in the page header cut off at the right edge. That's outside this issue, so I didn't touch it.
Remaining work:
The agent stopped before validating every requirement. Review the partial diff against the original request and complete any unaddressed implementation, tests, or documentation before merging.
Detailed Logs:
94e19a5f-c3b4-432e-8a65-6f04bafd6d69Log files stored at:
/usr/src/app/logs/executions/issue-3271-2026-10-19T22-15-39-448Z-conversation.json/usr/src/app/logs/executions/issue-3271-2026-10-19T22-15-39-448Z-output.txtLatest Conversation Messages
This PR was created automatically by ProPR after processing issue #3271.
💡 Need changes?
Comment on this PR to request refinements — the AI agent monitors comments and will update the implementation based on your feedback. Keep iterating until you're satisfied!
Visual preview
Task cards at 320px
The widest real-world card content (PR chip with 12 attachments, task-id chip, long repository, Completed/Cancelled, two-digit minute ages): the first line wraps the age or status beneath instead of overflowing sideways
Original unavailable: managed storage is unavailable or the upload has expired.
Task cards at 360px
The same cards at 360px with no horizontal list scroll
Original unavailable: managed storage is unavailable or the upload has expired.
Task cards at 390px
The same cards at 390px with no horizontal list scroll
Original unavailable: managed storage is unavailable or the upload has expired.