fix(tasks): count the rows a project lists, and let dialogs shrink - #1880
Merged
Conversation
A project showed three different task numbers at once: 130 on the Tasks tab, 93 in the sidebar, and TO DO (0) / IN PROGRESS (0) / DONE (37) in the sections under the badge that was claiming 130. None of them was the number of rows on screen. The hub badge counted every non-archived task carrying the project id; the sidebar badge counted the non-done ones. Both included subtasks, which render nested under a parent rather than as rows, and both included tasks whose status the project no longer has — which `groupTasksByStatus` matched to no bucket and dropped, leaving them invisible and uneditable while every badge kept counting them. Both badges now count top-level tasks, and the first status adopts tasks whose status is gone, so nothing is counted that cannot be seen and nothing on file is unreachable. The project picker drops archived tasks for the same reason the sidebar already did. Separately: multi-select delete with a long task title carried the confirm button off the dialog, and off the window entirely once the title was long enough. `DialogContent` is a grid, and a grid track sizes to its content's minimum, so one unbreakable string widened the single column past `max-w-lg` and the footer's end-aligned buttons rode along. Clamping the track with `minmax(0,1fr)` lets `truncate` do its job, in every dialog rather than only this one. Closes #1878
|
React Doctor found no new issues. 🎉 Reviewed by React Doctor for commit |
h4yfans
marked this pull request as ready for review
August 27, 2026 23:33
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1878
Summary
Two defects from one user report.
1 — a project showed three different task numbers at once
The Inbox project's tab bar read Tasks 130, the sidebar read 93, and the sections under the 130 read TO DO (0), IN PROGRESS (0), DONE (37).
None of the three was the number of rows on screen, because each counted a different set:
useProjectHub)getTaskWorkspaceCounts)So both badges counted subtasks, which render nested under a parent rather than as rows of their own, and both counted tasks whose
statusIdis no longer one of the project's statuses.That second group is the worse half.
groupTasksByStatusmatched them to no bucket and dropped them, so they were invisible and uneditable while every badge kept counting them. 130 − 37 = 93 is not a coincidence: the two badges were reporting on tasks the tab could not show.Both badges now count top-level tasks — the tab all of them, the sidebar the open ones — so the tab badge equals its own sections added together, and the sidebar badge is that minus the done ones. The first status adopts tasks whose status is gone, so nothing on file is unreachable and nothing counted is unseeable. The project picker in the Tasks toolbar was counting archived tasks; it now excludes them, as the sidebar already did.
2 — a long task title carried the bulk-delete confirm button off the window
DialogContentis a CSS grid. A grid track sizes to its content's minimum, so one long unbreakable title widened the single column pastmax-w-lg; every row stretched to that track, and the footer's end-aligned buttons rode along with it.truncateon the title could not help, because a flex item will not shrink below its content withoutmin-w-0.Clamping the track with
grid-cols-[minmax(0,1fr)]fixes it for every dialog in the app, not only this one. The bulk-delete row gets themin-w-0itstruncatewas always missing.Release note
Project task counts now match the list they label: subtasks count under their parent instead of separately, and a task whose status was deleted shows up in the project's first status instead of disappearing. Deleting several tasks at once no longer pushes the confirm button off the window when one of them has a long title.
Test plan
Bug 2, measured in a real browser. jsdom does no layout, so the claim was checked in headless Chromium at 1280px against the exact pre- and post-fix markup, with the title from the report repeated three times:
The dialog itself never exceeds 512px in either case — it is the track and the footer that escape it, which is why the button leaves the window while the dialog looks fine.
Bug 1, pinned to the render path. The new
useProjectHubtest builds a project holding an open parent, its subtask, a done task, a task with a deleted status, and an archived task, then asserts the badge equals the rowsflattenTasksByStatusactually emits — so the badge cannot drift from the list again without going red.Both halves of that test were mutation-checked: restoring the old count gives
expected 4 to be 3, and removing the orphan-status adoption givesexpected [ …(2) ] to have a length of 3 but got 2.The badge-vs-filter equivalence matrix in
task-workspace-counts.test.tsis unchanged in shape; its expectation now states the top-level rule explicitly and every count in it moved accordingly.typecheck:web,typecheck:test,eslinton the diff,git diff --check,docs:impact --base origin/main --strict,docs:buildall pass.pnpm typecheckfails onorigin/mainbefore this branch exists, in the architecture boundary check (apps/mobile/vitest.config.ts -> node:url, arrived with #1863); it needs its own fix.One note for anyone who sees a red local run: 35 renderer suites fail on Node 26 with
Cannot read properties of undefined (reading 'clear'), because jsdom leaveslocalStorageundefined there. The repo asks for Node 24 (engines), and on Node 24 every one of them passes. Nothing to do with this branch, but it looks alarming.Caveats
A subtask whose parent no longer exists in the task list still renders nowhere, and is now no longer counted either. It was unreachable before this change and remains so; making orphaned subtasks recoverable is a separate piece of work.