From 3e33bac42627eedf457dc260577fc991ca0662c3 Mon Sep 17 00:00:00 2001 From: Jokin Date: Sat, 11 Jul 2026 17:33:52 +0200 Subject: [PATCH] Drag & drop tab reordering Tabs are draggable within the strip: HTML5 DnD with the WebKit setData quirk handled, an inset primary insertion line at the drop position (no layout shift), and the dragged tab dimmed. Reordering only touches the workspaces array order; ids, sessions, and the active tab are unaffected. Co-Authored-By: Claude Fable 5 --- ui/src/app/panels.service.ts | 12 ++++++++ ui/src/app/tab-bar/tab-bar.ts | 57 ++++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 1 deletion(-) 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) {