Keep the timeline's ruler and playhead dot in view while its rows scroll
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
c139e4d747
commit
277c0c3b63
2 changed files with 28 additions and 9 deletions
|
|
@ -355,9 +355,7 @@
|
||||||
(reset! over nil)
|
(reset! over nil)
|
||||||
(when (< 1 (count from))
|
(when (< 1 (count from))
|
||||||
(rf/dispatch [::ui/move-node from []]))))}
|
(rf/dispatch [::ui/move-node from []]))))}
|
||||||
[:div {:style {:height "var(--ruler)"
|
[:div.tl-corner]
|
||||||
:border-bottom "1px solid var(--line)"
|
|
||||||
:background "var(--chrome)"}}]
|
|
||||||
(doall (for [row visible]
|
(doall (for [row visible]
|
||||||
^{:key (str (:path row))} [label-cell row selection over]))]
|
^{:key (str (:path row))} [label-cell row selection over]))]
|
||||||
[:div.tl-tracks
|
[:div.tl-tracks
|
||||||
|
|
@ -401,7 +399,8 @@
|
||||||
:on-pointer-cancel (fn [_] (reset! scrubbing false))}
|
:on-pointer-cancel (fn [_] (reset! scrubbing false))}
|
||||||
(doall
|
(doall
|
||||||
(for [f (range 0 frames step)]
|
(for [f (range 0 frames step)]
|
||||||
^{:key f} [:div.tick {:style {:left (edge% f frames)}} f]))]
|
^{:key f} [:div.tick {:style {:left (edge% f frames)}} f]))
|
||||||
|
[:div.tl-knob {:style {:left (at% frame frames)}}]]
|
||||||
(if (seq visible)
|
(if (seq visible)
|
||||||
(doall (for [row visible]
|
(doall (for [row visible]
|
||||||
^{:key (str (:path row))} [track-cell row frames sliding]))
|
^{:key (str (:path row))} [track-cell row frames sliding]))
|
||||||
|
|
|
||||||
|
|
@ -562,9 +562,16 @@ button.share-button:hover, button.share-button.on { filter: brightness(1.1); }
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
/* Not `stretch`: that sizes both columns to the body's height, the rows then
|
||||||
|
overflow them, and the sticky ruler goes out with its column. Each column is
|
||||||
|
as tall as its rows instead, and at least as tall as the body. */
|
||||||
|
align-items: flex-start;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tl-labels,
|
||||||
|
.tl-tracks { min-height: 100%; }
|
||||||
|
|
||||||
.tl-labels {
|
.tl-labels {
|
||||||
flex: 0 0 var(--label);
|
flex: 0 0 var(--label);
|
||||||
/* A flex item's `min-width` defaults to `auto`, which floors its used size at
|
/* A flex item's `min-width` defaults to `auto`, which floors its used size at
|
||||||
|
|
@ -574,7 +581,9 @@ button.share-button:hover, button.share-button.on { filter: brightness(1.1); }
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 1;
|
/* Over the ruler and the playhead, which both pass under it when the tracks
|
||||||
|
scroll sideways. */
|
||||||
|
z-index: 4;
|
||||||
background: var(--pane);
|
background: var(--pane);
|
||||||
border-right: 1px solid var(--line);
|
border-right: 1px solid var(--line);
|
||||||
}
|
}
|
||||||
|
|
@ -638,11 +647,20 @@ button.share-button:hover, button.share-button.on { filter: brightness(1.1); }
|
||||||
.tl-delete { margin-left: auto; padding: 0 4px; border: 0; background: none; color: var(--dim); }
|
.tl-delete { margin-left: auto; padding: 0 4px; border: 0; background: none; color: var(--dim); }
|
||||||
.tl-delete:hover { color: var(--fg); }
|
.tl-delete:hover { color: var(--fg); }
|
||||||
|
|
||||||
|
/* The ruler and the corner above the labels stay at the top of the body while
|
||||||
|
the rows scroll under them: the ruler is the scrubber, and scrolling down to
|
||||||
|
a row is no reason to lose it. */
|
||||||
|
.tl-corner,
|
||||||
.tl-ruler {
|
.tl-ruler {
|
||||||
position: relative;
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 2;
|
||||||
height: var(--ruler);
|
height: var(--ruler);
|
||||||
border-bottom: 1px solid var(--line);
|
border-bottom: 1px solid var(--line);
|
||||||
background: var(--chrome);
|
background: var(--chrome);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tl-ruler {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
@ -718,11 +736,13 @@ button.share-button:hover, button.share-button.on { filter: brightness(1.1); }
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tl-playhead::before {
|
/* The playhead's head, in the ruler rather than on the line, so it stays at the
|
||||||
content: "";
|
top with the ruler while the rows scroll. */
|
||||||
|
.tl-knob {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
pointer-events: none;
|
||||||
|
margin-left: -4px;
|
||||||
top: 1px;
|
top: 1px;
|
||||||
left: -4px;
|
|
||||||
width: 9px;
|
width: 9px;
|
||||||
height: 9px;
|
height: 9px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue