Skip to content

feat(ui): keep active diff file headers visible - #110

Merged
wingleeio merged 10 commits into
zeronsh:mainfrom
jsgrrchg:feature/sticky-diff-headers
Aug 25, 2026
Merged

wingleeio merged 10 commits into
zeronsh:mainfrom
jsgrrchg:feature/sticky-diff-headers

Conversation

@jsgrrchg

@jsgrrchg jsgrrchg commented Aug 15, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Keep the active file header visible while scrolling through long diffs in the Changes panel.

The sticky header preserves the existing file path, binary status, addition/deletion counts, chevron, hover state, and collapse/expand interaction. When the next file header reaches the top boundary, it pushes the current sticky header away.

What changed

  • Added a pure StickyFileHeader resolver based on the flattened diff row ranges.
  • Reused the existing file-header composition for both regular and sticky presentations.
  • Added distinct GPUI element IDs for regular and sticky headers.
  • Added a clipped, relative container around the virtualized diff list.
  • Rendered at most one additional sticky header overlay.
  • Calculated the push-off position from measured GPUI list and viewport bounds.
  • Preserved the regular header's translucent wash with a small backdrop blur on glass themes, plus an opaque fallback elsewhere.
  • Added a subtle bottom border and shadow to separate the overlay from the diff.
  • Allowed wheel and trackpad scrolling to pass through the sticky header.
  • Kept fold/collapse behavior shared between regular and sticky headers.
  • Added coverage for empty ranges, header boundaries, collapsed files, invalid indices, and push-off offsets.

Performance

  • The diff remains line-virtualized.
  • Active-file lookup uses partition_point over row_ranges (O(log n)).
  • No persistent scroll state, timers, debouncing, or manual height accumulation were introduced.
  • Only one additional 36 px overlay is rendered when needed.
  • The 16 px backdrop blur is restricted to that single header strip and only runs on glass themes.
  • Missing measurements for the next header safely fall back to top: 0.

Scope

Covered through the shared Changes renderer:

  • Working tree
  • Branch changes
  • Latest turn
  • Commit

Out of scope:

  • History diffs
  • Inline tool-call diffs inside the transcript
  • Hunk-level sticky headers
  • Parser, engine, RPC, protocol, or data-model changes

Validation

  • cargo fmt --all -- --check
  • cargo test -p zeron-ui changes
  • cargo test -p zeron-ui — 425 tests passed
  • git diff --check

cargo clippy -p zeron-ui --all-targets -- -D warnings is currently blocked by pre-existing unrelated lints in the workspace and other UI modules.

Manual QA checklist

  • Long single-file diff keeps its header visible while scrolling.
  • Multiple files transition through the push-off behavior in both directions.
  • Collapse/expand works from both the regular and sticky header.
  • Collapse all / expand all preserves a valid scroll position.
  • Wheel and trackpad scrolling work while the pointer is over the sticky header.
  • Added, deleted, renamed, binary, and truncated paths render correctly.
  • Working tree refreshes and scope changes do not leave stale sticky headers.
  • Summary strip, scrollbar, titlebar controls, and hover hit-testing remain unaffected.

@jsgrrchg
jsgrrchg marked this pull request as ready for review August 15, 2026 15:27
@jsgrrchg

Copy link
Copy Markdown
Contributor Author

fixed an issue with light mode, forgot to test it in light mode

jsgrrchg added a commit to jsgrrchg/comet that referenced this pull request Aug 17, 2026
@jsgrrchg

Copy link
Copy Markdown
Contributor Author

Updated the sticky diff headers to properly follow the active theme in both light and dark modes. Frosted themes now use a theme-aware content background tint, hover state, and border, while opaque themes preserve their expected appearance. Added tests covering both appearance modes and theme variants.

@wingleeio wingleeio left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking findings.

Safety review: this stays within GPUI presentation/list-state code in crates/ui/src/changes.rs; it adds no dependency, network, filesystem, process, protocol, or unsafe-code surface. The sticky-header resolver bounds-checks stale indices, and the overlay preserves scroll pass-through and the existing collapse callback.

Validation:

  • git diff --check origin/main...c4a14a8
  • rustfmt --check --edition 2024 crates/ui/src/changes.rs
  • cargo test -p zeron-ui changes — 33 passed
  • cargo test -p zeron-ui — 556 passed
  • cargo build -p zeron
  • Live QA in an isolated synthetic repository: unified/split layouts, push-off transition, sticky-header collapse, wheel pass-through, long-path truncation, and themed presentation

The repository-wide clippy command still reports 22 unrelated pre-existing warnings outside changes.rs; this patch introduces none of them.

Unified push-off transition:

Unified sticky-header push-off

Split-view sticky header:

Split-view sticky header

Scroll pass-through and long-path truncation:

Scroll pass-through and truncation

@wingleeio wingleeio left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One visual change requested: please remove .shadow_sm() from the sticky diff header. It reads like a raised Material-style card and separates the header too heavily from the diff content. The existing 1px bottom border plus the themed surface tint/blur is enough to establish stickiness without introducing elevation.

@jsgrrchg

Copy link
Copy Markdown
Contributor Author

Fixed, good catch, looks much better now

@wingleeio wingleeio left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed commit faff962 against main 2ebe6ed. No blocking findings; the requested shadow removal is present. The prospective merge is conflict-free, formatting and diff checks pass, all 575 zeron-ui tests pass, and cargo build -p zeron succeeds.

@wingleeio
wingleeio merged commit b3fa518 into zeronsh:main Aug 25, 2026
1 check passed
guilhermexp pushed a commit to guilhermexp/comet that referenced this pull request Aug 30, 2026
feat(ui): keep active diff file headers visible
hoangvu12 added a commit to hoangvu12/roboco that referenced this pull request Oct 13, 2026
…#110)

The folder browser's browsing half: FolderBrowserController (generation
guard, failure statuses, listingUsable, live host list, listingIsRepo
and onListingApplied hooks), NewProjectScreen (52 dp nav bar with glass
x/close + sheet-centred title + engine capsule and its glass menu, the
inset-grouped folder list with ticket 70 rows and the 160 dp bottom
inset, serial-keyed sections for scroll retention), 92's
NewSessionOptions.kt created per its spec (not yet landed), the debug
gallery section + fixtures + FakeHostPaths, the gallery registration,
controller tests and the Roborazzi screen tests. Builds/tests deferred
to the CI/VPS batch per the speed-rule override.
hoangvu12 added a commit to hoangvu12/roboco that referenced this pull request Oct 13, 2026
The reviewer noted the Derived-strings table's 'C:\ -> C:\' example was
only covered transitively; rowsAndTitleFollowTheListing now loads a
'C:\' listing and asserts the empty rows and the path-as-title.
hoangvu12 added a commit to hoangvu12/roboco that referenced this pull request Oct 13, 2026
Found by the import check over zeronsh#101, zeronsh#110, zeronsh#97, #41, #33 (not yet compiled
by CI):
- FolderBrowserController: Snapshot is androidx.compose.runtime.snapshots
- NewProjectScreen: Layout is androidx.compose.ui.layout.Layout
- SessionListStatusOverlay: Modifier.testTag is ui.platform.testTag (the
  semantics property was imported)
- LicensesBehaviourTest: SemanticsMatcher is ui.test; onAllNodes is a
  member, not importable
- SessionListBehaviourTest: Modifier and onRoot imports
hoangvu12 added a commit to hoangvu12/roboco that referenced this pull request Oct 14, 2026
… layer

NewSessionDraft + JSON codec (iOS Codable shape, nulls omitted, lenient
decode), NewSessionDraftStore (DataStore under newSessionDraft, text in
84's Drafts under new-session, memory-only images, launch harness
override, engine forget + full reset epoch), ModelCatalog source +
process-static cache, NewSessionModel (defaults, stale-id rule,
rememberDraft/markCreated moments, loadModels with app-scope fetch),
NewSessionDraftEffect (dispose + ON_STOP saves), RobocoApplication wiring.
NewSessionOptions.kt stays zeronsh#110's verbatim stand-in, now owned by zeronsh#92.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants