Files
olivv-cs-ComfyUI-FunPack/app/composer/elements/track.css
T
digital-garbageandClaude Sonnet 5 a600fe3e29 fix: real timeline -- full-width layout, playhead reentrancy, panel overlap
Round 1 + round 2 of adversarial review on the single-track timeline
(2092c8b) found and fixed:

- Clip position now stays absolute (seconds*pxPerSecond) instead of the
  MIN_CLIP_PX floor cascading into every later clip -- a floored short
  clip no longer pushes everything after it out of sync with the ruler.
- pendingSeek is cleared unconditionally right after project.select(),
  closing a gap where a no-op select() (clicking within the already
  selected clip) left it dangling for a later, unrelated draw to
  wrongly replay.
- draw() now always resyncs the playhead to the current scene's start
  on any non-track-click selection change, rather than only when the
  old value fell outside the new scene's span -- the old check let a
  stale playhead survive a wholesale project switch whenever it
  coincidentally still fit the new project's first scene.
- The timeline moved from the centre column's own inner split to an
  outer split above/below the whole three-column workspace, matching
  v4's actual layout (full-width timeline under resizable columns,
  not squeezed inside one of them).
- That restructuring put the Properties column under real height
  pressure for the first time, exposing a latent bug: .cx-stack's
  base rule set min-block-size:0 on every stack, letting a plain
  grouping stack (not meant to scroll) get flex-crushed below its own
  content height, so its overflow painted over the next row ("Settings"
  over "Loosen the starting image"). Removed from the base rule --
  .cx-stack-fill already carries it for the one case that should
  actually give up height to scroll.
- Documented, rather than "fixed" by reintroducing the rejected
  cascading-position bug: several under-floor clips in a row still
  visually occlude each other (later DOM paints over earlier). Click-
  seek still resolves correctly since it reads time, not paint order.
- Guarded framesOf() against a negative/NaN scene.length the same way
  fps() already guards its own input.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 19:29:44 +03:00

54 lines
2.8 KiB
CSS

/* A real timeline: a ruler in seconds, clips as wide as they play for, and a
* playhead over both. Pixel-positioned rather than percent/flex-grow -- what
* makes the ruler's ticks and the clips underneath actually line up. */
.cx-track { overflow-x: auto; min-inline-size: 0; }
.cx-track-inner { position: relative; min-inline-size: 100%; }
.cx-track-ruler {
position: relative; block-size: var(--lh-8); min-inline-size: 100%;
border-block-end: var(--bw) solid var(--line-2);
}
.cx-track-tick {
position: absolute; inset-block-start: 0;
padding-inline-start: var(--sp-1);
border-inline-start: var(--bw) solid var(--line);
font-size: var(--fs-8); line-height: var(--lh-8); color: var(--faint);
font-variant-numeric: tabular-nums;
}
/* A fixed row height, not aspect-ratio off the clip's own width -- a clip's
width now tracks real duration and can run to hundreds of pixels, and
16:10 off THAT would make a half-minute scene taller than the window.
Positioned (not flex-flow) for the same reason each clip sets its own
insetInlineStart in JS: a clip under the pixel floor must not push every
clip after it out of step with the ruler and the playhead, which both
stay in pure seconds*pxPerSecond regardless of any floor. */
.cx-track-clips { position: relative; min-inline-size: 100%; block-size: 45px; }
.cx-track-clip {
position: absolute; inset-block: 0; padding: 0;
border: var(--bw) solid var(--line); border-radius: var(--r-2);
background: var(--void); overflow: hidden; cursor: grab;
display: flex; align-items: center; justify-content: center;
}
.cx-track-face { position: relative; inline-size: 100%; block-size: 100%; display: flex; align-items: center; justify-content: center; }
.cx-track-clip:hover { border-color: var(--accent); }
.cx-track-clip.cx-on { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.cx-track-clip.cx-dragging { opacity: 0.4; cursor: grabbing; }
/* Still on the timeline, still there to bring back -- excluded from a batch
run reads as dimmed, not gone, the way a deleted scene would be. */
.cx-track-clip.cx-excluded { opacity: 0.45; }
/* A clip carries its rating as a colour on its edge -- the one thing about a
result you want to see without selecting it. */
.cx-track-clip.cx-rated { border-color: var(--muted); }
.cx-track-clip[data-rating="liked"] { border-color: var(--good); }
.cx-track-clip[data-rating="disliked"] { border-color: var(--danger); }
/* Spans both rows, so where the ruler reads and where the clip sits are
visibly the same point -- a plain marker on just one of them would not
read as "this is where you are" the way a line through both does. */
.cx-track-playhead {
position: absolute; inset-block: 0; inline-size: 0;
border-inline-start: 2px solid var(--accent-hi);
pointer-events: none; z-index: 1;
}