- Add 9-SUMMARY.md with execution results - Update STATE.md with quick task 9 entry
7.2 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | must_haves | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| quick-9 | 01 | execute | 1 |
|
true |
|
Purpose: The root cause is lit-virtualizer's flow layout dynamically recalculating _scrollSize based on measured item averages. With 20k items but only ~15-20 measured at any time, the initial item size estimate (100px default) vs actual size (~48px) causes the scroll height to shrink dramatically as items get measured during downward scrolling. This makes the scrollbar thumb "lag" behind the mouse because the scroll container height keeps changing underneath the drag. Going UP works because those items are already measured and stable.
The fix is to set a fixed, explicit height on .track-item elements so that all items have identical measured heights from the very first render. This makes _scrollSize = items.length * (averageMargin + averageSize) + averageMargin completely stable because the average never changes — it equals the actual size of every item.
Output: Stable scrollbar behavior on large queues.
<execution_context> @/home/caleb/.config/Claude/get-shit-done/workflows/execute-plan.md @/home/caleb/.config/Claude/get-shit-done/templates/summary.md </execution_context>
@frontend/src/components/queue-panel/queue-panel.ts @frontend/src/styles/tokens.css.tsFrom node_modules/@lit-labs/virtualizer/layouts/flow.js:
// _scrollSize is computed from average of MEASURED items only:
_updateScrollSize() {
const { averageMarginSize } = this._metricsCache;
this._scrollSize = Math.max(1,
this.items.length * (averageMarginSize + this._getAverageSize()) + averageMarginSize);
}
// Initial estimate before any measurements:
this._itemSize = { width: 100, height: 100 }; // <-- way off from actual ~48px
// Average comes from SizeCache which only has measured (visible) items:
_getAverageSize() {
return this._metricsCache.averageChildSize || this._itemSize[this._sizeDim];
}
From frontend/src/styles/tokens.css.ts:
--yj-text-xs: 11px; // artist font
--yj-text-sm: 12px; // position number font
--yj-text-md: 13px; // title font
Current .track-item CSS (around line 273):
.track-item {
position: relative;
display: flex;
align-items: center;
padding: 8px 16px;
gap: 12px;
border-bottom: 1px solid var(--yj-hover-overlay, rgba(255, 255, 255, 0.05));
cursor: default;
user-select: none;
width: 100%;
box-sizing: border-box;
}
Add these properties to .track-item:
height: 49px;
overflow: hidden;
Height calculation: The content is two text lines (13px title at ~1.2 line-height = ~16px, 11px artist at ~1.2 line-height = ~13px) with 2px gap = ~31px content. Add 8px + 8px vertical padding = 47px. Plus 1px border-bottom = 48px total box. Setting height: 49px gives 1px breathing room for sub-pixel rounding (the border-bottom is outside the height due to box-sizing: border-box including it — actually border-box INCLUDES the border in height, so 49px = 8px pad-top + ~32px content + 8px pad-bottom + 1px border = 49px total).
IMPORTANT: After setting this, verify the actual rendered height matches by loading the app with a queue of tracks and inspecting a .track-item in DevTools. If the actual measured height differs from 49px, adjust accordingly. The critical requirement is that ALL items have the SAME fixed height — the exact value matters less than uniformity.
Also add overflow: hidden on .track-details to ensure long titles/artists don't cause any height variation:
.track-details {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 2px;
overflow: hidden; /* add this */
}
Do NOT:
- Change the flow layout or virtualizer configuration — the fix is pure CSS
- Add
min-heightormax-height— use onlyheightfor exact sizing - Change padding, gap, or font sizes — only add the
heightandoverflowproperties cd frontend && npx tsc --noEmit 2>&1 | head -20.track-itemhas explicit fixedheight: 49pxandoverflow: hidden.track-detailshasoverflow: hidden- All queue items render at identical pixel heights
- TypeScript compiles without errors
<success_criteria>
- Scrollbar follows mouse position proportionally when dragging in both directions
- Works correctly on queues with 20k+ tracks
- No visual layout changes to queue track items </success_criteria>