|
10 | 10 | </head> |
11 | 11 | <body class="font-['Inter',system-ui,sans-serif] bg-surface text-text-primary m-0 p-0 overflow-hidden flex h-full"> |
12 | 12 | <aside class="w-64 bg-surface-elevated border-r border-border flex flex-col h-full z-10"> |
13 | | - <div class="p-6 border-b border-border"> |
| 13 | + <div class="px-2 pt-5 pb-4 border-b border-border"> |
| 14 | + <div class="px-2.5"> |
14 | 15 | <h1 class="text-lg font-bold tracking-tight mb-1 flex items-center gap-2"> |
15 | 16 | <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-accent" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"/><line x1="3" x2="21" y1="9" y2="9"/><line x1="9" x2="9" y1="21" y2="9"/></svg> |
16 | 17 | Tab Manager |
17 | 18 | </h1> |
18 | 19 | <div class="text-[11px] text-text-muted font-medium">Never get lost in your tabs again</div> |
| 20 | + </div> |
19 | 21 | </div> |
20 | 22 |
|
21 | 23 | <div class="flex-1 overflow-y-auto custom-scrollbar p-2 space-y-1" id="window-list"> |
22 | | - <div id="window-list-windows" class="min-h-[7.5rem]"> |
23 | | - <!-- Placeholder to prevent layout shift when Windows load; replaced by renderSidebar() --> |
24 | | - <div class="sidebar-item w-full text-left px-3 py-2 rounded-md mb-1 flex items-center justify-between text-text-muted opacity-60" aria-hidden="true"> |
| 24 | + <div id="window-list-windows" class="min-h-[13.5rem]"> |
| 25 | + <!-- Placeholders reserve space before renderSidebar() / saved sessions load --> |
| 26 | + <div class="sidebar-item w-full text-left px-2.5 py-2 rounded-md mb-1 flex items-center justify-between text-text-muted opacity-60 min-h-[2.25rem]" aria-hidden="true"> |
25 | 27 | <span class="text-xs font-semibold">All Windows</span> |
26 | | - <span class="text-[10px] bg-surface-elevated border border-border px-1.5 rounded-full">—</span> |
| 28 | + <span class="text-[10px] bg-surface-elevated border border-border px-1.5 rounded-full tabular-nums">—</span> |
27 | 29 | </div> |
28 | | - <div class="w-full px-3 py-2 rounded-md mb-1 flex items-center justify-between text-text-muted opacity-40" aria-hidden="true"> |
29 | | - <div class="h-4 w-24 rounded bg-surface-elevated/50 animate-pulse"></div> |
30 | | - <span class="text-[10px] bg-surface-elevated/50 px-1.5 rounded-full">—</span> |
| 30 | + <div class="w-full px-2.5 py-2 rounded-md mb-1 flex items-center justify-between text-text-muted opacity-40 min-h-[2.75rem]" aria-hidden="true"> |
| 31 | + <div class="min-w-0 flex-1 pr-2"> |
| 32 | + <div class="h-3.5 w-20 rounded bg-surface-elevated/50 animate-pulse mb-1"></div> |
| 33 | + <div class="h-2.5 w-14 rounded bg-surface-elevated/40 animate-pulse"></div> |
| 34 | + </div> |
| 35 | + <span class="text-[10px] bg-surface-elevated/50 px-1.5 rounded-full tabular-nums">—</span> |
| 36 | + </div> |
| 37 | + <div class="w-full px-2.5 py-2 rounded-md mb-1 flex items-center justify-between text-text-muted opacity-40 min-h-[2.75rem]" aria-hidden="true"> |
| 38 | + <div class="min-w-0 flex-1 pr-2"> |
| 39 | + <div class="h-3.5 w-20 rounded bg-surface-elevated/50 animate-pulse mb-1"></div> |
| 40 | + <div class="h-2.5 w-14 rounded bg-surface-elevated/40 animate-pulse"></div> |
| 41 | + </div> |
| 42 | + <span class="text-[10px] bg-surface-elevated/50 px-1.5 rounded-full tabular-nums">—</span> |
| 43 | + </div> |
| 44 | + <div class="w-full px-2.5 py-2 rounded-md mb-1 flex items-center justify-between text-text-muted opacity-40 min-h-[2.75rem]" aria-hidden="true"> |
| 45 | + <div class="min-w-0 flex-1 pr-2"> |
| 46 | + <div class="h-3.5 w-20 rounded bg-surface-elevated/50 animate-pulse mb-1"></div> |
| 47 | + <div class="h-2.5 w-14 rounded bg-surface-elevated/40 animate-pulse"></div> |
| 48 | + </div> |
| 49 | + <span class="text-[10px] bg-surface-elevated/50 px-1.5 rounded-full tabular-nums">—</span> |
| 50 | + </div> |
| 51 | + </div> |
| 52 | + <div class="h-px bg-border my-2.5"></div> |
| 53 | + <div class="px-2.5 py-1.5 mb-1 text-[10px] uppercase font-bold text-text-muted tracking-wider">Saved</div> |
| 54 | + <div class="px-2.5 mb-1.5"> |
| 55 | + <input type="text" id="session-sidebar-search" class="w-full px-2.5 py-1.5 text-[11px] border border-border rounded-md bg-surface text-text-primary placeholder:text-text-muted focus:outline-none focus:border-text-muted" placeholder="Filter sessions…" /> |
| 56 | + </div> |
| 57 | + <div id="saved-sessions-sidebar" class="space-y-1 min-h-[10.5rem]" aria-busy="true"> |
| 58 | + <div class="sidebar-session-skeleton w-full px-2.5 py-2 rounded-md mb-1 min-h-[3.25rem] flex items-center opacity-40" aria-hidden="true"> |
| 59 | + <div class="min-w-0 flex-1"> |
| 60 | + <div class="h-3.5 w-32 max-w-[85%] rounded bg-surface-elevated/50 animate-pulse mb-1"></div> |
| 61 | + <div class="h-2.5 w-24 max-w-[65%] rounded bg-surface-elevated/40 animate-pulse"></div> |
| 62 | + </div> |
| 63 | + </div> |
| 64 | + <div class="sidebar-session-skeleton w-full px-2.5 py-2 rounded-md mb-1 min-h-[3.25rem] flex items-center opacity-40" aria-hidden="true"> |
| 65 | + <div class="min-w-0 flex-1"> |
| 66 | + <div class="h-3.5 w-32 max-w-[85%] rounded bg-surface-elevated/50 animate-pulse mb-1"></div> |
| 67 | + <div class="h-2.5 w-24 max-w-[65%] rounded bg-surface-elevated/40 animate-pulse"></div> |
| 68 | + </div> |
| 69 | + </div> |
| 70 | + <div class="sidebar-session-skeleton w-full px-2.5 py-2 rounded-md mb-1 min-h-[3.25rem] flex items-center opacity-40" aria-hidden="true"> |
| 71 | + <div class="min-w-0 flex-1"> |
| 72 | + <div class="h-3.5 w-32 max-w-[85%] rounded bg-surface-elevated/50 animate-pulse mb-1"></div> |
| 73 | + <div class="h-2.5 w-24 max-w-[65%] rounded bg-surface-elevated/40 animate-pulse"></div> |
| 74 | + </div> |
31 | 75 | </div> |
32 | 76 | </div> |
33 | | - <div class="h-px bg-border my-2 mx-2"></div> |
34 | | - <div class="px-2 py-1 text-[10px] uppercase font-bold text-text-muted tracking-wider">Saved</div> |
35 | | - <div id="saved-sessions-sidebar" class="space-y-1"></div> |
36 | 77 | </div> |
37 | 78 |
|
38 | | - <div class="p-4 border-t border-border mt-auto"> |
39 | | - <div class="flex items-center justify-between text-xs text-text-muted"> |
40 | | - <span id="global-stats-count">Loading...</span> |
| 79 | + <div class="px-2 py-3 border-t border-border mt-auto shrink-0"> |
| 80 | + <div class="px-2.5 flex items-center justify-between text-xs text-text-muted min-h-[1rem]"> |
| 81 | + <span id="global-stats-count" class="tabular-nums whitespace-nowrap">0 videos · 00:00:00</span> |
41 | 82 | </div> |
42 | 83 | </div> |
43 | 84 | </aside> |
@@ -180,6 +221,17 @@ <h3 class="text-lg font-bold text-text-primary mb-4">Settings</h3> |
180 | 221 | </div> |
181 | 222 | </div> |
182 | 223 |
|
| 224 | + <div class="pt-4 border-t border-border"> |
| 225 | + <div class="text-[10px] uppercase font-bold text-text-muted tracking-wider mb-2">Saved sessions</div> |
| 226 | + <div class="flex gap-2"> |
| 227 | + <button type="button" id="btn-export-sessions" class="flex-1 px-3 py-2 text-xs font-medium rounded-md border border-border bg-surface-hover hover:bg-surface text-text-secondary hover:text-text-primary transition-colors cursor-pointer active:scale-[0.96]">Export JSON</button> |
| 228 | + <label class="flex-1 px-3 py-2 text-xs font-medium rounded-md border border-border bg-surface-hover hover:bg-surface text-text-secondary hover:text-text-primary transition-colors cursor-pointer text-center active:scale-[0.96]"> |
| 229 | + Import |
| 230 | + <input type="file" id="import-sessions-file" accept="application/json,.json" class="hidden" /> |
| 231 | + </label> |
| 232 | + </div> |
| 233 | + </div> |
| 234 | + |
183 | 235 | <div class="pt-4 border-t border-border"> |
184 | 236 | <button id="btn-clear-cache" class="w-full text-left px-4 py-3 rounded-lg border border-border bg-surface-hover/20 hover:bg-red-500/10 hover:border-red-500 group/clear transition-[background-color,border-color,color]"> |
185 | 237 | <div class="flex items-center justify-between"> |
@@ -211,7 +263,52 @@ <h3 class="text-lg font-bold text-text-primary mb-4">Settings</h3> |
211 | 263 | </div> |
212 | 264 | </div> |
213 | 265 |
|
214 | | - <!-- Name session modal (replaces browser prompt) --> |
| 266 | + <!-- Save session modal --> |
| 267 | + <div id="save-session-modal" class="hidden fixed inset-0 z-[55] bg-black/60 backdrop-blur-sm" aria-modal="true" role="dialog" aria-labelledby="save-session-title"> |
| 268 | + <div class="bg-surface-elevated border border-border rounded-lg shadow-xl w-full max-w-md p-5 mx-4 animate-in zoom-in-95 duration-200"> |
| 269 | + <h3 id="save-session-title" class="text-lg font-bold text-text-primary mb-2">Save session</h3> |
| 270 | + <p id="save-session-summary" class="text-xs text-text-muted mb-3"></p> |
| 271 | + <label for="save-session-input" class="text-[10px] uppercase font-bold text-text-muted tracking-wider">Name</label> |
| 272 | + <input type="text" id="save-session-input" class="w-full px-3 py-2 mt-1 mb-4 text-sm border border-border rounded-md bg-surface text-text-primary placeholder:text-text-muted focus:outline-none focus:border-text-muted" placeholder="Session name" /> |
| 273 | + <div id="save-session-options" class="space-y-3 mb-4"> |
| 274 | + <div class="text-[10px] uppercase font-bold text-text-muted tracking-wider">Action</div> |
| 275 | + <label class="flex items-center gap-2 text-sm text-text-secondary cursor-pointer"><input type="radio" name="save-session-mode" value="new" class="accent-accent" checked /> Save as new session</label> |
| 276 | + <label class="flex items-center gap-2 text-sm text-text-secondary cursor-pointer"><input type="radio" name="save-session-mode" value="replace" class="accent-accent" /> Replace existing session</label> |
| 277 | + <label class="flex items-center gap-2 text-sm text-text-secondary cursor-pointer"><input type="radio" name="save-session-mode" value="merge" class="accent-accent" /> Merge into existing session</label> |
| 278 | + <select id="save-session-target" class="hidden w-full mt-1 px-3 py-2 text-sm border border-border rounded-md bg-surface text-text-primary focus:outline-none focus:border-text-muted"></select> |
| 279 | + <p id="save-session-duplicate-hint" class="hidden text-xs text-accent leading-relaxed"></p> |
| 280 | + </div> |
| 281 | + <div class="flex justify-end gap-2"> |
| 282 | + <button type="button" id="save-session-cancel" class="px-4 py-2 text-sm font-medium rounded-md border border-border bg-surface-hover text-text-primary hover:bg-surface transition-colors cursor-pointer active:scale-[0.96]">Cancel</button> |
| 283 | + <button type="button" id="save-session-confirm" class="px-4 py-2 text-sm font-medium rounded-md border-0 bg-accent text-white hover:opacity-90 cursor-pointer transition-opacity active:scale-[0.96]">Save</button> |
| 284 | + </div> |
| 285 | + </div> |
| 286 | + </div> |
| 287 | + |
| 288 | + <!-- Restore session modal --> |
| 289 | + <div id="restore-session-modal" class="hidden fixed inset-0 z-[55] bg-black/60 backdrop-blur-sm" aria-modal="true" role="dialog" aria-labelledby="restore-session-title"> |
| 290 | + <div class="bg-surface-elevated border border-border rounded-lg shadow-xl w-full max-w-md p-5 mx-4 animate-in zoom-in-95 duration-200"> |
| 291 | + <h3 id="restore-session-title" class="text-lg font-bold text-text-primary mb-2">Open session</h3> |
| 292 | + <p id="restore-session-summary" class="text-xs text-text-muted mb-4"></p> |
| 293 | + <div class="space-y-3 mb-5"> |
| 294 | + <div> |
| 295 | + <label for="restore-target-window" class="text-[10px] uppercase font-bold text-text-muted tracking-wider">Open in</label> |
| 296 | + <select id="restore-target-window" class="w-full mt-1 px-3 py-2 text-sm border border-border rounded-md bg-surface text-text-primary focus:outline-none focus:border-text-muted"> |
| 297 | + <option value="new">New window</option> |
| 298 | + <option value="current">Current window</option> |
| 299 | + </select> |
| 300 | + </div> |
| 301 | + <label class="flex items-center gap-2 text-sm text-text-secondary cursor-pointer"><input type="checkbox" id="restore-missing-only" class="accent-accent rounded" /> Open only tabs not already open</label> |
| 302 | + <label class="flex items-center gap-2 text-sm text-text-secondary cursor-pointer"><input type="checkbox" id="restore-by-sections" class="accent-accent rounded" /> One window per section (when sections exist)</label> |
| 303 | + </div> |
| 304 | + <div class="flex justify-end gap-2"> |
| 305 | + <button type="button" id="restore-session-cancel" class="px-4 py-2 text-sm font-medium rounded-md border border-border bg-surface-hover text-text-primary hover:bg-surface transition-colors cursor-pointer active:scale-[0.96]">Cancel</button> |
| 306 | + <button type="button" id="restore-session-confirm" class="px-4 py-2 text-sm font-medium rounded-md border-0 bg-accent text-white hover:opacity-90 cursor-pointer transition-opacity active:scale-[0.96]">Open tabs</button> |
| 307 | + </div> |
| 308 | + </div> |
| 309 | + </div> |
| 310 | + |
| 311 | + <!-- Name session modal (rename / section rename) --> |
215 | 312 | <div id="name-session-modal" class="hidden fixed inset-0 z-[55] bg-black/60 backdrop-blur-sm" aria-modal="true" role="dialog" aria-labelledby="name-session-title"> |
216 | 313 | <div class="bg-surface-elevated border border-border rounded-lg shadow-xl w-full max-w-sm p-5 mx-4 animate-in zoom-in-95 duration-200"> |
217 | 314 | <h3 id="name-session-title" class="text-lg font-bold text-text-primary mb-2">Name this session</h3> |
@@ -283,7 +380,15 @@ <h3 id="add-section-title" class="font-['Syne',sans-serif] text-xl font-semibold |
283 | 380 | </button> |
284 | 381 | <button type="button" id="ctx-open-tabs" class="sidebar-ctx-item hidden w-full text-left px-4 py-2 items-center gap-2 hover:bg-surface-hover text-text-primary border-0 bg-transparent cursor-pointer"> |
285 | 382 | <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/></svg> |
286 | | - Open in New Window |
| 383 | + Open tabs… |
| 384 | + </button> |
| 385 | + <button type="button" id="ctx-add-to-session" class="sidebar-ctx-item hidden w-full text-left px-4 py-2 items-center gap-2 hover:bg-surface-hover text-text-primary border-0 bg-transparent cursor-pointer"> |
| 386 | + <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14"/><path d="M5 12h14"/></svg> |
| 387 | + Add current tabs |
| 388 | + </button> |
| 389 | + <button type="button" id="ctx-duplicate-session" class="sidebar-ctx-item hidden w-full text-left px-4 py-2 items-center gap-2 hover:bg-surface-hover text-text-primary border-0 bg-transparent cursor-pointer"> |
| 390 | + <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect width="14" height="14" x="8" y="8" rx="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg> |
| 391 | + Duplicate |
287 | 392 | </button> |
288 | 393 | <button type="button" id="ctx-rename-session" class="sidebar-ctx-item hidden w-full text-left px-4 py-2 items-center gap-2 hover:bg-surface-hover text-text-primary border-0 bg-transparent cursor-pointer"> |
289 | 394 | <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/></svg> |
|
0 commit comments