From 239ea1aecd8ae6e67e0e7958e33c217410c86549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20=C3=81ngel?= Date: Sun, 4 Oct 2026 02:16:53 +0000 Subject: [PATCH] feat(studio): a host can put its own controls before the timeline's thumbnails toggle (#4973) * feat(studio): a host can put its own controls before the timeline's thumbnails toggle * fix(studio): keep the toolbar under the comment ratchet --- .../studio/src/components/TimelineToolbar.test.tsx | 14 ++++++++++++++ packages/studio/src/components/TimelineToolbar.tsx | 5 ++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/studio/src/components/TimelineToolbar.test.tsx b/packages/studio/src/components/TimelineToolbar.test.tsx index d9de1d7fe4..050c364613 100644 --- a/packages/studio/src/components/TimelineToolbar.test.tsx +++ b/packages/studio/src/components/TimelineToolbar.test.tsx @@ -422,3 +422,17 @@ describe("TimelineToolbar Linked Selection", () => { act(() => useLinkedClipPreferences.getState().setSyncIndicatorsVisible(true)); }); }); + +describe("TimelineToolbar — host right actions", () => { + it("draws the host's controls immediately before the thumbnails toggle", () => { + const { host, root } = renderToolbar(undefined, { + rightActions: , + }); + const buttons = [...host.querySelectorAll("button")]; + const script = buttons.findIndex((b) => b.textContent === "Script"); + const thumbs = buttons.findIndex((b) => b.getAttribute("aria-label")?.includes("thumbnails")); + expect(script).toBeGreaterThan(-1); + expect(thumbs).toBe(script + 1); + act(() => root.unmount()); + }); +}); diff --git a/packages/studio/src/components/TimelineToolbar.tsx b/packages/studio/src/components/TimelineToolbar.tsx index dfa9dbe937..56336b1f4f 100644 --- a/packages/studio/src/components/TimelineToolbar.tsx +++ b/packages/studio/src/components/TimelineToolbar.tsx @@ -1,4 +1,4 @@ -import { memo, useEffect, useRef } from "react"; +import { memo, useEffect, useRef, type ReactNode } from "react"; import { ArrowsOutLineHorizontal, Image, @@ -50,6 +50,7 @@ export interface TimelineToolbarProps { showAddBeat?: boolean; /** Hides Add keyframe and auto-record, and turns off auto-record and the K shortcut with them. */ showKeyframes?: boolean; + rightActions?: ReactNode; } interface KeyframeToggleState { @@ -149,6 +150,7 @@ export const TimelineToolbar = memo(function TimelineToolbar({ showSelectAroundPlayhead = true, showAddBeat = true, showKeyframes = true, + rightActions, }: TimelineToolbarProps) { const timelineSnapEnabled = usePlayerStore((s) => s.timelineSnapEnabled); const setTimelineSnapEnabled = usePlayerStore((s) => s.setTimelineSnapEnabled); @@ -460,6 +462,7 @@ export const TimelineToolbar = memo(function TimelineToolbar({ })()}
+ {rightActions}