ProgressionBuilder component for guitar-app (~2000 lines). USE FOR: modifying progression grid, drag-and-drop behavior, pool management, quick-add search, cell actions, PDF export, URL sharing, multi-select/sweep, mobile layout. Covers component state, two-column layout, two quick-add systems, grid cell rendering, drag system, selection modes.
src/components/ProgressionBuilder.svelte — the most complex component (~2000 lines). Manages a chord progression grid with pool sidebar, drag-and-drop, multi-select, PDF export, and URL sharing.
┌─────────────┬──────────────────────────────────┐
│ Pool Column │ Progression Column │
│ (200px) │ │
│ │ [Title input] [Select] [URL] [PDF]│
│ Quick Search│ │
│ [Nav btns] │ ┌────┬────┬────┬────┐ │
│ │ │Cell│Cell│Cell│Cell│ ← 4 cols │
│ Pool Entry │ ├────┼────┼────┼────┤ │
│ Pool Entry │ │Cell│Cell│Cell│Cell│ │
│ Pool Entry │ └────┴────┴────┴────┘ │
│ ... │ [+ Add Row] │
│ │ │
│ [Clear Pool]│ │
└─────────────┴──────────────────────────────────┘
position: absolutepoolCollapsed| Group | Variables | Purpose |
|---|---|---|
| Global quick-add | quickSearch, quickResults, quickDropdownOpen, quickAddingSymbol | Pool column search |
| Cell quick-add | cellQuickIdx, cellQuickSearch, cellQuickResults, cellPoolMatches, cellQuickOpen, cellQuickAdding | Empty cell inline search |
| PDF export | progressionGridEl, exporting | Grid element ref, export flag |
| URL sharing | urlCopied | Clipboard feedback |
| Responsive | isMobile ($derived), poolCollapsed | Layout mode |
| Multi-select | selectMode, selectedCells (Set), sweeping, swept, sweepStartIdx | Sweep/select |
| Click-to-move | moveFromIdx | Highlighted source cell |
| Drag & drop | dragSource, dragOverIdx, dragOverInsertIdx, dragOverZone | Drag state |
| Pool mgmt | sortedPool ($derived), clearPoolConfirm, deletePoolConfirmKey | Sorted entries, clear/delete confirmation |
Search input at top of pool sidebar. Searches chord database.
updateQuickResults(): filters to 8 results from filterChords()handleQuickAdd(): adds best voicing to pool onlyhandleQuickAddToProgression(): adds to pool AND pushes to progression gridWhen user clicks an empty cell, shows inline search with two sections:
Grid columns: 4 (desktop) / 2 (mobile) / 6 (PDF export)
| Class | Appearance | When |
|---|---|---|
.filled | Solid border, chord diagram + name | Cell has poolKey |
.moving | Accent border + glow shadow | moveFromIdx === idx |
.selected | Accent border + light background | In selectedCells set |
.drag-over | Accent highlight | Drag hovering over cell |
displayAccidental)cellQuickIdx === idx: inline quick-add input + dropdown.cell-actions row, plays voicing via playStrum(entry.voicing.notes).cell-actions row, returns voicing from cellFull details: drag-and-drop.md
Summary: Pool entries and filled cells are draggable. Drop targets: cells (swap/place), insert gutters (splice). Drag disabled on mobile.
Full details: drag-and-drop.md
Summary: Toggle selectMode, sweep-select via pointer drag, batch delete/duplicate. Contiguity check enables duplicate.
Full details: pdf-export.md
Summary: Inline style overrides for html2canvas, 6-col grid, row-aware page breaks, jsPDF output.
handleGenerateUrl():
progression.toCompactUrl() → compact string${origin}${pathname}#p=${encodeURIComponent(compact)}urlCopied feedback for 2s| Handler | Action |
|---|---|
handlePoolPush(key, idx) | Place pool entry in cell |
handleReturnFromProgression(idx) | Clear cell, show quick-add UI |
handleDeleteFromPool(key) | Remove from pool AND all progression cells |
handleInsertCell(idx) | Insert empty cell, shift right |
handleDeleteCell(idx) | Delete cell, shift left |
handleDuplicateCell(idx) | Copy cell after itself |
handleAddMoreCells() | Add row (2 cols mobile, 4 desktop) |
sortedPool: $derived — sorts by chordName alphabetically, then by voicing.rank.pool-card-in-prog class (dashed accent border) and "in progression" badgeclearPoolConfirm: 2-click confirmation pattern (auto-resets after 3s)deletePoolConfirmKey: per-entry 2-click confirmation for entries used in progression (auto-resets 3s); delete button turns red with "!!" textESC key: cancels moveFromIdx, exits selectMode, clears selection