feat: smart fold around errors with drag-to-reveal handle

Replaces the all-or-nothing "Errors only" collapse with a contextual
fold: ±25 entries around every error stay visible, and runs of
non-error entries with no nearby error collapse into a fold bar.

Each fold bar is draggable. Vertical pointer drag on the bar reveals
or re-hides lines from the top of the hidden range, ~6 px per line.
A click without drag reveals the next 25 lines. When the run is
fully revealed, the bar removes itself. Buttons / scroll behaviour
are unchanged; the existing "X errors" toggle in the header is the
entry point and still un-collapses everything on second click.

Visual: foldable bars get a faint horizontal hatch (suggesting
compressed content), an ns-resize cursor, and a hover/dragging
state that intensifies the hatch toward --accent. The grip-lines
icon flanks the line-count to call out the affordance.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-06 19:27:59 +00:00
parent cc1e853f89
commit 4d0d98c604
2 changed files with 194 additions and 58 deletions

View File

@@ -1088,6 +1088,71 @@ main {
color: var(--accent);
}
/*
* Foldable variant — generated by the smart "errors + 25 context" toggle in
* log.js. The bar is draggable: vertical pointer drag reveals or re-hides
* lines from the top of the hidden range. Visual cues:
* - ns-resize cursor announces the drag direction.
* - Faint horizontal hatch hints at compressed content underneath.
* - Hover and drag states intensify the hatch toward --accent so the
* bar reads as an interactive separator, not decorative chrome.
*/
.collapsed-lines-foldable {
cursor: ns-resize;
user-select: none;
-webkit-user-select: none;
}
.collapsed-lines-foldable .collapsed-lines-count {
background:
repeating-linear-gradient(
to bottom,
transparent 0,
transparent 3px,
color-mix(in srgb, var(--border) 60%, transparent) 3px,
color-mix(in srgb, var(--border) 60%, transparent) 4px
),
var(--surface);
border-top: 1px solid var(--border);
border-bottom: 1px solid var(--border);
transition:
background-color 0.12s ease,
color 0.12s ease,
border-color 0.12s ease,
box-shadow 0.12s ease;
}
.collapsed-lines-foldable:hover .collapsed-lines-count,
.collapsed-lines-dragging .collapsed-lines-count {
background:
repeating-linear-gradient(
to bottom,
transparent 0,
transparent 3px,
color-mix(in srgb, var(--accent) 35%, transparent) 3px,
color-mix(in srgb, var(--accent) 35%, transparent) 4px
),
var(--accent-bg);
border-top-color: color-mix(in srgb, var(--accent) 60%, transparent);
border-bottom-color: color-mix(in srgb, var(--accent) 60%, transparent);
color: var(--accent);
}
.collapsed-lines-foldable:hover .collapsed-lines-count i,
.collapsed-lines-dragging .collapsed-lines-count i {
color: var(--accent);
}
.collapsed-lines-dragging {
cursor: grabbing;
}
.collapsed-lines-dragging .collapsed-lines-count {
box-shadow:
inset 0 0 0 1px color-mix(in srgb, var(--accent) 70%, transparent),
0 6px 16px color-mix(in srgb, var(--accent) 25%, transparent);
}
.log-inner .level {
display: block;
white-space: pre-wrap;