claude-code-kanban 4.16.0 → 4.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/public/index.html CHANGED
@@ -56,10 +56,58 @@
56
56
  <!-- Tasks -->
57
57
  <div class="sidebar-section flex-1">
58
58
  <div class="section-header" onclick="toggleSection('sessions-filters', 'sessions-chevron')" style="cursor: pointer;">
59
- <span>Sessions</span>
60
- <svg id="sessions-chevron" class="collapse-chevron" viewBox="0 0 24 24">
61
- <path d="M6 9l6 6 6-6"/>
62
- </svg>
59
+ <span class="section-header-label">Sessions</span>
60
+ <span id="filter-summary" class="filter-summary" title=""></span>
61
+ <span class="section-header-actions">
62
+ <button
63
+ id="filter-menu-btn"
64
+ class="icon-btn section-btn"
65
+ onclick="toggleFilterMenu(event)"
66
+ title="Filters"
67
+ aria-label="Filters"
68
+ aria-haspopup="true"
69
+ aria-expanded="false"
70
+ >
71
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
72
+ <path d="M20 4H4l6.5 8v6l3 2v-8L20 4z"/>
73
+ </svg>
74
+ </button>
75
+ <button
76
+ class="icon-btn section-btn"
77
+ onclick="event.stopPropagation(); resetState()"
78
+ title="Reset filters and clear selection"
79
+ aria-label="Reset filters and clear selection"
80
+ >
81
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
82
+ <path d="M3 2v6h6"/>
83
+ <path d="M3.51 15a9 9 0 1 0 2.13-9.36L3 8"/>
84
+ </svg>
85
+ </button>
86
+ <svg id="sessions-chevron" class="collapse-chevron" viewBox="0 0 24 24">
87
+ <path d="M6 9l6 6 6-6"/>
88
+ </svg>
89
+ </span>
90
+ <div id="filter-menu" class="filter-menu" onclick="event.stopPropagation()">
91
+ <div class="filter-row">
92
+ <select id="project-filter" class="filter-dropdown" onchange="filterByProject(this.value)" aria-label="Filter by project">
93
+ <option value="">All Projects</option>
94
+ </select>
95
+ </div>
96
+ <div class="filter-row">
97
+ <select id="session-filter" class="filter-dropdown" onchange="filterBySessions(this.value)" aria-label="Filter by session status">
98
+ <option value="all">All Sessions</option>
99
+ <option value="active">Active Only</option>
100
+ </select>
101
+ </div>
102
+ <div class="filter-row">
103
+ <select id="session-limit" class="filter-dropdown" onchange="changeSessionLimit(this.value)" aria-label="Number of sessions to show">
104
+ <option value="10">Show 10</option>
105
+ <option value="20">Show 20</option>
106
+ <option value="50">Show 50</option>
107
+ <option value="all">Show All</option>
108
+ </select>
109
+ </div>
110
+ </div>
63
111
  </div>
64
112
  <div id="sessions-filters" class="collapsible-section">
65
113
  <div class="search-container">
@@ -76,29 +124,6 @@
76
124
  </svg>
77
125
  </button>
78
126
  </div>
79
- <div class="filter-row">
80
- <select id="project-filter" class="filter-dropdown" onchange="filterByProject(this.value)" aria-label="Filter by project">
81
- <option value="">All Projects</option>
82
- </select>
83
- <select id="session-filter" class="filter-dropdown" onchange="filterBySessions(this.value)" aria-label="Filter by session status">
84
- <option value="all">All Sessions</option>
85
- <option value="active">Active Only</option>
86
- </select>
87
- </div>
88
- <div class="filter-row">
89
- <select id="session-limit" class="filter-dropdown" onchange="changeSessionLimit(this.value)" aria-label="Number of sessions to show">
90
- <option value="10">Show 10</option>
91
- <option value="20">Show 20</option>
92
- <option value="50">Show 50</option>
93
- <option value="all">Show All</option>
94
- </select>
95
- <button class="icon-btn reset-btn" onclick="resetState()" title="Reset all filters" aria-label="Reset all filters">
96
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16">
97
- <path d="M3 12a9 9 0 1 1 9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/>
98
- <path d="M3 22v-6h6"/>
99
- </svg>
100
- </button>
101
- </div>
102
127
  </div>
103
128
  <div id="sessions-list" class="sessions-list"></div>
104
129
  </div>
@@ -276,7 +301,7 @@
276
301
  <button class="icon-btn" aria-label="Open in editor" title="Open in editor" onclick="openMsgInEditor()">
277
302
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
278
303
  </button>
279
- <button id="msg-detail-fullscreen-btn" class="icon-btn" aria-label="Toggle fullscreen" title="Toggle fullscreen" onclick="toggleModalFullscreen('msg-detail-modal')">
304
+ <button id="msg-detail-modal-fullscreen-btn" class="icon-btn" aria-label="Toggle fullscreen" title="Toggle fullscreen" onclick="toggleModalFullscreen('msg-detail-modal')">
280
305
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>
281
306
  </button>
282
307
  <button class="modal-close" aria-label="Close" onclick="closeMsgDetailModal()">
@@ -285,7 +310,7 @@
285
310
  </div>
286
311
  </div>
287
312
  <div class="modal-body" style="flex: 0 1 auto; min-height: 0; display: flex; flex-direction: column; overflow: hidden;">
288
- <div id="msg-detail-body" class="rendered-md" style="word-break: break-word; font-size: 13px; line-height: 1.6; overflow-y: auto; flex: 0 1 auto; min-height: 0; padding-right: 8px;"></div>
313
+ <div id="msg-detail-body" class="rendered-md modal-zoomable"></div>
289
314
  <div id="msg-detail-meta" style="margin-top: 12px; font-size: 11px; color: var(--text-muted); flex-shrink: 0;"></div>
290
315
  </div>
291
316
  </div>
@@ -312,7 +337,7 @@
312
337
  </div>
313
338
  </div>
314
339
  <div class="modal-body">
315
- <div id="preview-modal-body" class="rendered-md"></div>
340
+ <div id="preview-modal-body" class="rendered-md modal-zoomable"></div>
316
341
  <div id="preview-modal-meta"></div>
317
342
  </div>
318
343
  </div>
@@ -329,7 +354,7 @@
329
354
  </svg>
330
355
  </button>
331
356
  </div>
332
- <div class="modal-body">
357
+ <div class="modal-body modal-zoomable">
333
358
  <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 0 24px;">
334
359
  <div style="display: grid; gap: 16px; align-content: start;">
335
360
  <div>
@@ -434,6 +459,14 @@
434
459
  <td style="padding: 4px 0; color: var(--text-secondary);"><kbd style="background: var(--bg-hover); padding: 2px 6px; border-radius: 4px; font-family: monospace;">Shift+M</kbd></td>
435
460
  <td style="padding: 4px 0; color: var(--text-primary);">Open last message detail</td>
436
461
  </tr>
462
+ <tr>
463
+ <td style="padding: 4px 0; color: var(--text-secondary);"><kbd style="background: var(--bg-hover); padding: 2px 6px; border-radius: 4px; font-family: monospace;">Ctrl++</kbd> / <kbd style="background: var(--bg-hover); padding: 2px 6px; border-radius: 4px; font-family: monospace;">Ctrl+-</kbd></td>
464
+ <td style="padding: 4px 0; color: var(--text-primary);">Modal text size</td>
465
+ </tr>
466
+ <tr>
467
+ <td style="padding: 4px 0; color: var(--text-secondary);"><kbd style="background: var(--bg-hover); padding: 2px 6px; border-radius: 4px; font-family: monospace;">Ctrl+0</kbd></td>
468
+ <td style="padding: 4px 0; color: var(--text-primary);">Reset text size</td>
469
+ </tr>
437
470
  <tr>
438
471
  <td style="padding: 4px 0; color: var(--text-secondary);"><kbd style="background: var(--bg-hover); padding: 2px 6px; border-radius: 4px; font-family: monospace;">Shift+S</kbd></td>
439
472
  <td style="padding: 4px 0; color: var(--text-primary);">Storage manager</td>
@@ -502,7 +535,7 @@
502
535
  </button>
503
536
  </div>
504
537
  </div>
505
- <div id="team-modal-body" class="modal-body"></div>
538
+ <div id="team-modal-body" class="modal-body modal-zoomable"></div>
506
539
  <div class="modal-footer">
507
540
  <button id="session-info-dismiss-btn" class="btn btn-secondary" onclick="toggleDismissSession(_infoModalSessionId); closeTeamModal()">Dismiss</button>
508
541
  <button class="btn btn-secondary" onclick="showToolStatsModal(_infoModalSessionId)" title="Tool invocation statistics">Tool Stats</button>
@@ -522,7 +555,7 @@
522
555
  </svg>
523
556
  </button>
524
557
  </div>
525
- <div id="tool-stats-modal-body" class="modal-body" style="overflow-y:auto;flex:1 1 auto;min-height:0;"></div>
558
+ <div id="tool-stats-modal-body" class="modal-body modal-zoomable" style="overflow-y:auto;flex:1 1 auto;min-height:0;"></div>
526
559
  <div class="modal-footer">
527
560
  <button class="btn btn-secondary" onclick="closeToolStatsModal()">Close</button>
528
561
  </div>
@@ -551,7 +584,7 @@
551
584
  </button>
552
585
  </div>
553
586
  </div>
554
- <div id="plan-modal-body" class="modal-body detail-desc rendered-md" style="overflow-y: auto; flex: 0 1 auto; min-height: 0;"></div>
587
+ <div id="plan-modal-body" class="modal-body detail-desc rendered-md modal-zoomable"></div>
555
588
  <div class="modal-footer">
556
589
  <button class="btn btn-secondary" onclick="closePlanModal()">Close</button>
557
590
  </div>
@@ -597,7 +630,7 @@
597
630
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6L6 18M6 6l12 12"/></svg>
598
631
  </button>
599
632
  </div>
600
- <div id="loop-modal-body" class="modal-body" style="overflow-y:auto;flex:0 1 auto;min-height:0;"></div>
633
+ <div id="loop-modal-body" class="modal-body modal-zoomable" style="overflow-y:auto;flex:0 1 auto;min-height:0;"></div>
601
634
  <div class="modal-footer">
602
635
  <button class="btn btn-secondary" onclick="closeLoopModal()">Close</button>
603
636
  </div>
@@ -621,7 +654,7 @@
621
654
  </button>
622
655
  </div>
623
656
  </div>
624
- <div id="workflow-modal-body" class="modal-body" style="overflow-y:auto;flex:1 1 auto;min-height:0;"></div>
657
+ <div id="workflow-modal-body" class="modal-body modal-zoomable" style="overflow-y:auto;flex:1 1 auto;min-height:0;"></div>
625
658
  <div class="modal-footer">
626
659
  <button class="btn btn-secondary" onclick="closeWorkflowModal()">Close</button>
627
660
  </div>
@@ -652,7 +685,7 @@
652
685
  </button>
653
686
  </div>
654
687
  </div>
655
- <div id="agent-modal-body" class="modal-body" style="overflow-y: auto; overflow-x: hidden; flex: 0 1 auto; min-height: 0;"></div>
688
+ <div id="agent-modal-body" class="modal-body modal-zoomable" style="overflow-y: auto; overflow-x: hidden; flex: 0 1 auto; min-height: 0;"></div>
656
689
  <div class="modal-footer">
657
690
  <button id="agent-modal-dismiss-btn" class="btn agent-dismiss-btn" style="display:none" onclick="dismissAgent(currentAgentModalId);closeAgentModal()">Dismiss</button>
658
691
  <button class="btn btn-secondary" onclick="closeAgentModal()">Close</button>
@@ -695,7 +728,7 @@
695
728
  <button class="storage-tab" data-tab="scratchpads" onclick="switchStorageTab('scratchpads')">Scratchpads</button>
696
729
  <button class="storage-tab" data-tab="linked-docs" onclick="switchStorageTab('linked-docs')">Linked Docs</button>
697
730
  </div>
698
- <div class="modal-body" id="storage-modal-body" style="overflow-y:auto;min-height:200px;max-height:60vh;padding-top:16px;padding-right:8px;"></div>
731
+ <div class="modal-body modal-zoomable" id="storage-modal-body"></div>
699
732
  <div class="modal-footer">
700
733
  <button id="storage-cleanup-btn" class="btn btn-secondary" onclick="cleanupOrphanedStorage()">Clean Orphaned</button>
701
734
  <button class="btn btn-secondary" onclick="closeStorageManager()">Close</button>
package/public/style.css CHANGED
@@ -38,6 +38,8 @@
38
38
  /* aliases: many rules reference --font-mono/--font-serif; keep them on-brand */
39
39
  --font-mono: var(--mono);
40
40
  --font-serif: var(--serif);
41
+ /* reading-surface scale for the message-detail and preview modals (Ctrl +/-/0) */
42
+ --modal-zoom: 1;
41
43
  }
42
44
 
43
45
  * {
@@ -353,10 +355,11 @@ body::before {
353
355
  }
354
356
 
355
357
  .section-header {
358
+ position: relative;
356
359
  display: flex;
357
360
  align-items: center;
358
- justify-content: space-between;
359
- padding: 14px 20px 10px;
361
+ gap: 8px;
362
+ padding: 14px 16px 10px 20px;
360
363
  font-size: 11px;
361
364
  font-weight: 500;
362
365
  text-transform: uppercase;
@@ -364,16 +367,95 @@ body::before {
364
367
  color: var(--text-muted);
365
368
  }
366
369
 
370
+ .section-header-label {
371
+ flex: 0 0 auto;
372
+ }
373
+
374
+ /* Non-default filters, spelled out in the header so folding them into the popover
375
+ never hides *that* the list is filtered. Empty (and invisible) at defaults. */
376
+ .filter-summary {
377
+ flex: 1;
378
+ min-width: 0;
379
+ overflow: hidden;
380
+ white-space: nowrap;
381
+ text-overflow: ellipsis;
382
+ font-size: 10px;
383
+ font-weight: 400;
384
+ letter-spacing: 0.02em;
385
+ text-transform: none;
386
+ color: var(--accent-text);
387
+ }
388
+
389
+ .section-header-actions {
390
+ flex: 0 0 auto;
391
+ display: flex;
392
+ align-items: center;
393
+ gap: 2px;
394
+ margin-left: auto;
395
+ }
396
+
397
+ /* Quiet at rest: no box around a header glyph. The hairline arrives on hover.
398
+ Compounded with .icon-btn because that rule is declared later in this file and would
399
+ otherwise win on size, border, and colour. */
400
+ .icon-btn.section-btn {
401
+ width: 26px;
402
+ height: 26px;
403
+ padding: 0;
404
+ background: none;
405
+ border-color: transparent;
406
+ color: var(--text-muted);
407
+ }
408
+
409
+ .icon-btn.section-btn:hover {
410
+ background: var(--bg-hover);
411
+ border-color: var(--border);
412
+ color: var(--text-primary);
413
+ }
414
+
415
+ .icon-btn.section-btn:focus-visible {
416
+ outline: none;
417
+ box-shadow: 0 0 0 2px var(--accent-dim);
418
+ }
419
+
420
+ .icon-btn.section-btn svg {
421
+ width: 15px;
422
+ height: 15px;
423
+ stroke-width: 1.75;
424
+ }
425
+
426
+ /* Ember only while something is actually filtered — at rest the funnel is just chrome. */
427
+ .icon-btn.section-btn.has-filters {
428
+ color: var(--accent-text);
429
+ }
430
+
431
+ .filter-menu {
432
+ display: none;
433
+ position: absolute;
434
+ top: calc(100% - 2px);
435
+ right: 16px;
436
+ left: 16px;
437
+ z-index: 100;
438
+ padding: 8px;
439
+ background: var(--bg-elevated);
440
+ border: 1px solid var(--border);
441
+ border-radius: 8px;
442
+ box-shadow:
443
+ 0 16px 44px rgba(0, 0, 0, 0.38),
444
+ 0 4px 12px rgba(0, 0, 0, 0.2);
445
+ cursor: default;
446
+ }
447
+
448
+ .filter-menu.open {
449
+ display: block;
450
+ }
451
+
367
452
  .filter-row {
368
453
  display: flex;
369
- gap: 6px;
370
- padding: 0 16px 10px;
454
+ gap: 5px;
371
455
  }
372
456
 
373
- .reset-btn {
374
- flex-shrink: 0;
375
- width: 32px;
376
- height: 32px;
457
+ .filter-row + .filter-row {
458
+ margin-top: 5px;
377
459
  }
378
460
 
379
461
  .filter-dropdown {
@@ -399,6 +481,17 @@ body::before {
399
481
  border-color: var(--border);
400
482
  }
401
483
 
484
+ /* A filter holding a non-default value tints toward the ember, so it reads as "active"
485
+ before you read the value. Border and text only — the fill never floods. */
486
+ .filter-dropdown.non-default {
487
+ color: var(--accent-text);
488
+ border-color: color-mix(in srgb, var(--accent) 40%, transparent);
489
+ }
490
+
491
+ .filter-dropdown.non-default:hover {
492
+ border-color: color-mix(in srgb, var(--accent) 60%, transparent);
493
+ }
494
+
402
495
  .filter-dropdown option {
403
496
  background: var(--bg-surface);
404
497
  color: var(--text-primary);
@@ -3638,10 +3731,12 @@ body.light .msg-assistant .msg-text {
3638
3731
  overflow-y: auto;
3639
3732
  }
3640
3733
 
3734
+ /* Height is a cap, not a floor — a two-line message should not sit in a 92vh box.
3735
+ The HTML preview keeps its explicit height below: its iframe is `height: 100%`
3736
+ and needs a resolvable parent height. */
3641
3737
  .modal.fullscreen {
3642
3738
  width: 80vw;
3643
3739
  max-width: 80vw;
3644
- height: 92vh;
3645
3740
  max-height: 92vh;
3646
3741
  }
3647
3742
 
@@ -3682,7 +3777,9 @@ body.light .msg-assistant .msg-text {
3682
3777
  overflow: hidden;
3683
3778
  }
3684
3779
 
3685
- #preview-modal-body {
3780
+ #msg-detail-body,
3781
+ #preview-modal-body,
3782
+ #plan-modal-body {
3686
3783
  word-break: break-word;
3687
3784
  font-size: 13px;
3688
3785
  line-height: 1.6;
@@ -3692,6 +3789,30 @@ body.light .msg-assistant .msg-text {
3692
3789
  padding-right: 8px;
3693
3790
  }
3694
3791
 
3792
+ /* Same reading size as the other modal bodies — `.detail-desc` is really the
3793
+ task-panel inline editor's style, and its 14px/1.7 is wrong here. */
3794
+ .agent-tab-panel .detail-desc {
3795
+ font-size: 13px;
3796
+ line-height: 1.6;
3797
+ }
3798
+
3799
+ /* One reading scale for every modal (Ctrl +/-/0). `zoom` rather than font-size
3800
+ because the bodies mix px, rem, inline sizes from tool rendering and an iframe.
3801
+ It hangs on the inner scrolling body — never on `.modal`, whose own vw/vh
3802
+ sizing would scale with it and push the dialog off-screen. */
3803
+ .modal-zoomable {
3804
+ zoom: var(--modal-zoom, 1);
3805
+ }
3806
+
3807
+ /* Height is left to the flex column under `.storage-modal`'s 85vh cap — a `vh`
3808
+ cap here would be multiplied by the zoom above. */
3809
+ #storage-modal-body {
3810
+ overflow-y: auto;
3811
+ min-height: 200px;
3812
+ padding-top: 16px;
3813
+ padding-right: 8px;
3814
+ }
3815
+
3695
3816
  #preview-modal-meta {
3696
3817
  margin-top: 12px;
3697
3818
  font-size: 11px;