Redesign document list with Finder-style views, sidebar workflows, and recents polish#91
Redesign document list with Finder-style views, sidebar workflows, and recents polish#91richardr1126 wants to merge 23 commits into
Conversation
…ndowed UI Revamp the document list experience by introducing a Finder-style window interface with multiple views (icons, list, columns, gallery) and a new sidebar filter system. Remove legacy folder and list item components in favor of modular, windowed views. Integrate react-dnd-touch-backend and custom DnD context for improved drag-and-drop, including mobile support. Update uploader and dialog styles for consistency. Extend document types to support new view modes, icon sizing, and sidebar state.
…roved file size formatting Integrate DocumentUploader in overlay mode to wrap all document views, enabling drag-and-drop uploads across the entire list area. Refine file size formatting to support KB, MB, and GB units in all views and tiles. Standardize button scaling and padding for consistent UI rhythm. Update DocumentPreview and detail panels to display both type and human-readable size. Add overlay drag visual feedback for uploads. These changes improve usability, visual clarity, and consistency in the document list interface.
…tons and columns UI Simplify document list state handling by centralizing loading and empty logic into DocumentList. Remove redundant state management from HomeContent. Refactor DocumentListSkeleton to support all view modes and icon sizes for improved visual consistency during loading. Enhance ColumnsView styling for folder and document rows, improving selection, hover, and drag feedback. Use useMemo for visible order calculation to optimize rendering. These changes streamline the document list rendering flow, unify skeleton loading visuals, and improve the clarity and responsiveness of the columns view interface.
… in document list Enhance mobile and desktop sidebar behavior by introducing a separate state for mobile sidebar visibility and ensuring it does not persist from desktop state. Update FinderToolbar to visually indicate sidebar open state and make the toolbar sticky for better accessibility. Refine FinderSidebar width handling for improved responsiveness. Remove redundant border in mobile sidebar dialog for a cleaner appearance. These changes provide a more consistent and intuitive sidebar experience across viewports.
… variables Replace fixed Tailwind grid column classes with a responsive CSS grid that leverages tile width variables per icon size. Grid columns now adapt automatically via `auto-fit` and `minmax`, and grid gaps are centralized for consistency. This update enhances layout flexibility, maintainability, and responsiveness in the icons view.
…iew toggle Replace inline icon size buttons with a dropdown menu that appears when the icons view toggle is active. This change improves toolbar clarity by grouping related controls and enhances accessibility with better focus handling. The update also streamlines the button structure for view mode selection.
…list Introduce recentlyOpenedAt field to document types and fetch per-document recently opened timestamps from local cache. Update the "Recently Opened" sidebar filter to sort by this value and show only documents with recent activity. Adjust grid layout logic for icons view to better handle small numbers of documents. Update sidebar label for clarity.
…der UI Eliminate folder grouping logic and related UI from all document list views. Switch to a flat document array model for rendering, selection, and filtering. Remove folder collapse/expand state and folder drag-and-drop handling. Update sidebar and toolbar components to remove folder creation and management controls. Simplify props and internal state across all views for consistency.
…eadiness Update gallery view document tiles with refined border, shadow, and background styles for better visual feedback and accessibility. Enhance image preview component to immediately reveal cached images by checking decode state on mount, preventing opacity glitches on remount. Adjust gallery rail scrolling to reset on document list changes for consistent navigation.
…tion Introduce a "Remove All Folders" action accessible via a new sidebar menu, allowing users to clear all folders at once. Add a confirmation dialog to prevent accidental removal. Update the FinderSidebar to include a menu button with the new action, and implement supporting state and handlers in the document list. Add DotsHorizontalIcon for menu UI. Expand folder tests to cover the new bulk removal flow.
… behavior Eliminate unused loading state and related effects from document tile and list row components. Standardize navigation by disabling prefetch on all document open links in doclist views for consistent client-side routing. Cache document list state on load to improve state restoration and initialization.
… and accessibility Revise test helpers and specs to use stricter role-based selectors for document actions, including delete buttons and document links. Improve accessibility and upload tests by asserting document presence via explicit file lists instead of generic text checks. Remove redundant summary assertion from delete flow.
…tility Move grid style and template calculation for icon views into a shared iconsGrid.ts utility. Replace inline grid logic in IconsView and DocumentListSkeleton with calls to the new iconsGridStyle function for consistency and maintainability.
Shift app-level actions (settings and user menu) from the top bar to the bottom of the sidebar for improved navigation consistency. Introduce a new "sidebar" variant for the UserMenu component with tailored styling and behavior for sidebar placement. Update SettingsModal to support a customizable trigger label and styling for sidebar integration. Refactor FinderSidebar to accept an optional bottomSlot, enabling flexible placement of sidebar controls.
Eliminate the deprecated "columns" view mode from the document list, toolbar, icons, and skeleton components. Update all related types and logic to only support "icons", "list", and "gallery" views. Standardize user-facing labels from "HTML" to "Text" for improved clarity across the sidebar, segment locator labels, and document counts. Clean up associated code and types to reflect these changes.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
💤 Files with no reviewable changes (2)
📝 WalkthroughWalkthroughThis PR refactors the document list into a Finder-style layout with touch-aware react-dnd backend switching, a selection context for multi-select, three view modes (icons/list/gallery), sidebar folders with persistence, finder toolbar/sidebar/status components, preview cache dedupe, Dexie lookup for recently opened, UI/skeleton/uploader updates, and test locator adjustments. ChangesDocument List View System Refactoring
Sequence Diagram (high-level flow) sequenceDiagram
participant Browser
participant DocumentDndProvider
participant DocumentSelectionProvider
participant DocumentList
participant DexieDB
Browser->>DocumentDndProvider: detect touch or mouse
DocumentDndProvider->>DocumentSelectionProvider: wrap children
DocumentList->>DexieDB: getDocumentRecentlyOpenedMap()
DocumentList->>DocumentSelectionProvider: setVisibleOrder / selection events
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
src/contexts/OnboardingFlowContext.tsxESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 12
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/components/auth/UserMenu.tsx`:
- Around line 75-86: The disconnect button in UserMenu.tsx currently exposes
only the user email (session.user.email || 'Account') as its accessible name;
update the button (the element with onClick={handleDisconnectAccount}) to
provide an explicit action label for screen readers—either add
aria-label="Disconnect account" (or "Sign out") to the <button> or include a
visually-hidden span (e.g., className="sr-only") with the action text alongside
the email so assistive tech announces the sign-out action clearly while
preserving the visible email.
In `@src/components/doclist/dnd/dndTypes.ts`:
- Around line 5-11: The drag payload currently loses type info because
DocumentDragItem.ids: string[] only holds raw IDs; change the shape to preserve
type by replacing ids with e.g. items: { id: string; type: string }[] (or a
composite key string if you prefer) and update references to DocumentDragItem
(including usages in folder move/dedupe logic and any functions expecting ids)
to use the new items list or composite key so consumers can distinguish same-id
documents of different types; ensure DocumentDragItem.docs and any conversion
helpers are updated to derive or match the new item type.
In `@src/components/doclist/DocumentList.tsx`:
- Around line 384-401: The folder move/merge logic in handleDropOnFolder (the
setFolders mapping that uses item.ids, existingIds.has, and filtering by d.id)
compares only numeric ids and thus conflates cross-type items (e.g., "pdf/123"
vs "html/123"); change all identity comparisons (item.ids.includes(d.id),
existingIds.has(d.id), and any s.id !== target.id logic) to compare the same
composite key used by selection (e.g., `${type}/${id}` or the existing
selectionKey on DocumentDragItem and Document entries) so removal/deduping only
matches when both type and id match; apply the same fix to the other block
mentioned (lines 410-443) where documents are compared/filtered by id.
- Around line 272-305: The maps (allDocumentsById, foldersWithLiveDocs,
folderNameById, folderIdByDocId) are keyed only by doc.id causing collisions
across different document types; change them to use a stable composite key of
type+id (e.g. `${doc.type}|${doc.id}` or JSON.stringify({type,id})) when
building and looking up entries (update the map creation in allDocumentsById and
folderIdByDocId and the lookups in foldersWithLiveDocs and folderNameById to use
that composite key so document/folder hydration and badge lookups use {type,id}
identity).
In `@src/components/doclist/formatSize.ts`:
- Around line 1-8: The formatDocumentSize function renders sub-1KB sizes as
fractional KB; add a branch at the start of formatDocumentSize to handle bytes <
1024 and return an integer bytes string with "B" (e.g., "0 B", "512 B") instead
of using KB formatting; keep the existing GB and MB branches and the KB branch
for >=1024 to preserve current behavior.
In `@src/components/doclist/views/DocumentTile.tsx`:
- Around line 82-105: The drag payload’s item callback in DocumentTile’s useDrag
closes over selection.getSelectedDocs() and selection.replace(...) but the hook
deps are only [doc, isSelected], causing stale payloads when selection changes;
update the implementation so the item callback reads the current selection (or a
selection-version token) at drag-start by making the item function stable with
correct dependencies: include the selection reference or a selection
version/getter in the useDrag dependency array (or wrap the item callback in a
useCallback that depends on selection / selection.getSelectedDocs() /
selectionVersion) so selection.getSelectedDocs() and selection.replace() are
always up-to-date when dragging begins.
In `@src/components/doclist/views/GalleryView.tsx`:
- Around line 144-168: The keyboard handler in GalleryView.tsx can set activeIdx
to -1 when documents.length === 0; update the onKey handler (the useEffect that
defines onKey) to guard against an empty gallery by returning early if
documents.length === 0 (or otherwise skipping ArrowLeft/ArrowRight logic).
Specifically, inside the onKey callback referenced by window.addEventListener,
check documents.length === 0 before computing or calling setActiveIdx so
ArrowRight/ArrowLeft cannot produce negative or out-of-range indices for
activeIdx.
In `@src/components/doclist/window/finderIcons.tsx`:
- Around line 5-16: The baseSvg function currently sets width and height
defaults before spreading ...props, which allows callers to pass explicit
undefined to override the defaults; modify baseSvg (and use IconProps) to
destructure width and height with defaults from props (e.g., const { width =
'1em', height = '1em', ...rest } = props) and then return the SVG object using
width and height from those variables and spread ...rest so undefined values on
props do not clobber the defaults.
In `@src/components/doclist/window/FinderStatusBar.tsx`:
- Around line 1-14: The local formatSize function in FinderStatusBar.tsx causes
sub-1MB values to round to 0; remove this local formatSize and instead import
and use the shared size formatter used by the document list UI (replace calls to
formatSize in FinderStatusBar with the shared formatter), keeping
FinderStatusBarProps and all usage of itemCount/selectedCount/totalSize
unchanged so the status bar uses the canonical formatting logic.
In `@src/components/doclist/window/FinderWindow.tsx`:
- Around line 63-65: The Dialog in FinderWindow currently calls
onSidebarOpenChange(false) via its onClose prop which allows backdrop clicks and
Escape to dismiss the mobile drawer; remove the onClose handler (or replace it
with a no-op) from the Dialog component so it no longer closes via the generic
dismiss path, and ensure the existing explicit row action callbacks (the
sidebar/row action handlers that already call onSidebarOpenChange(false)) remain
the only places that close the drawer.
In `@src/components/documents/DocumentUploader.tsx`:
- Around line 100-122: The overlay branch (when variant === 'overlay') never
shows upload errors even though onDrop sets an error state; update the JSX
returned by the overlay branch (inside the element created from
getRootProps()/getInputProps()) to conditionally render the existing error state
(e.g., error) alongside the drop instructions when isDragActive is true or below
them when not active, and include a short retry hint or action (e.g., "Upload
failed: {error} — try again") so users see the failure and can retry; touch the
component rendering inside the overlay div that contains UploadIcon and the
accept text (reference: variant, getRootProps, getInputProps, isDragActive,
enableDocx, onDrop, error).
In `@src/lib/client/dexie.ts`:
- Around line 828-848: The current getDocumentRecentlyOpenedMap uses
db[PDF_TABLE].toArray(), db[EPUB_TABLE].toArray(), and db[HTML_TABLE].toArray(),
which loads full document payloads into memory; change the implementation to
only fetch id and cacheAccessedAt (avoid full ArrayBuffer/HTML payloads). For
each table (PDF_TABLE, EPUB_TABLE, HTML_TABLE) replace the toArray() calls with
a lean iteration or keyed fetch: obtain the primary keys (e.g.,
table.toCollection().keys() or table.primaryKeys()), then use
table.bulkGet(keys) or table.get(key, ['cacheAccessedAt']) to retrieve only
cacheAccessedAt for each id, and feed those id/timestamp pairs into the same
write(...) logic in getDocumentRecentlyOpenedMap so the recents map is built
without loading full cached documents.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: b08b98b8-847a-40ce-9a62-38533d82ada8
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (38)
package.jsonsrc/app/(app)/app/page.tsxsrc/app/(app)/layout.tsxsrc/components/HomeContent.tsxsrc/components/SettingsModal.tsxsrc/components/auth/UserMenu.tsxsrc/components/doclist/CreateFolderDialog.tsxsrc/components/doclist/DocumentFolder.tsxsrc/components/doclist/DocumentList.tsxsrc/components/doclist/DocumentListItem.tsxsrc/components/doclist/DocumentListSkeleton.tsxsrc/components/doclist/DocumentPreview.tsxsrc/components/doclist/SortControls.tsxsrc/components/doclist/dnd/DocumentDndProvider.tsxsrc/components/doclist/dnd/DocumentSelectionContext.tsxsrc/components/doclist/dnd/dndTypes.tssrc/components/doclist/formatSize.tssrc/components/doclist/views/DocumentTile.tsxsrc/components/doclist/views/GalleryView.tsxsrc/components/doclist/views/IconsView.tsxsrc/components/doclist/views/ListView.tsxsrc/components/doclist/views/iconsGrid.tssrc/components/doclist/window/FinderSidebar.tsxsrc/components/doclist/window/FinderStatusBar.tsxsrc/components/doclist/window/FinderToolbar.tsxsrc/components/doclist/window/FinderWindow.tsxsrc/components/doclist/window/finderIcons.tsxsrc/components/documents/DocumentUploader.tsxsrc/components/icons/Icons.tsxsrc/components/reader/SegmentsSidebar.tsxsrc/lib/client/cache/previews.tssrc/lib/client/dexie.tssrc/types/documents.tstests/accessibility.spec.tstests/delete.spec.tstests/folders.spec.tstests/helpers.tstests/upload.spec.ts
💤 Files with no reviewable changes (4)
- src/components/doclist/DocumentFolder.tsx
- src/components/doclist/SortControls.tsx
- tests/delete.spec.ts
- src/components/doclist/DocumentListItem.tsx
…drop robustness Introduce a document identity key combining type and id for consistent identification across document operations, including selection, drag-and-drop, and folder management. Refactor drag item structures to use identity objects instead of plain ids, preventing cross-type collisions and improving merge accuracy. Update Dexie recently opened map to use identity keys. Enhance document size formatting for small files and improve error feedback in the uploader. Clean up redundant props and standardize icon SVG handling.
Summary
Major Changes
Summary by CodeRabbit
New Features
Improvements