From 4e49dae4f219e0b56cb9c1a23d2ac985cde0c46a Mon Sep 17 00:00:00 2001 From: Abarnaa Sree Date: Sun, 9 Aug 2026 14:45:16 +0530 Subject: [PATCH 1/2] feat(trees): add flattened segment truncation option --- packages/trees/src/model/publicTypes.ts | 6 +----- packages/trees/src/render/FileTree.ts | 11 ++++++++++- packages/trees/src/render/FileTreeView.tsx | 19 ++++++++++++++++--- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/packages/trees/src/model/publicTypes.ts b/packages/trees/src/model/publicTypes.ts index e43cd6fba..33d6029ad 100644 --- a/packages/trees/src/model/publicTypes.ts +++ b/packages/trees/src/model/publicTypes.ts @@ -142,17 +142,13 @@ export interface FileTreeDirectoryHandle extends FileTreeItemHandleBase { export interface FileTreeFileHandle extends FileTreeItemHandleBase { isDirectory(): false; } - export type FileTreeItemHandle = FileTreeDirectoryHandle | FileTreeFileHandle; - export interface FileTreeRenderOptions { - // Hint how many rows should fit in the first render before the browser can - // measure the real scroll viewport. Fractional values are allowed when the - // desired first-render budget is not an exact multiple of itemHeight. initialVisibleRowCount?: number; itemHeight?: number; overscan?: number; stickyFolders?: boolean; + flattenedSegmentsTruncation?: 'per-segment' | 'end'; } export type FileTreeScrollOffset = 'top' | 'center' | 'nearest'; diff --git a/packages/trees/src/render/FileTree.ts b/packages/trees/src/render/FileTree.ts index 3948e3c77..e448084ee 100644 --- a/packages/trees/src/render/FileTree.ts +++ b/packages/trees/src/render/FileTree.ts @@ -190,7 +190,11 @@ export class FileTree readonly #density: FileTreeDensityPreset; readonly #viewOptions: Pick< FileTreeOptions, - 'initialVisibleRowCount' | 'itemHeight' | 'overscan' | 'stickyFolders' + | 'initialVisibleRowCount' + | 'itemHeight' + | 'overscan' + | 'stickyFolders' + | 'flattenedSegmentsTruncation' >; #fileTreeContainer: HTMLElement | undefined; #gitStatusState: FileTreeGitStatusState | null; @@ -229,6 +233,7 @@ export class FileTree searchFakeFocus, stickyFolders, unsafeCSS, + flattenedSegmentsTruncation, initialVisibleRowCount, ...controllerOptions } = options; @@ -249,6 +254,7 @@ export class FileTree overscan, stickyFolders, initialVisibleRowCount, + flattenedSegmentsTruncation, }; this.#controller = new FileTreeController({ ...controllerOptions, @@ -561,6 +567,7 @@ export class FileTree itemHeight?: number; overscan?: number; stickyFolders?: boolean; + flattenedSegmentsTruncation?: 'per-segment' | 'end'; } { return { initialViewportHeight: resolveInitialViewportHeight({ @@ -570,6 +577,8 @@ export class FileTree itemHeight: this.#viewOptions.itemHeight, overscan: this.#viewOptions.overscan, stickyFolders: this.#viewOptions.stickyFolders, + flattenedSegmentsTruncation: + this.#viewOptions.flattenedSegmentsTruncation, }; } diff --git a/packages/trees/src/render/FileTreeView.tsx b/packages/trees/src/render/FileTreeView.tsx index 0d3cbab06..8ee1f23b7 100644 --- a/packages/trees/src/render/FileTreeView.tsx +++ b/packages/trees/src/render/FileTreeView.tsx @@ -78,7 +78,8 @@ import { function formatFlattenedSegments( row: FileTreeVisibleRow, renameInput: JSX.Element | null = null, - dragTargetFlattenedSegmentPath: string | null = null + dragTargetFlattenedSegmentPath: string | null = null, + flattenedSegmentsTruncation: 'per-segment' | 'end' = 'per-segment' ): JSX.Element | string { 'use no memo'; const segments = row.flattenedSegments; @@ -86,7 +87,11 @@ function formatFlattenedSegments( return renameInput ?? row.name; } - return ( + return flattenedSegmentsTruncation === 'end' ? ( + + {segments.map((segment) => segment.name).join(' / ')} + + ) : ( {segments.map((segment, index) => { const isLast = index === segments.length - 1; @@ -848,6 +853,7 @@ function renderFileTreeRowContent( gitLaneActive = false, renameInput = null, showDecorativeActionAffordance = false, + flattenedSegmentsTruncation = 'per-segment', }: { actionLaneEnabled?: boolean; customDecoration?: FileTreeRowDecoration | null; @@ -857,6 +863,7 @@ function renderFileTreeRowContent( gitLaneActive?: boolean; renameInput?: JSX.Element | null; showDecorativeActionAffordance?: boolean; + flattenedSegmentsTruncation?: 'per-segment' | 'end'; } = {} ): JSX.Element { const targetPath = getFileTreeRowPath(row); @@ -886,7 +893,8 @@ function renderFileTreeRowContent( ? formatFlattenedSegments( row, renameInput, - dragTargetFlattenedSegmentPath + dragTargetFlattenedSegmentPath, + flattenedSegmentsTruncation ) : (renameInput ?? ( @@ -929,6 +937,7 @@ type FileTreeRenderedRowMode = FileTreeRowClickMode; // with a different `registerButton` target. type FileTreeRenderRowFrame = { controller: FileTreeController; + flattenedSegmentsTruncation: 'per-segment' | 'end'; renameView: ReturnType; visualFocusPath: string | null; contextHoverPath: string | null; @@ -999,6 +1008,7 @@ function renderStyledRow( ): JSX.Element { const { controller, + flattenedSegmentsTruncation, renameView, visualFocusPath, contextHoverPath, @@ -1077,6 +1087,7 @@ function renderStyledRow( customDecoration, decorationLaneEnabled, dragTargetFlattenedSegmentPath: dragTarget?.flattenedSegmentPath ?? null, + flattenedSegmentsTruncation, gitDecoration, gitLaneActive, renameInput, @@ -1239,6 +1250,7 @@ export function FileTreeView({ searchFakeFocus = false, slotHost, stickyFolders = false, + flattenedSegmentsTruncation = 'per-segment', initialViewportHeight = FILE_TREE_DEFAULT_VIEWPORT_HEIGHT, }: FileTreeViewProps): JSX.Element { 'use no memo'; @@ -3636,6 +3648,7 @@ export function FileTreeView({ contextMenuRightClickEnabled, contextMenuTriggerMode, controller, + flattenedSegmentsTruncation, directoriesWithGitChanges, dragAndDropEnabled, draggedPathSet, From 54a7b4dc5ae5b95275cbbad1d7f9f9e92980fa1a Mon Sep 17 00:00:00 2001 From: Abarnaa Sree Date: Sun, 9 Aug 2026 23:20:40 +0530 Subject: [PATCH 2/2] feat(trees): add flattened segment truncation option --- packages/trees/src/render/FileTree.ts | 6 ++++-- packages/trees/src/render/FileTreeView.tsx | 8 +++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/trees/src/render/FileTree.ts b/packages/trees/src/render/FileTree.ts index e448084ee..9080a8b7e 100644 --- a/packages/trees/src/render/FileTree.ts +++ b/packages/trees/src/render/FileTree.ts @@ -233,8 +233,8 @@ export class FileTree searchFakeFocus, stickyFolders, unsafeCSS, - flattenedSegmentsTruncation, initialVisibleRowCount, + flattenedSegmentsTruncation, ...controllerOptions } = options; this.#composition = composition; @@ -253,8 +253,8 @@ export class FileTree itemHeight: this.#density.itemHeight, overscan, stickyFolders, - initialVisibleRowCount, flattenedSegmentsTruncation, + initialVisibleRowCount, }; this.#controller = new FileTreeController({ ...controllerOptions, @@ -886,6 +886,7 @@ export function preloadFileTree(options: FileTreeOptions): FileTreeSsrPayload { searchFakeFocus, stickyFolders, unsafeCSS, + flattenedSegmentsTruncation, initialVisibleRowCount, ...controllerOptions } = options; @@ -934,6 +935,7 @@ export function preloadFileTree(options: FileTreeOptions): FileTreeSsrPayload { searchEnabled: search === true, searchFakeFocus: searchFakeFocus === true, stickyFolders, + flattenedSegmentsTruncation, initialViewportHeight, }) ); diff --git a/packages/trees/src/render/FileTreeView.tsx b/packages/trees/src/render/FileTreeView.tsx index 8ee1f23b7..ecf68afc7 100644 --- a/packages/trees/src/render/FileTreeView.tsx +++ b/packages/trees/src/render/FileTreeView.tsx @@ -88,9 +88,11 @@ function formatFlattenedSegments( } return flattenedSegmentsTruncation === 'end' ? ( - - {segments.map((segment) => segment.name).join(' / ')} - + (renameInput ?? ( + + {segments.map((segment) => segment.name).join(' / ')} + + )) ) : ( {segments.map((segment, index) => {