feat(studio): timeline hidden by default with toggle in header + player (#142)

## Summary

The timeline is now hidden by default. A toggle button appears in both the header (alongside panel toggles) and the player controls bar. Both sync the same state and turn teal when the timeline is visible.

## Changes

- **`timelineVisible` state** in `App.tsx`, defaults to `false`
- **Header toggle**: icon button between sidebar toggle and Renders button
- **Player controls toggle**: icon button at the right end of the controls bar
- **NLELayout**: `timelineVisible` and `onToggleTimeline` props gate the timeline + resize divider
- **Player controls stay visible**: moved from inside the timeline section to inside the preview area, so hiding the timeline doesn't hide play/seek/timecode

## Behavior

| State | Preview | Player controls | Timeline |
|---|---|---|---|
| Timeline hidden (default) | Full height |  Visible | Hidden |
| Timeline visible | Shorter |  Visible | Shown with resize handle |

Both toggle buttons show identical teal active state (`#3CE6AC/10` bg + `#3CE6AC/30` border).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
Miguel Ángel
2026-03-31 04:01:01 +02:00
committed by GitHub
parent 2f99e33bbe
commit 1bc83c62a5
4 changed files with 146 additions and 96 deletions
@@ -8,11 +8,15 @@ const SPEED_OPTIONS = [0.25, 0.5, 1, 1.5, 2] as const;
interface PlayerControlsProps {
onTogglePlay: () => void;
onSeek: (time: number) => void;
timelineVisible?: boolean;
onToggleTimeline?: () => void;
}
export const PlayerControls = memo(function PlayerControls({
onTogglePlay,
onSeek,
timelineVisible,
onToggleTimeline,
}: PlayerControlsProps) {
// Subscribe to only the fields we render — each selector prevents cascading re-renders
const isPlaying = usePlayerStore((s) => s.isPlaying);
@@ -224,6 +228,33 @@ export const PlayerControls = memo(function PlayerControls({
</div>
)}
</div>
{/* Timeline toggle */}
{onToggleTimeline !== undefined && (
<button
onClick={onToggleTimeline}
className={`w-7 h-7 flex items-center justify-center rounded-md border transition-colors ${
timelineVisible
? "text-[#3CE6AC] bg-[#3CE6AC]/10 border-[#3CE6AC]/30"
: "border-neutral-700 text-neutral-500 hover:text-neutral-300 hover:bg-neutral-800"
}`}
title={timelineVisible ? "Hide timeline" : "Show timeline"}
>
<svg
width="13"
height="13"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
>
<rect x="3" y="13" width="18" height="8" rx="1" />
<line x1="3" y1="9" x2="21" y2="9" />
<line x1="3" y1="5" x2="21" y2="5" />
</svg>
</button>
)}
</div>
);
});