Skip to content

Commit cd789d8

Browse files
mpstatonclaude
andcommitted
fix(search-results, shell): rail rows fit the rail; flow resize-drag tracks the pointer 1:1
Two more live-use findings on the queue evening. Rail overflow (search-results): grid/flex children default to min-width:auto and refuse to shrink below content, so a long nowrap result title pushed the whole card wider than the rail — cutting off the right side, ➕ included. min-width:0 down the list chains, overflow-x hidden on the rail, overflow-wrap on snippets; titles now ellipsize inside the 340px rail and every ➕ is reachable. Flow resize-drag (shell): the focused-panel edge drag computed width as distance-from-stage-centre × 2, which assumes a centred panel — on the rotation's first/last step it jumped ~10% the instant you grabbed and tracked 2× per pixel; mid-drag the pointer also crossed the peek overlay, whose hover-expand fought the drag geometry. Now the dragged edge's stage position maps per-arrangement (centred → symmetric doubling; edge-anchored → the position IS the width), the edge takes pointer capture, hover-expand is suppressed while resizing, and only sides that actually border a peek render an edge. Verified live: pointer at 50/65/80% of the stage → panel at exactly 50/65/80%. Files changed: - apps/search-results/src/app.css - shell/src/App.svelte Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013u3i9BoKeZRndqToQ3M5Q5
1 parent 88197ed commit cd789d8

2 files changed

Lines changed: 45 additions & 14 deletions

File tree

apps/search-results/src/app.css

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,22 @@
88
padding: 0.5rem 0.75rem 2rem;
99
height: 100%;
1010
overflow-y: auto;
11+
overflow-x: hidden;
1112
box-sizing: border-box;
1213
}
1314

15+
/* Grid/flex children default to min-width:auto and refuse to shrink below
16+
their content — a long nowrap title then pushes the whole card wider than
17+
the rail and shoves the ➕ off-screen. Zero the min-width down the chain
18+
so ellipsis/wrap rules actually get to do their jobs. */
19+
.srq-list > *,
20+
.srq-results > *,
21+
.srq-staged-list > *,
22+
.srq-gate-list > *,
23+
.srq-card-body {
24+
min-width: 0;
25+
}
26+
1427
.srq-header { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 0 0.65rem; border-bottom: 1px solid var(--color-border, #2a2c33); position: sticky; top: 0; z-index: 2; background: var(--color-bg, #14151a); }
1528
.srq-title { font-size: 0.95rem; margin: 0; }
1629
.srq-badge { background: var(--color-accent, #8ab4f8); color: var(--color-on-accent, #10121a); font-size: 0.72rem; font-weight: 700; border-radius: 999px; min-width: 1.2rem; height: 1.2rem; display: inline-flex; align-items: center; justify-content: center; padding: 0 0.3rem; }
@@ -80,7 +93,7 @@
8093
.srq-row-host { color: var(--color-text-muted, #9aa0aa); font-size: 0.68rem; margin-left: 0.4rem; }
8194
.srq-kind { font-size: 0.64rem; padding: 0 5px; border-radius: 3px; background: var(--color-border, #2a2c33); color: var(--color-text-muted, #cfd3da); margin-left: 0.4rem; }
8295
.srq-row-name { color: var(--color-text-muted, #cfd3da); font-size: 0.72rem; margin-left: 0.4rem; }
83-
.srq-row-snippet { margin: 0.2rem 0 0; font-size: 0.72rem; color: var(--color-text-muted, #b7bcc5); line-height: 1.35; }
96+
.srq-row-snippet { margin: 0.2rem 0 0; font-size: 0.72rem; color: var(--color-text-muted, #b7bcc5); line-height: 1.35; overflow-wrap: anywhere; }
8497
.srq-add { flex-shrink: 0; width: 1.7rem; height: 1.7rem; border-radius: 5px; border: 1px solid var(--color-border, #2a2c33); background: var(--color-surface, #1c1e25); color: inherit; font-size: 0.95rem; line-height: 1; cursor: pointer; }
8598
.srq-add:hover:not(:disabled) { background: var(--color-border, #2a2c33); }
8699
.srq-add.added { border-color: var(--color-ok-text, #6ee7a8); color: var(--color-ok-text, #6ee7a8); cursor: default; }

shell/src/App.svelte

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,9 @@
242242
const peekEach = neighbourCount ? Math.max(MIN_PEEK, remainder / neighbourCount) : 0;
243243
244244
const slotKey = (s: Slot): string => (s.kind === 'remote' ? s.remote.id : s.composite.id);
245+
// Hover-expand never applies mid-resize — the drag owns the geometry.
245246
const isHovered = (s: Slot): boolean =>
246-
hoveredNeighborId !== null && slotKey(s) === hoveredNeighborId;
247+
!resizing && hoveredNeighborId !== null && slotKey(s) === hoveredNeighborId;
247248
const widthOf = (s: Slot): number => (isHovered(s) ? HOVER_PCT : peekEach);
248249
249250
const items: StageItem[] = [];
@@ -282,16 +283,27 @@
282283
}
283284
284285
// ---- focused-panel edge resize (peek-flow) ------------------------------
285-
function startResize(e: PointerEvent): void {
286+
// The dragged edge's stage-relative position maps to the focused width
287+
// according to which neighbours share the leftover: centred between two
288+
// peeks → symmetric doubling; anchored at a stage edge (first/last step)
289+
// → the edge position IS the width. The old centre-only math jumped on
290+
// grab and tracked 2× at the rotation's ends. Pointer capture keeps the
291+
// drag from feeding the peek overlays' hover-expand, which used to fight
292+
// the resize mid-drag.
293+
function startResize(e: PointerEvent, side: 'left' | 'right'): void {
286294
e.preventDefault();
287295
resizing = true;
296+
hoveredNeighborId = null;
297+
(e.currentTarget as HTMLElement | null)?.setPointerCapture?.(e.pointerId);
298+
const i = layout.focusIndex;
299+
const hasPrev = i > 0;
300+
const hasNext = i < activeFlow.rotation.length - 1;
288301
const onMove = (ev: PointerEvent) => {
289302
if (!stageEl) return;
290303
const rect = stageEl.getBoundingClientRect();
291-
// distance of the cursor from the stage centre, doubled, is the
292-
// focused panel's width as a fraction of the stage.
293-
const centre = rect.left + rect.width / 2;
294-
const pct = (Math.abs(ev.clientX - centre) * 2) / rect.width * 100;
304+
const p = ((ev.clientX - rect.left) / rect.width) * 100;
305+
const pct =
306+
hasPrev && hasNext ? Math.abs(p - 50) * 2 : side === 'right' ? p : 100 - p;
295307
layout.setFocusedWidth(pct);
296308
};
297309
const onUp = () => {
@@ -657,13 +669,19 @@
657669

658670
{#if item.role === 'focused'}
659671
<!-- focused-panel resize edges — distinct pixels from the peek
660-
overlays, so a resize-drag never fires a focus-commit. -->
661-
<div class="resize-edge resize-edge-left"
662-
onpointerdown={startResize}
663-
role="separator" aria-label="Resize focused panel" tabindex="-1"></div>
664-
<div class="resize-edge resize-edge-right"
665-
onpointerdown={startResize}
666-
role="separator" aria-label="Resize focused panel" tabindex="-1"></div>
672+
overlays, so a resize-drag never fires a focus-commit. Only
673+
sides that actually border a peek get one; the first/last
674+
step's outer edge is the stage boundary, not a divider. -->
675+
{#if layout.focusIndex > 0}
676+
<div class="resize-edge resize-edge-left"
677+
onpointerdown={(e) => startResize(e, 'left')}
678+
role="separator" aria-label="Resize focused panel" tabindex="-1"></div>
679+
{/if}
680+
{#if layout.focusIndex < activeFlow.rotation.length - 1}
681+
<div class="resize-edge resize-edge-right"
682+
onpointerdown={(e) => startResize(e, 'right')}
683+
role="separator" aria-label="Resize focused panel" tabindex="-1"></div>
684+
{/if}
667685
{/if}
668686
</section>
669687
{/each}

0 commit comments

Comments
 (0)