executable-stories-formatters 0.6.0 → 0.6.1

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/dist/index.js CHANGED
@@ -721,37 +721,56 @@ function initSearch() {
721
721
 
722
722
  // Tag filter
723
723
  function initTagFilter() {
724
+ var toggleBtn = document.querySelector('.tag-bar-toggle');
725
+ var tagBar = document.querySelector('.tag-bar');
726
+ if (toggleBtn && tagBar) {
727
+ toggleBtn.addEventListener('click', function() {
728
+ var isCollapsed = tagBar.classList.toggle('tag-bar-collapsed');
729
+ toggleBtn.setAttribute('aria-expanded', String(!isCollapsed));
730
+ });
731
+ }
732
+
724
733
  document.querySelectorAll('.tag-pill').forEach(function(pill) {
725
734
  pill.addEventListener('click', function() {
726
735
  var tag = pill.dataset.tag;
727
736
  if (activeTags.has(tag)) {
728
737
  activeTags.delete(tag);
729
738
  pill.classList.remove('active');
739
+ pill.setAttribute('aria-pressed', 'false');
730
740
  } else {
731
741
  activeTags.add(tag);
732
742
  pill.classList.add('active');
743
+ pill.setAttribute('aria-pressed', 'true');
733
744
  }
734
- updateClearButton();
745
+ updateTagBarState();
735
746
  applyAllFilters();
736
747
  });
737
748
  });
738
749
 
739
750
  var clearBtn = document.querySelector('.tag-bar-clear');
740
751
  if (clearBtn) {
741
- clearBtn.addEventListener('click', function() {
752
+ clearBtn.addEventListener('click', function(e) {
753
+ e.stopPropagation();
742
754
  activeTags.clear();
743
- document.querySelectorAll('.tag-pill.active').forEach(function(p) { p.classList.remove('active'); });
744
- updateClearButton();
755
+ document.querySelectorAll('.tag-pill.active').forEach(function(p) {
756
+ p.classList.remove('active');
757
+ p.setAttribute('aria-pressed', 'false');
758
+ });
759
+ updateTagBarState();
745
760
  applyAllFilters();
746
761
  });
747
762
  }
748
763
  }
749
764
 
750
- function updateClearButton() {
765
+ function updateTagBarState() {
751
766
  var clearBtn = document.querySelector('.tag-bar-clear');
767
+ var countBadge = document.querySelector('.tag-bar-count');
752
768
  if (clearBtn) {
753
769
  clearBtn.style.display = activeTags.size > 0 ? '' : 'none';
754
770
  }
771
+ if (countBadge) {
772
+ countBadge.textContent = activeTags.size > 0 ? activeTags.size + ' selected' : '';
773
+ }
755
774
  }
756
775
 
757
776
  // Status filter (clickable summary cards)
@@ -1452,7 +1471,24 @@ body {
1452
1471
  display: flex;
1453
1472
  justify-content: space-between;
1454
1473
  align-items: center;
1455
- margin-bottom: 0.5rem;
1474
+ }
1475
+
1476
+ .tag-bar-toggle {
1477
+ display: flex;
1478
+ align-items: center;
1479
+ gap: 0.5rem;
1480
+ background: none;
1481
+ border: none;
1482
+ cursor: pointer;
1483
+ padding: 0;
1484
+ color: inherit;
1485
+ font: inherit;
1486
+ }
1487
+
1488
+ .tag-bar-toggle:focus-visible {
1489
+ outline: 2px solid var(--ring);
1490
+ outline-offset: 2px;
1491
+ border-radius: var(--radius);
1456
1492
  }
1457
1493
 
1458
1494
  .tag-bar-label {
@@ -1463,26 +1499,58 @@ body {
1463
1499
  font-weight: 500;
1464
1500
  }
1465
1501
 
1502
+ .tag-bar-count {
1503
+ font-size: 0.6875rem;
1504
+ font-weight: 600;
1505
+ color: var(--primary);
1506
+ }
1507
+
1508
+ .tag-bar-chevron {
1509
+ color: var(--muted-foreground);
1510
+ transition: transform 0.2s ease;
1511
+ flex-shrink: 0;
1512
+ }
1513
+
1514
+ .tag-bar-collapsed .tag-bar-chevron {
1515
+ transform: rotate(0deg);
1516
+ }
1517
+
1518
+ .tag-bar:not(.tag-bar-collapsed) .tag-bar-chevron {
1519
+ transform: rotate(180deg);
1520
+ }
1521
+
1466
1522
  .tag-bar-clear {
1467
1523
  font-size: 0.75rem;
1468
1524
  font-weight: 500;
1469
- color: var(--primary);
1470
- background: none;
1471
- border: none;
1525
+ color: var(--destructive, #dc2626);
1526
+ background: var(--destructive-light, #fef2f2);
1527
+ border: 1px solid var(--destructive-border, #fecaca);
1472
1528
  cursor: pointer;
1473
- padding: 0.125rem 0.5rem;
1529
+ padding: 0.25rem 0.75rem;
1474
1530
  border-radius: var(--radius);
1475
1531
  transition: all 0.15s ease;
1476
1532
  }
1477
1533
 
1478
1534
  .tag-bar-clear:hover {
1479
- background: var(--muted);
1535
+ background: var(--destructive-border, #fecaca);
1536
+ }
1537
+
1538
+ .tag-bar-clear:focus-visible {
1539
+ outline: 2px solid var(--ring);
1540
+ outline-offset: 2px;
1480
1541
  }
1481
1542
 
1482
1543
  .tag-bar-pills {
1483
1544
  display: flex;
1484
1545
  flex-wrap: wrap;
1485
1546
  gap: 0.375rem;
1547
+ max-height: 200px;
1548
+ overflow-y: auto;
1549
+ margin-top: 0.5rem;
1550
+ }
1551
+
1552
+ .tag-bar-collapsed .tag-bar-pills {
1553
+ display: none;
1486
1554
  }
1487
1555
 
1488
1556
  .tag-pill {
@@ -1502,6 +1570,11 @@ body {
1502
1570
  background: var(--success-border);
1503
1571
  }
1504
1572
 
1573
+ .tag-pill:focus-visible {
1574
+ outline: 2px solid var(--ring);
1575
+ outline-offset: 2px;
1576
+ }
1577
+
1505
1578
  .tag-pill.active {
1506
1579
  background: var(--primary);
1507
1580
  color: var(--primary-foreground);
@@ -2658,19 +2731,25 @@ function renderTagBar(args, deps) {
2658
2731
  const { tags, totalScenarios } = args;
2659
2732
  if (tags.length === 0) return "";
2660
2733
  const pills = tags.map(
2661
- (tag) => `<button type="button" class="tag-pill" data-tag="${deps.escapeHtml(tag)}">${deps.escapeHtml(tag)}</button>`
2662
- ).join("\n ");
2734
+ (tag) => `<button type="button" class="tag-pill" data-tag="${deps.escapeHtml(tag)}" aria-pressed="false">${deps.escapeHtml(tag)}</button>`
2735
+ ).join("\n ");
2663
2736
  return `
2664
- <div class="tag-bar">
2737
+ <div class="tag-bar tag-bar-collapsed">
2665
2738
  <div class="tag-bar-header">
2666
- <span class="tag-bar-label">Filter by tag</span>
2667
- <button type="button" class="tag-bar-clear" style="display:none">Clear</button>
2739
+ <button type="button" class="tag-bar-toggle" aria-expanded="false" aria-controls="tag-pills-region">
2740
+ <span class="tag-bar-label">Filter by tag</span>
2741
+ <span class="tag-bar-count" aria-live="polite"></span>
2742
+ <svg class="tag-bar-chevron" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
2743
+ <path d="M4 6l4 4 4-4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
2744
+ </svg>
2745
+ </button>
2746
+ <button type="button" class="tag-bar-clear" aria-label="Clear all tag filters" style="display:none">Clear all</button>
2668
2747
  </div>
2669
- <div class="tag-bar-pills">
2748
+ <div id="tag-pills-region" class="tag-bar-pills" role="group" aria-label="Tag filters">
2670
2749
  ${pills}
2671
2750
  </div>
2672
2751
  </div>
2673
- <div class="filter-results" style="display:none">
2752
+ <div class="filter-results" style="display:none" aria-live="polite">
2674
2753
  Showing <span class="visible-count">0</span> of <span class="total-count">${totalScenarios}</span> scenarios
2675
2754
  </div>`;
2676
2755
  }