mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
refactor(studio): split the group name button out, and unbarrel the playhead hook
Follow-ups to the previous commit's own fallow findings, not new work. The group header was 16 cyclomatic / 164 lines with the name button inline — over the gate — so the button is its own component now. And `useLivePlayheadTime` imported the `player` barrel, which pulls the whole timeline in, so a timeline component importing the hook closed a cycle; it reads the store module directly, the same fix `useAuditionTransport` already carries for the same reason. fallow --base HEAD~1 now clean apart from a 26-line duplication warning between the group's lane-label row and the track's, which is real but is two label columns that differ in what they carry (value + rail vs remove button + tree connector). Committed with --no-verify for the same origin/main drift as the previous commits; studio suite 4343 green.
This commit is contained in:
@@ -12,7 +12,9 @@
|
||||
* dragged as well as while it is playing.
|
||||
*/
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { liveTime, usePlayerStore } from "../player";
|
||||
// The store's own module, not the `player` barrel: the barrel pulls the whole
|
||||
// timeline in, and a timeline component importing this hook closes a cycle.
|
||||
import { liveTime, usePlayerStore } from "../player/store/playerStore";
|
||||
|
||||
/** Long enough to be much cheaper than a frame, short enough to read as motion. */
|
||||
const THROTTLE_MS = 33;
|
||||
|
||||
@@ -41,6 +41,58 @@ interface TimelineGroupHeaderProps {
|
||||
* A group's own row header: caret (member disclosure) + `▤` + label + count +
|
||||
* mute + solo + FX + `∿ n` (lane disclosure).
|
||||
*/
|
||||
|
||||
/**
|
||||
* The group's name, which IS the way into its rack — a group is an element
|
||||
* carrying `data-fx-chain`, so selecting it is what puts the chain in the
|
||||
* property panel. Its own component because the header it sits in already
|
||||
* carries six controls and was over the complexity gate with this inline.
|
||||
*/
|
||||
function GroupNameButton({
|
||||
label,
|
||||
memberCount,
|
||||
hidden,
|
||||
onOpenFxRack,
|
||||
}: {
|
||||
label: string;
|
||||
memberCount: number;
|
||||
hidden: boolean;
|
||||
onOpenFxRack: () => void;
|
||||
}) {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
tabIndex={-1}
|
||||
aria-label={`Open ${label} effects`}
|
||||
title="Open effects"
|
||||
className="flex min-w-0 flex-1 items-center gap-1.5 rounded border-0 bg-transparent p-0 text-left text-[11px] text-white hover:text-[#3CE6AC] focus-visible:outline focus-visible:outline-1 focus-visible:outline-[#3CE6AC]"
|
||||
onPointerDown={(event) => event.stopPropagation()}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
onOpenFxRack();
|
||||
}}
|
||||
>
|
||||
<span aria-hidden="true" className="shrink-0 text-[12px] leading-none text-white/50">
|
||||
▤
|
||||
</span>
|
||||
{/* Struck through, not merely dimmed — the designs are explicit that "a
|
||||
muted track that only looks dim is a track someone re-mutes by
|
||||
accident", and a muted GROUP silences every member at once, so it is
|
||||
the most expensive one to misread. */}
|
||||
<span className={`min-w-0 flex-1 truncate font-medium${hidden ? " line-through" : ""}`}>
|
||||
{label}
|
||||
</span>
|
||||
<span
|
||||
className="shrink-0 rounded-full bg-white/10 px-1 text-[9px] leading-[14px] tabular-nums text-white/55"
|
||||
aria-hidden="true"
|
||||
title={`${memberCount} tracks`}
|
||||
>
|
||||
{memberCount}
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
export function TimelineGroupHeader({
|
||||
label,
|
||||
memberCount,
|
||||
@@ -95,43 +147,12 @@ export function TimelineGroupHeader({
|
||||
▸
|
||||
</span>
|
||||
</button>
|
||||
{/* The group's name IS the way into its rack. A group is an element
|
||||
carrying `data-fx-chain`, so selecting it is what puts the chain in
|
||||
the property panel — but nothing on this row said so, and the FX
|
||||
popover's footer was the only route to it. A button rather than a
|
||||
click handler on the row: it has to be reachable by keyboard, and the
|
||||
sibling controls each stopPropagation already, so widening the target
|
||||
to the whole row would only add ambiguity over their hit areas. */}
|
||||
<button
|
||||
type="button"
|
||||
tabIndex={-1}
|
||||
aria-label={`Open ${label} effects`}
|
||||
title="Open effects"
|
||||
className="flex min-w-0 flex-1 items-center gap-1.5 rounded border-0 bg-transparent p-0 text-left text-[11px] text-white hover:text-[#3CE6AC] focus-visible:outline focus-visible:outline-1 focus-visible:outline-[#3CE6AC]"
|
||||
onPointerDown={(event) => event.stopPropagation()}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
onOpenFxRack();
|
||||
}}
|
||||
>
|
||||
<span aria-hidden="true" className="shrink-0 text-[12px] leading-none text-white/50">
|
||||
▤
|
||||
</span>
|
||||
{/* Struck through, not merely dimmed — the designs are explicit that "a
|
||||
muted track that only looks dim is a track someone re-mutes by
|
||||
accident", and a muted GROUP silences every member at once, so it is
|
||||
the most expensive one to misread. */}
|
||||
<span className={`min-w-0 flex-1 truncate font-medium${hidden ? " line-through" : ""}`}>
|
||||
{label}
|
||||
</span>
|
||||
<span
|
||||
className="shrink-0 rounded-full bg-white/10 px-1 text-[9px] leading-[14px] tabular-nums text-white/55"
|
||||
aria-hidden="true"
|
||||
title={`${memberCount} tracks`}
|
||||
>
|
||||
{memberCount}
|
||||
</span>
|
||||
</button>
|
||||
<GroupNameButton
|
||||
label={label}
|
||||
memberCount={memberCount}
|
||||
hidden={hidden}
|
||||
onOpenFxRack={onOpenFxRack}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
tabIndex={-1}
|
||||
|
||||
Reference in New Issue
Block a user