feat(drive): list view on frappe-ui/list, inline folder tree, derived breadcrumbs - #378
Merged
Conversation
Collaborator
Author
|
Also redoes list view, adds infinite scrolling, removes rename dialog, and a couple more long pending issues. |
…er fixes fix(writer): join adjacent same-type list nodes after each transaction so deleting a block between two lists (or Enter-lifting an item out) no longer restarts numbering; map boundaries through tr.mapping, require matching list types, and collect top-level boundaries since descendants() skips the doc node fix(drive): let an open dialog's own Escape handler run instead of clearing the selection in GridView/ListView (preventDefault was blocking Reka's dismiss) fix(writer): focus the comment editor without scrolling, on mount and when it flips into edit mode refactor(drive): use the Button component for UploadTracker controls and MoveDialog breadcrumbs; tidy ConfirmDialog markup and use a solid trash button refactor(writer): drop the watermark logic from PDF and print export style(writer): sentence-case the settings labels style(drive): add gap in the UserListSettings avatar row Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… typography Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
safwansamsudeen
force-pushed
the
fix/frappe-ui-typography
branch
from
July 29, 2026 09:09
fd60996 to
c4d46ae
Compare
Clicking a folder's icon in the list view opens it as a tree in place instead of navigating: hovering a row swaps the icon for a chevron, and children render indented under the folder with the full row behaviour (selection, shift-range, context menu, rename, share, move, delete, drag-and-drop in and out). - data/folderTree.js holds the expansion state and per-folder children, fetched with the parent's sort. Collapsing drops the subtree and returns the hidden names so ListView can deselect them; a per-folder token discards responses a newer fetch has superseded. - Rows carry path-based keys, since a folder and its child can both be top-level rows in Favourites/Recents/search. - GenericPage resolves selections and actions against children too, so the toolbar operates on nested rows; the tree resets on navigation and re-fetches open subtrees on a sort change. - Loading shows one skeleton row per known child (capped at 20) so the layout doesn't shift when children land. Also in this branch: - inline rename: select the base name on focus, reclaim focus for the whole grace window after opening, roll the title back if the rename request fails, and surface the server message instead of the raw error - sortEntities: folders sink below files on a size sort and order by child count; nullish values sort last; smart sort only for name - move the list/grid keyboard shortcuts up to GenericPage - dark-mode scrollbar colours, stable scrollbar gutter, toolbar filter placement, sort button hugs its label, grid rows top-aligned - e2e coverage for renaming a document from the breadcrumb Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Tab lookups scanned the doc with `descendants` and returned false to stop, which only skips a node's children, not its siblings — so with two same-id tabs every lookup silently used the last match (print emitted only the second half) while the node view unhid both. Route all lookups through tabsIn/findTab, and refuse transactions that introduce a duplicate id. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The breadcrumb trail was a mutable global written from eight places (route hooks, openEntity, rename, move dialog, and four pages), and it doubled as ambient app state: the sidebar highlight, isHomeContext, and the personal flag on image upload all read crumb 0. Any writer that missed left a stale or empty trail, which is why the navbar kept disappearing. pageBreadcrumbs is now computed from the route plus a single crumbEntity published by the page that owns it. Every setter is gone; what remains acts on the entity, never on a trail. Also fixed along the way: - Navbar no longer unmounts when the trail is empty; the bar keeps its actions and gets shrink-0 so a tall list can't squash it. - MoveDialog emitted `success` before awaiting the move, so EntityDialogs reset the dialog and its `@complete` refetch never ran — moving the open folder left the old parent in the trail. Refetch and close now both happen on `@complete`. - MoveDialog rows had no hover surface: frappe-ui's Tree drops its own when a consumer overrides #item. - drive-Teams gained the page-title hook it never had. Covered by e2e/drive-backed-apps/specs/drive/breadcrumbs.spec.ts: section names, nested trails, ancestor navigation, deep links, browser back, rename, and move. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reordering deleted the tab node and re-inserted a copy. Yjs has no move operation, so that destroys the element and creates a new one with the same id: a concurrent peer or an undo leaves both alive, with the content split between them, and it also drops edits made inside the moved tab. Tab order now lives in a `data-tab-order` attribute that reorder rewrites in place, so nodes never move. Documents without the attribute keep falling back to document order. Since document order is no longer display order, getHTML serialises the tab slots in display order — patched in onBeforeCreate because tiptap emits `create` a tick late. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…lures The list view lost its grid in production builds: `frappe-ui/list` imports list-style.css from a module the bundler treats as side-effect-free, so the stylesheet was tree-shaken away and every header and row cell stacked. Import it from the app entry. - restore `data-testid="drive-entity-<name>"` on list rows (dropped in the frappe-ui/list migration, so every e2e row locator missed) and add `drive-expand-<name>` for the inline folder toggle - confirmRemove/confirmRestore and toggleFav spread a resource's `data` that is null until that list is first fetched — trashing a file before opening Trash threw "d is not iterable", leaving the dialog open with the file already trashed server-side - surface the server's message when a move fails, and refetch the list plus open subtrees so optimistically removed rows come back - e2e: drive and drive-writer specs drive the inline rename instead of the removed Rename dialog; new tree-expand spec covers expanding a folder in place and dragging a subfile into another folder Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Everything in it was either global or dead: the scroll-shadow helper and the
fade-in transition classes had no users, `html { scrollbar-width: auto }` set
the default, and `body { overflow: hidden }` is already implied by the shell's
height: 100% chain. The theme-switching transition freeze belongs next to
setupTheme's own class, so it moves to the root stylesheet.
Scrollbars now follow `color-scheme` per theme instead of hardcoded hexes —
nothing declared it, which is why dark mode drew a light scrollbar (and light
native controls) in the first place.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
An empty or placeholder trail rendered as a blank bar, which read as the breadcrumbs disappearing when navigating. EditableBreadcrumbs now owns the loading state — two bars and a separator, so it has the shape of a real trail — which also gives Writer's navbar the same treatment, since it uses the same component. The e2e trail helper now targets the breadcrumbs test id instead of the first div in the navbar, and waits for the loading state to clear; the positional lookup raced with the skeleton. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…suite into fix/frappe-ui-typography
This was referenced Jul 30, 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
Drive's list view now runs on
frappe-ui/list, folders expand inline as a tree, and breadcrumbs are derived from the route instead of a mutable global. Plus Writer list-numbering and tab fixes.Changes
List view on
frappe-ui/list— real column tracks, inset dividers, a sticky sortable header, and the typography/dialog cleanups that came with it.Folders expand inline. Hovering a row swaps the folder icon for a chevron; clicking it expands the folder underneath. Clicking elsewhere in the row still navigates in. Nested rows behave like any other row — selection, context menu, rename, move, delete, drag-and-drop in and out of a subtree.
Breadcrumbs are derived. The trail was a mutable global written from eight places, and it doubled as ambient state — the sidebar highlight and the
personalflag on upload both read crumb 0, so a missed writer left it stale or empty. It is now computed from the route plus the entity the open page publishes. This fixes the navbar vanishing mid-navigation, and moving a folder updating its trail (which never worked; a loading placeholder hid it).Writer — list numbering no longer restarts when you edit around a list, and reordering tabs can't duplicate them.
Notable fixes along the way
MoveDialogclosed before awaiting the move, so its@completerefetch never ran.title, notfile_name.bg-surface-whiteis a retired token, so the background was dropped).Testing
folderTree.test.ts— 16 cases covering fetch params, the stale-response race, collapse-drops-subtree, path keys, skeleton counts.breadcrumbs.spec.ts— 7 e2e cases: section names, nested trails, ancestor navigation, deep links, browser back, rename, move.rename.spec.ts,tabs.spec.ts— breadcrumb rename persistence; tab reordering preserves content.Full suite: 1057 unit tests, 34 e2e.
Known limits
⌘A and the filter chips apply to top-level rows only, socket updates patch just the current folder, and the chevron isn't keyboard-reachable yet. The navbar still flashes on navigation because
DriveLayoutkeys itsrouter-viewon$route.fullPath, remounting the page and navbar on every route change — the skeleton makes it read as loading, but the remount itself is untouched.🤖 Generated with Claude Code