fix(tickets): smooth cursor nav#113
Merged
Merged
Conversation
hiskudin
reviewed
Jul 1, 2026
hiskudin
left a comment
Collaborator
There was a problem hiding this comment.
Reviewed the diff. Right diagnosis, right fix — no changes needed from me.
withAnimation(.easeOut(duration: 0.15))aroundproxy.scrollTo(anchor: .center)firing on every key-repeat is exactly the bounce cause. Dropping the animation is the only fix that reads right at key-repeat cadence.- Memoization is correct:
handoffsRevisiondidSet clearscachedOutcomeGroups, so ledger changes bust the cache; thehideShippedTicketsfilter is still applied per call on top, so toggling "hide shipped" or a PR flipping to shipped both still take effect without a ledger tick. visibleOutcomeGroups()is only ever called from SwiftUI body renders + keyboard indexing (both main-thread), so the cache read/write stay serialized without an explicit lock. Consistent with the rest ofPanelNav.- The
.backgroundmoving from the wholegroupRowcontainer to just the header HStack fixes the "entire group lights up when a header is selected" perception cleanly, and.id(Self.headerID(group))moving inside the header HStack is fine because that HStack is unconditionally rendered —proxy.scrollTo(id:)still finds it.
Ship it.
hiskudin
approved these changes
Jul 1, 2026
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.
Summary
Holding ↑/↓ on the Tickets tab was jumpy, and crossing a group boundary made
the highlight appear to "bounce back up." This makes cursor navigation track
smoothly through a group's branches and straight on to the next group. The
selection logic was never wrong — this is all rendering/scroll.
Changes
scrollTo(anchor: .center)was wrapped in a 0.15s animation and fired onevery key-repeat. On a long list (100+ rows) the animations piled up, the
scroll lagged the selection, then settled with an upward snap — which read as
the highlight bouncing up. Dropping the animation pins the selection and
tracks it smoothly.
visibleOutcomeGroups()re-ran the fullgrouping (a regex per ledger record + branch breakdown + sorts) on every
body render, i.e. every selection change. Now cached and invalidated only
when the ledger changes (
handoffsRevision); thehideShippedfilter stillruns per call.
(which spans all its branches) — so
scrollTocenters a small, consistenttarget whether you land on a header or a branch.
keeps the selection a consistent small marker at every row.
Testing
./build.sh→ Build complete, zero warnings.moved perfectly monotonically (clean ±1 per keystroke, every index mapping to
the right row) — which is how we confirmed the "bounce" was scroll/animation,
not the selection.
multi-branch group and across boundaries — tracks smoothly, no bounce.
Related issues
Follow-up to the Tickets-tab repo-grouping work. No tracked issue.