From 6b59004de2dd233ce32ae2cb0743b3867c154d41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20=C3=81ngel?= Date: Tue, 29 Sep 2026 01:21:14 +0000 Subject: [PATCH] feat(studio): one timeline tool picker with select leftward and rightward (#4714) * feat(studio): one timeline tool picker with select leftward and rightward The Selection and Razor buttons become one button showing the active tool, with a menu: Select (V), Split (B), Select leftward ([) and Select rightward (]). Leftward and rightward select every clip, on every track, that starts before or at/after the playhead. * test(studio): toolbar order and label follow the tool picker * fix(studio): select leftward and rightward use the live playhead and the usual selection resets * style(studio): keep playerStore's comment share at its base --- .../TimelineHistoryButtons.dom.test.tsx | 17 +++- .../src/components/TimelineToolPicker.tsx | 90 +++++++++++++++++++ .../studio/src/components/TimelineToolbar.tsx | 29 +----- .../studio/src/hooks/appHotkeysDispatch.ts | 8 ++ .../studio/src/hooks/useAppHotkeys.test.ts | 59 +++++++++++- .../src/player/components/studioShortcuts.ts | 2 + .../studio/src/player/store/playerStore.ts | 16 ++++ 7 files changed, 190 insertions(+), 31 deletions(-) create mode 100644 packages/studio/src/components/TimelineToolPicker.tsx diff --git a/packages/studio/src/components/TimelineHistoryButtons.dom.test.tsx b/packages/studio/src/components/TimelineHistoryButtons.dom.test.tsx index 34346678a1..76d61a61fb 100644 --- a/packages/studio/src/components/TimelineHistoryButtons.dom.test.tsx +++ b/packages/studio/src/components/TimelineHistoryButtons.dom.test.tsx @@ -96,14 +96,25 @@ it("leaves enabled buttons without the disabled attribute", () => { expect(el.className).not.toContain("cursor-not-allowed"); }); -it("orders the toolbar Undo, Redo, Select, Razor", () => { +it("orders the toolbar Undo, Redo, then the tool picker showing the active tool", () => { const host = mount(); const labels = Array.from(host.querySelectorAll("button")) .map((b) => b.getAttribute("aria-label")) .filter((l) => l !== null) - .slice(0, 4); + .slice(0, 3); - expect(labels).toEqual(["Undo", "Redo", "Selection tool", "Razor tool"]); + expect(labels).toEqual(["Undo", "Redo", "Timeline tool: Select"]); +}); + +it("shows the Split tool on the picker while the razor is active", async () => { + const { usePlayerStore } = await import("../player"); + usePlayerStore.setState({ activeTool: "razor" }); + try { + const host = mount(); + expect(host.querySelector('button[aria-label="Timeline tool: Split"]')).not.toBeNull(); + } finally { + usePlayerStore.setState({ activeTool: "select" }); + } }); it("classifies Undo and Redo for the hotkey filters at their new location (KTD13)", () => { diff --git a/packages/studio/src/components/TimelineToolPicker.tsx b/packages/studio/src/components/TimelineToolPicker.tsx new file mode 100644 index 0000000000..0d2b587c3f --- /dev/null +++ b/packages/studio/src/components/TimelineToolPicker.tsx @@ -0,0 +1,90 @@ +import type { ReactNode } from "react"; +import { ArrowLineLeft, ArrowLineRight, CaretDown } from "@phosphor-icons/react"; +import { usePlayerStore } from "../player"; +import { Scissors } from "../icons/SystemIcons"; +import { Menu, MenuItem } from "./ui"; +import { cn } from "./ui/cn"; +import { flatIdle } from "./timelineToolbarStyles"; + +function SelectIcon() { + return ( + + ); +} + +interface ToolRow { + label: string; + shortcut: string; + icon: ReactNode; + active: boolean; + run: () => void; +} + +/** One button for the active timeline tool; its menu switches tools or selects clips around the playhead. */ +export function TimelineToolPicker() { + const activeTool = usePlayerStore((s) => s.activeTool); + const store = () => usePlayerStore.getState(); + const rows: ToolRow[] = [ + { + label: "Select", + shortcut: "V", + icon: , + active: activeTool === "select", + run: () => store().setActiveTool("select"), + }, + { + label: "Split", + shortcut: "B", + icon: , + active: activeTool === "razor", + run: () => store().setActiveTool("razor"), + }, + { + label: "Select leftward", + shortcut: "[", + icon: