Add sidebar thread folders (folders view, scoped archived views, shared components)#258
Merged
Merged
Conversation
06d9fec to
04bfdda
Compare
brsbl
added a commit
that referenced
this pull request
Jun 23, 2026
These are the non-folder changes split out of the nested-folders PR (#258), placed here so #258 is folder-only and nothing is dropped. Adapted to main's reworked sidebar (chevron/worktree-menu ProjectRow, ProjectActionsMenu). Search deep-link / scroll-to-message: - Expose ThreadSearchMatch.sourceSeq (db) + threadSearchMatchSchema.sourceSeq (contract); server already passes matches through. - useScrollToSearchedMessage + ThreadTimelineRows scroll hook, AppSidebar nav state (searchMessageSeq), SidebarThreadSearchPanel/sidebarThreadSearch messageSeq, app.css bb-search-flash, thread-search tests. - ThreadSearchResultRow redesign (+ story). Sidebar/menu interaction polish: - Row cursor/state-class affordances (sidebarRowClasses cursor-pointer + selected /70, ThreadRow grab cursor + dropped title tooltips, ProjectList + ProjectRow row classes), adapted to main's chevron (SidebarChildToggleChevron drops title props; callers updated). - Menu icons + label tweaks (ThreadActionsMenu Mail/Pin icons, "Mark read", separators) + rename payload refactor (ThreadActionsProvider/ThreadRenameDialog), PinnedThreadTree/ProjectListProjects/SidebarHistoryNavigationControls/ sortableMotion/ui sidebar tooltip + story-harness TooltipProvider. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
brsbl
added a commit
that referenced
this pull request
Jun 24, 2026
- Swap the worktree-style FolderGit icon for a plain Folder icon, matching the sidebar's project/folder iconography (avoids the worktree confusion). - Add an optional folderLabel prop: when the sidebar is organized by folder the caller passes the thread's folder path, shown in place of the project. Story adds an 'organized by folder' variant demonstrating title + folder. The live wiring (caller deriving folderLabel from Organize-by + thread.folderPath) lands when #258's folderPath merges in — that data is not on this branch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1c0a029 to
290dedb
Compare
Add thread folders end to end, rebuilt cleanly on top of current main so the change set is folder-only (no cross-cutting design/interaction polish). Backend - thread_folders table + migration 0044_thread_folders (snapshot + journal), folderPath column on threads, fld_ id prefix, thread-folders data CRUD (create/rename/delete/ensure/list + path normalization), and folderPath handling in createThread/updateThread/listThreads (folderPath + unfiled). - domain threadSchema.folderPath; server-contract folder routes + request/ response schemas, folderPath in thread create/list/update/filter schemas, folders in the sidebar bootstrap response. - server thread-folders routes + registration, folderPath in thread create/ update/list and the public thread mapper. Frontend (built on main's reworked ProjectRow) - SidebarFolderRow, folder bucketing/grouping in projectThreadGroups, ProjectList folder sections + the Group-by-folder organize menu, folder collapse/organize state atoms, folder drag-and-drop, ThreadFolderCreateDialog, folder API client methods, folder query keys, folder archived views + route-paths, and create-thread-in-folder from the root composer. - ProjectRow keeps main's chevron/worktree-menu header (ProjectRow.interactions tests pass unchanged); folder rendering lives in the cross-project Folders view. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The folder row's action span was missing the bb-sidebar-hover-actions class, so its ···/+ buttons stayed visible on every folder row. Add the class so they reveal on row hover / focus / menu-open, matching the project row. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Aligns the visible label (tooltip / mobile title / menu header + aria-label) with the existing internal naming (sidebarOrganizationModeAtom / organizationMode). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Row actions reveal on hover by default; but when exactly one project/folder container is open (visible + expanded) the sidebar is sparse, so render them inline. Counted once in ProjectList (expanded projects in the Projects section + visible-expanded folders in the Threads section) and applied via a data-sidebar-actions-inline attribute + one CSS rule — no prop threading through the row components. Adds countVisibleExpandedFolders helper + unit tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… rows Replace the "show row actions inline when only one container is expanded" rule with a simpler split that matches the intended design: - The primary section header (Projects in project mode, Folders in folder mode) always shows its actions. - Project rows, folder rows, the Threads header, and thread rows reveal their actions on hover. The old inline rule used a shared `.bb-sidebar-hover-actions` CSS override that leaked onto thread rows, forcing their actions visible whenever the sidebar was sparse. Removing it (plus the `data-sidebar-actions-inline` attr, `countVisibleExpandedFolders`, and its tests) fixes that and drops the complexity. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`folderPathSubtreeFilter` sized its SQLite `substr()` prefix with JS
`String.length` (UTF-16 code units), but `substr()` counts code points. A
folder named with a non-BMP character (e.g. an emoji) over-read the prefix, so
the `"${path}/"` comparison never matched its descendants — silently skipping
descendant folders/threads on rename and delete and orphaning their
`folder_path` values.
Size the prefix by the path's code-point length (`[...path].length`). Adds a
regression test covering rename + delete of emoji-named folders.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fd08688 to
9790a23
Compare
brsbl
added a commit
that referenced
this pull request
Jun 24, 2026
These are the non-folder changes split out of the nested-folders PR (#258), placed here so #258 is folder-only and nothing is dropped. Adapted to main's reworked sidebar (chevron/worktree-menu ProjectRow, ProjectActionsMenu). Search deep-link / scroll-to-message: - Expose ThreadSearchMatch.sourceSeq (db) + threadSearchMatchSchema.sourceSeq (contract); server already passes matches through. - useScrollToSearchedMessage + ThreadTimelineRows scroll hook, AppSidebar nav state (searchMessageSeq), SidebarThreadSearchPanel/sidebarThreadSearch messageSeq, app.css bb-search-flash, thread-search tests. - ThreadSearchResultRow redesign (+ story). Sidebar/menu interaction polish: - Row cursor/state-class affordances (sidebarRowClasses cursor-pointer + selected /70, ThreadRow grab cursor + dropped title tooltips, ProjectList + ProjectRow row classes), adapted to main's chevron (SidebarChildToggleChevron drops title props; callers updated). - Menu icons + label tweaks (ThreadActionsMenu Mail/Pin icons, "Mark read", separators) + rename payload refactor (ThreadActionsProvider/ThreadRenameDialog), PinnedThreadTree/ProjectListProjects/SidebarHistoryNavigationControls/ sortableMotion/ui sidebar tooltip + story-harness TooltipProvider. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
brsbl
added a commit
that referenced
this pull request
Jun 24, 2026
- Swap the worktree-style FolderGit icon for a plain Folder icon, matching the sidebar's project/folder iconography (avoids the worktree confusion). - Add an optional folderLabel prop: when the sidebar is organized by folder the caller passes the thread's folder path, shown in place of the project. Story adds an 'organized by folder' variant demonstrating title + folder. The live wiring (caller deriving folderLabel from Organize-by + thread.folderPath) lands when #258's folderPath merges in — that data is not on this branch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
brsbl
added a commit
that referenced
this pull request
Jun 24, 2026
These are the non-folder changes split out of the nested-folders PR (#258), placed here so #258 is folder-only and nothing is dropped. Adapted to main's reworked sidebar (chevron/worktree-menu ProjectRow, ProjectActionsMenu). Search deep-link / scroll-to-message: - Expose ThreadSearchMatch.sourceSeq (db) + threadSearchMatchSchema.sourceSeq (contract); server already passes matches through. - useScrollToSearchedMessage + ThreadTimelineRows scroll hook, AppSidebar nav state (searchMessageSeq), SidebarThreadSearchPanel/sidebarThreadSearch messageSeq, app.css bb-search-flash, thread-search tests. - ThreadSearchResultRow redesign (+ story). Sidebar/menu interaction polish: - Row cursor/state-class affordances (sidebarRowClasses cursor-pointer + selected /70, ThreadRow grab cursor + dropped title tooltips, ProjectList + ProjectRow row classes), adapted to main's chevron (SidebarChildToggleChevron drops title props; callers updated). - Menu icons + label tweaks (ThreadActionsMenu Mail/Pin icons, "Mark read", separators) + rename payload refactor (ThreadActionsProvider/ThreadRenameDialog), PinnedThreadTree/ProjectListProjects/SidebarHistoryNavigationControls/ sortableMotion/ui sidebar tooltip + story-harness TooltipProvider. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
brsbl
added a commit
that referenced
this pull request
Jun 24, 2026
- Swap the worktree-style FolderGit icon for a plain Folder icon, matching the sidebar's project/folder iconography (avoids the worktree confusion). - Add an optional folderLabel prop: when the sidebar is organized by folder the caller passes the thread's folder path, shown in place of the project. Story adds an 'organized by folder' variant demonstrating title + folder. The live wiring (caller deriving folderLabel from Organize-by + thread.folderPath) lands when #258's folderPath merges in — that data is not on this branch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
brsbl
added a commit
that referenced
this pull request
Jun 24, 2026
These are the non-folder changes split out of the nested-folders PR (#258), placed here so #258 is folder-only and nothing is dropped. Adapted to main's reworked sidebar (chevron/worktree-menu ProjectRow, ProjectActionsMenu). Search deep-link / scroll-to-message: - Expose ThreadSearchMatch.sourceSeq (db) + threadSearchMatchSchema.sourceSeq (contract); server already passes matches through. - useScrollToSearchedMessage + ThreadTimelineRows scroll hook, AppSidebar nav state (searchMessageSeq), SidebarThreadSearchPanel/sidebarThreadSearch messageSeq, app.css bb-search-flash, thread-search tests. - ThreadSearchResultRow redesign (+ story). Sidebar/menu interaction polish: - Row cursor/state-class affordances (sidebarRowClasses cursor-pointer + selected /70, ThreadRow grab cursor + dropped title tooltips, ProjectList + ProjectRow row classes), adapted to main's chevron (SidebarChildToggleChevron drops title props; callers updated). - Menu icons + label tweaks (ThreadActionsMenu Mail/Pin icons, "Mark read", separators) + rename payload refactor (ThreadActionsProvider/ThreadRenameDialog), PinnedThreadTree/ProjectListProjects/SidebarHistoryNavigationControls/ sortableMotion/ui sidebar tooltip + story-harness TooltipProvider. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
brsbl
added a commit
that referenced
this pull request
Jun 24, 2026
- Swap the worktree-style FolderGit icon for a plain Folder icon, matching the sidebar's project/folder iconography (avoids the worktree confusion). - Add an optional folderLabel prop: when the sidebar is organized by folder the caller passes the thread's folder path, shown in place of the project. Story adds an 'organized by folder' variant demonstrating title + folder. The live wiring (caller deriving folderLabel from Organize-by + thread.folderPath) lands when #258's folderPath merges in — that data is not on this branch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
brsbl
added a commit
that referenced
this pull request
Jun 24, 2026
These are the non-folder changes split out of the nested-folders PR (#258), placed here so #258 is folder-only and nothing is dropped. Adapted to main's reworked sidebar (chevron/worktree-menu ProjectRow, ProjectActionsMenu). Search deep-link / scroll-to-message: - Expose ThreadSearchMatch.sourceSeq (db) + threadSearchMatchSchema.sourceSeq (contract); server already passes matches through. - useScrollToSearchedMessage + ThreadTimelineRows scroll hook, AppSidebar nav state (searchMessageSeq), SidebarThreadSearchPanel/sidebarThreadSearch messageSeq, app.css bb-search-flash, thread-search tests. - ThreadSearchResultRow redesign (+ story). Sidebar/menu interaction polish: - Row cursor/state-class affordances (sidebarRowClasses cursor-pointer + selected /70, ThreadRow grab cursor + dropped title tooltips, ProjectList + ProjectRow row classes), adapted to main's chevron (SidebarChildToggleChevron drops title props; callers updated). - Menu icons + label tweaks (ThreadActionsMenu Mail/Pin icons, "Mark read", separators) + rename payload refactor (ThreadActionsProvider/ThreadRenameDialog), PinnedThreadTree/ProjectListProjects/SidebarHistoryNavigationControls/ sortableMotion/ui sidebar tooltip + story-harness TooltipProvider. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
brsbl
added a commit
that referenced
this pull request
Jun 24, 2026
- Swap the worktree-style FolderGit icon for a plain Folder icon, matching the sidebar's project/folder iconography (avoids the worktree confusion). - Add an optional folderLabel prop: when the sidebar is organized by folder the caller passes the thread's folder path, shown in place of the project. Story adds an 'organized by folder' variant demonstrating title + folder. The live wiring (caller deriving folderLabel from Organize-by + thread.folderPath) lands when #258's folderPath merges in — that data is not on this branch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
brsbl
added a commit
that referenced
this pull request
Jun 24, 2026
These are the non-folder changes split out of the nested-folders PR (#258), placed here so #258 is folder-only and nothing is dropped. Adapted to main's reworked sidebar (chevron/worktree-menu ProjectRow, ProjectActionsMenu). Search deep-link / scroll-to-message: - Expose ThreadSearchMatch.sourceSeq (db) + threadSearchMatchSchema.sourceSeq (contract); server already passes matches through. - useScrollToSearchedMessage + ThreadTimelineRows scroll hook, AppSidebar nav state (searchMessageSeq), SidebarThreadSearchPanel/sidebarThreadSearch messageSeq, app.css bb-search-flash, thread-search tests. - ThreadSearchResultRow redesign (+ story). Sidebar/menu interaction polish: - Row cursor/state-class affordances (sidebarRowClasses cursor-pointer + selected /70, ThreadRow grab cursor + dropped title tooltips, ProjectList + ProjectRow row classes), adapted to main's chevron (SidebarChildToggleChevron drops title props; callers updated). - Menu icons + label tweaks (ThreadActionsMenu Mail/Pin icons, "Mark read", separators) + rename payload refactor (ThreadActionsProvider/ThreadRenameDialog), PinnedThreadTree/ProjectListProjects/SidebarHistoryNavigationControls/ sortableMotion/ui sidebar tooltip + story-harness TooltipProvider. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
brsbl
added a commit
that referenced
this pull request
Jun 24, 2026
- Swap the worktree-style FolderGit icon for a plain Folder icon, matching the sidebar's project/folder iconography (avoids the worktree confusion). - Add an optional folderLabel prop: when the sidebar is organized by folder the caller passes the thread's folder path, shown in place of the project. Story adds an 'organized by folder' variant demonstrating title + folder. The live wiring (caller deriving folderLabel from Organize-by + thread.folderPath) lands when #258's folderPath merges in — that data is not on this branch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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
Adds thread folders to the sidebar — group personal threads into folders via a dedicated Folders organization mode — and reworks the sidebar's view‑options and archived surfaces to use shared components with variants, so the project view and folders view can't drift. Built on the otto‑s1 spec, then refined across QA.
Folders
…menu with View archived threads / Rename / Remove.Organize & Sort menus
Archived views
ArchivedThreadsViewfor every scope (project / personal‑loose / folder); the scope shows in theAppLayoutbreadcrumb (Threads › <folder> › Archived), not a bespoke in‑body heading./archived?folder=…). The personal/loose list now excludes foldered threads via a newunfiledfilter. Menu items renamed to "View archived threads".Shared components (the no‑duplication goal)
ManualThreadTreeItems— the single place that maps tree items to rows for every view (project, chronological, folders), plusThreadTreeLoadingSkeleton.SidebarDisplayOptionsActions+SidebarThreadsSectionActions— shared header action clusters used by both modes.ArchivedThreadsView+ breadcrumb variants for the archived pages.Other polish
…/+).Server / data
folderPathandunfiledfilters on the thread‑list query, threaded contract → route → db, with db regression tests.Testing
typecheck(30/30),lint, andprettier --checkclean.sortComparator(sort direction + leaf/folder consistency) and dbfolderPath/unfiledfilter tests.Notes
🤖 Generated with Claude Code