diff --git a/ui/src/app/panels.service.ts b/ui/src/app/panels.service.ts
index 93e63bb..e172c9c 100644
--- a/ui/src/app/panels.service.ts
+++ b/ui/src/app/panels.service.ts
@@ -274,6 +274,18 @@ export class PanelsService {
}
}
+ /** Reorder a tab (drag & drop). Order is purely visual; ids stay stable. */
+ moveWorkspace(id: number, toIndex: number): void {
+ this.workspaces.update((list) => {
+ const fromIndex = list.findIndex((w) => w.id === id);
+ if (fromIndex < 0) return list;
+ const next = [...list];
+ const [moved] = next.splice(fromIndex, 1);
+ next.splice(Math.max(0, Math.min(next.length, toIndex)), 0, moved);
+ return next;
+ });
+ }
+
cycleWorkspace(delta: 1 | -1): void {
const list = this.workspaces();
if (list.length < 2) return;
diff --git a/ui/src/app/tab-bar/tab-bar.ts b/ui/src/app/tab-bar/tab-bar.ts
index 406e951..bb1384f 100644
--- a/ui/src/app/tab-bar/tab-bar.ts
+++ b/ui/src/app/tab-bar/tab-bar.ts
@@ -26,10 +26,17 @@ const CONCURRENCY_CHOICES = [2, 3, 4, 6, 8] as const;
[class.pl-1.5]="!isMacChrome"
[class.pt-1]="!isMacChrome"
>
- @for (ws of panels.workspaces(); track ws.id) {
+ @for (ws of panels.workspaces(); track ws.id; let i = $index) {