From 9fce8b095e2ce529220d4cdd003deebad464e6f5 Mon Sep 17 00:00:00 2001 From: Akshar Patel Date: Sat, 5 Sep 2026 15:45:12 -0400 Subject: [PATCH] perf(web): speed up folder menu sorting --- apps/web/src/components/files/filePath.test.ts | 11 +++++++++-- apps/web/src/components/files/filePath.ts | 4 +++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/apps/web/src/components/files/filePath.test.ts b/apps/web/src/components/files/filePath.test.ts index 3018aa91a776..b501562fee00 100644 --- a/apps/web/src/components/files/filePath.test.ts +++ b/apps/web/src/components/files/filePath.test.ts @@ -67,8 +67,15 @@ describe("fileBreadcrumbChildren", () => { ]); }); - it("uses natural file-name ordering", () => { - expect(fileBreadcrumbChildren(entries, "src/lib").map((entry) => entry.label)).toEqual([ + it("uses natural file-name ordering and preserves input order for equivalent names", () => { + const files = ["file10.ts", "File2.ts", "file02.ts", "file2.ts"].map((name) => ({ + path: `src/lib/${name}`, + kind: "file" as const, + })); + + expect(fileBreadcrumbChildren(files, "src/lib").map((entry) => entry.label)).toEqual([ + "File2.ts", + "file02.ts", "file2.ts", "file10.ts", ]); diff --git a/apps/web/src/components/files/filePath.ts b/apps/web/src/components/files/filePath.ts index aea8266ec8b8..e819315310b8 100644 --- a/apps/web/src/components/files/filePath.ts +++ b/apps/web/src/components/files/filePath.ts @@ -36,6 +36,7 @@ export function fileBreadcrumbChildren( entries: readonly ProjectEntry[], directoryPath: string, ): FileBreadcrumbChild[] { + let collator: Intl.Collator | undefined; const prefix = directoryPath ? `${directoryPath}/` : ""; return entries .flatMap((entry) => { @@ -46,10 +47,11 @@ export function fileBreadcrumbChildren( }) .toSorted((left, right) => { if (left.kind !== right.kind) return left.kind === "directory" ? -1 : 1; - return left.label.localeCompare(right.label, undefined, { + collator ??= new Intl.Collator(undefined, { numeric: true, sensitivity: "base", }); + return collator.compare(left.label, right.label); }); }