feat(ui): sticky restore action bar and virtualized large lists - #54
Merged
Merged
Conversation
Make the Restore browser usable on huge folders. - Sticky action bar: the selection / destination / Restore / Cancel bar is now position: sticky; bottom: 0 within the page scroll container, with a page-matching background, top border, and z-index so it stays reachable without scrolling a large folder all the way down. Readable in light and dark mode; a small section bottom buffer keeps the last rows clear of it. - Virtualized file list: a new dependency-free windowing composable (useVirtualList + the pure, unit-tested computeVirtualRange) renders only the visible window (+ overscan) of fixed-height rows and replaces the rest with top/bottom spacer paddings, so a folder with thousands of entries mounts a bounded number of <li> nodes instead of one per file. Selection, keyOf keying, breadcrumb nav, search-vs-tree rendering, the truncated notice, and empty states are all preserved (the store still holds every row; only the DOM is windowed). Tests: pure windowing math (visible-range, spacer invariant, bounded slice, fallback) plus a Restore.vue test asserting a 5000-entry folder mounts a bounded row count with a large bottom spacer and that the action bar is sticky. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MZQh3ZfwtZsM6c5qnTuWZP
Contributor
Coverage
Gate: passed - no coverage regression (epsilon 0.1 pp). |
pmaxhogan
marked this pull request as ready for review
June 27, 2026 01:47
…ex P2) Addresses codex /codex review [P2] findings before merge. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MZQh3ZfwtZsM6c5qnTuWZP
pmaxhogan
enabled auto-merge (squash)
June 27, 2026 02:04
pmaxhogan
added a commit
that referenced
this pull request
Jun 27, 2026
🤖 I have created a release *beep* *boop* --- ## [0.4.0](v0.3.1...v0.4.0) (2026-06-27) ### Features * **ui:** global backup progress bar in the app header ([#55](#55)) ([b7513b5](b7513b5)) * **ui:** sticky restore action bar and virtualized large lists ([#54](#54)) ([4631225](4631225)) ### Bug Fixes * **ui:** keep the activity screen smooth during uploads ([#56](#56)) ([44f3853](44f3853)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
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
Fixes the Restore browser for large folders (issue #47).
position: sticky; bottom: 0within the page scroll container, with a page-matching background (bg-zinc-50 dark:bg-zinc-950), a top border, and a z-index so it sits above the list. The primary actions stay reachable without scrolling a huge folder all the way down. It reads correctly in both light and dark mode, and a smallpb-4buffer on the section keeps the last rows clear of it when scrolled to the bottom.useVirtualList(and its pure, unit-tested corecomputeVirtualRange) renders only the visible window of rows (plus a small overscan) at a fixed row height and replaces the off-screen rows with top/bottom spacer paddings on the<ul>, so the scrollbar still reflects the full list while the DOM node count stays bounded. A folder with thousands of files mounts ~26<li>nodes instead of thousands.keyOfkeying, breadcrumb navigation, search-result vs tree-node rendering, thetreeTruncatednotice, keyboard/scroll behavior, and the empty states are all unchanged. The store still holds every row in memory; only the DOM is windowed. UI-only, no Rust touched.Testing
All run from the worktree in
ui/:pnpm install --frozen-lockfile- okpnpm lint- cleanpnpm format:check- all files match Prettier stylepnpm test:unit- 25 files, 218 tests pass (11 new: 9 windowing-math + 2 Restore.vue component tests; existing restore-store and restore-empty-dropdown tests still green)pnpm build(vue-tsc --noEmit && vite build) - typecheck + build succeedNew tests:
ui/src/__tests__/virtual-list.test.ts- visible-range math, the spacer invariant (top + window + bottom == full content height), bounded slices when scrolled into / past / before the list, and the zero-measure fallback.ui/src/__tests__/restore-virtual-list.test.ts- mounts the realRestore.vueagainst a 5000-entry folder and asserts a bounded<li>count + a large bottom spacer, plus that the action bar carries the sticky/bottom-0/border-t/z-10/background classes and contains the Restore action.Closes #47
🤖 Generated with Claude Code
https://claude.ai/code/session_01MZQh3ZfwtZsM6c5qnTuWZP