From ba91d367cfe896daab2da08965743ebca99c84b1 Mon Sep 17 00:00:00 2001 From: webadderall <131426131+webadderall@users.noreply.github.com> Date: Fri, 20 Mar 2026 13:03:26 +1100 Subject: [PATCH] Animate launch HUD transitions --- src/components/launch/LaunchWindow.module.css | 18 ++ src/components/launch/LaunchWindow.tsx | 238 ++++++++++-------- 2 files changed, 149 insertions(+), 107 deletions(-) diff --git a/src/components/launch/LaunchWindow.module.css b/src/components/launch/LaunchWindow.module.css index 2ca0623e..adc4dd6f 100644 --- a/src/components/launch/LaunchWindow.module.css +++ b/src/components/launch/LaunchWindow.module.css @@ -19,6 +19,24 @@ inset 0 1px 0 rgba(255, 255, 255, 0.04); overflow: visible; position: relative; + transform-origin: center bottom; +} + +.barStateViewport { + position: relative; + display: flex; + align-items: center; + min-height: 46px; + min-width: 0; +} + +.barState { + display: flex; + align-items: center; + gap: 8px; + white-space: nowrap; + min-width: 0; + pointer-events: auto; } .sep { diff --git a/src/components/launch/LaunchWindow.tsx b/src/components/launch/LaunchWindow.tsx index 9a16bff7..c8ec7135 100644 --- a/src/components/launch/LaunchWindow.tsx +++ b/src/components/launch/LaunchWindow.tsx @@ -1,5 +1,6 @@ import type { ReactNode } from "react"; import { useCallback, useEffect, useRef, useState } from "react"; +import { AnimatePresence, motion } from "motion/react"; import { Monitor, Mic, @@ -472,12 +473,119 @@ export function LaunchWindow() { const screenSources = sources.filter((s) => s.sourceType === "screen"); const windowSources = sources.filter((s) => s.sourceType === "window"); + const hudStateTransition = { duration: 0.24, ease: [0.22, 1, 0.36, 1] as const }; const toggleWebcam = () => { if (recording) return; toggleDropdown("webcam"); }; + const recordingControls = ( + <> +
+
+ + {paused ? t("recording.paused") : t("recording.rec")} + +
+ + + {formatTime(elapsed)} + + + + + + {microphoneEnabled ? : } + + + + + + {paused ? : } + + + + + + + window.electronAPI?.hudOverlayHide?.()} title={t("recording.hideHud")}> + + + + + + + + ); + + const idleControls = ( + <> + + + + + + {microphoneEnabled ? : } + + + + {webcamEnabled ? + + toggleDropdown("countdown")} + title={t("recording.countdownDelay")} + className={countdownDelay > 0 ? styles.ibActive : ""} + > + + + + + + + + + + toggleDropdown("more")} title={t("recording.more")}> + + + + window.electronAPI?.hudOverlayHide?.()} title={t("recording.hideHud")}> + + + + window.electronAPI?.hudOverlayClose?.()} title={t("recording.closeApp")}> + + + + ); + return (
-
-
- -
- - {recording ? ( - <> -
-
- - {paused ? t("recording.paused") : t("recording.rec")} - + +
+
- - {formatTime(elapsed)} - - - - - - {microphoneEnabled ? : } - - - - - - {paused ? : } - - - - - - - window.electronAPI?.hudOverlayHide?.()} title={t("recording.hideHud")}> - - - - - - - - ) : ( - <> - - - - - - {microphoneEnabled ? : } - - - - {webcamEnabled ? - - toggleDropdown("countdown")} - title={t("recording.countdownDelay")} - className={countdownDelay > 0 ? styles.ibActive : ""} - > - - - - - - - - - - toggleDropdown("more")} title={t("recording.more")}> - - - - window.electronAPI?.hudOverlayHide?.()} title={t("recording.hideHud")}> - - - - window.electronAPI?.hudOverlayClose?.()} title={t("recording.closeApp")}> - - - - )} -
+
+ + + {recording ? recordingControls : idleControls} + + +
+