From c4ac9df8cf0f493172801d79d3ab6f119328265a Mon Sep 17 00:00:00 2001 From: Carlos Valente Date: Wed, 26 Aug 2026 13:30:28 +0000 Subject: [PATCH] refactor(ui): overlay the status icons and let the preview fill the panel Three adjustments to the panel layout: - the timer status icons go back to overlaying the stage, which returns the row they were costing. They sit in the same chrome layer as the pop-out buttons, so the blackout no longer hides them - the screen state buttons group with the preview they act on, and the gap before the message inputs widens to separate the two - the stage drops its fixed aspect ratio and fills the panel width, which also removes the slack a tall panel used to leave around it Without a 16:9 frame the width derived font size can overflow a short, wide stage, so the timer is now capped by container height at the ratio the estimate assumes. In the pip window, which has no ancestor query container, both terms resolve against the viewport, so a 16:9 window is unchanged and a wider one stops clipping its digits. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_011CHxSQ6nWHuyar8feieRra --- .../message/MessageControl.module.scss | 8 ++++++ .../control/message/MessageControl.tsx | 8 ++++-- .../message/MessageControlExport.module.scss | 2 +- .../control/message/TimerPreview.module.scss | 27 +++---------------- .../features/control/message/TimerPreview.tsx | 14 ++++------ .../control/message/TimerStatus.module.scss | 5 ++++ .../src/views/editor/pip-timer/PipTimer.tsx | 4 ++- 7 files changed, 32 insertions(+), 36 deletions(-) create mode 100644 apps/client/src/features/control/message/MessageControl.module.scss diff --git a/apps/client/src/features/control/message/MessageControl.module.scss b/apps/client/src/features/control/message/MessageControl.module.scss new file mode 100644 index 000000000..427b13344 --- /dev/null +++ b/apps/client/src/features/control/message/MessageControl.module.scss @@ -0,0 +1,8 @@ +/* the screen state buttons belong with the preview they act on, not with the message inputs */ +.screenGroup { + flex: 1 1 auto; + min-height: 0; + display: flex; + flex-direction: column; + gap: $element-inner-spacing; +} diff --git a/apps/client/src/features/control/message/MessageControl.tsx b/apps/client/src/features/control/message/MessageControl.tsx index ecbab07a3..c86bb7c66 100644 --- a/apps/client/src/features/control/message/MessageControl.tsx +++ b/apps/client/src/features/control/message/MessageControl.tsx @@ -8,11 +8,15 @@ import InputRow from './InputRow'; import ScreenControl from './ScreenControl'; import TimerPreview from './TimerPreview'; +import style from './MessageControl.module.scss'; + export default function MessageControl() { return ( <> - - +
+ + +
diff --git a/apps/client/src/features/control/message/MessageControlExport.module.scss b/apps/client/src/features/control/message/MessageControlExport.module.scss index 1fa4dde5a..90b91bc01 100644 --- a/apps/client/src/features/control/message/MessageControlExport.module.scss +++ b/apps/client/src/features/control/message/MessageControlExport.module.scss @@ -18,7 +18,7 @@ display: flex; flex-direction: column; - gap: $element-spacing; + gap: $section-spacing; color: $ui-white; padding-top: $panel-top-padding; } diff --git a/apps/client/src/features/control/message/TimerPreview.module.scss b/apps/client/src/features/control/message/TimerPreview.module.scss index aa4c26658..002a8ec3e 100644 --- a/apps/client/src/features/control/message/TimerPreview.module.scss +++ b/apps/client/src/features/control/message/TimerPreview.module.scss @@ -1,36 +1,17 @@ -.preview { - flex: 1 1 auto; - min-height: 0; - display: flex; - flex-direction: column; - /* the stage caps at the panel width, so centre whatever slack a tall panel leaves */ - justify-content: center; - gap: $element-inner-spacing; -} - /* the stage is the only elastic element in the panel, the controls below it keep their size */ .stage { flex: 1 1 auto; min-height: 3rem; - /* keep the height driven frame from growing wider than the panel */ - max-height: calc(100cqw * 9 / 16); - display: grid; - place-items: center; -} - -/* the frame is a query container so that the embedded timer scales to the preview, not to the viewport */ -.stageFrame { position: relative; - container-type: inline-size; + /* a query container so that the embedded timer scales to the preview, not to the viewport */ + container-type: size; contain: paint; overflow: hidden; - aspect-ratio: 16 / 9; - height: 100%; border-radius: $component-border-radius-md; } -/* keep the pop-out affordances reachable above the blackout and message overlays */ -.stageCorners { +/* editor chrome sits above the blackout and message overlays, so it stays reachable and readable */ +.stageChrome { position: absolute; inset: 0; z-index: calc($zindex-floating + 2); diff --git a/apps/client/src/features/control/message/TimerPreview.tsx b/apps/client/src/features/control/message/TimerPreview.tsx index b7f667daa..01f81d922 100644 --- a/apps/client/src/features/control/message/TimerPreview.tsx +++ b/apps/client/src/features/control/message/TimerPreview.tsx @@ -11,16 +11,12 @@ export default function TimerPreview() { const { data } = useViewSettings(); return ( -
-
-
- -
- handleLinks('timer', event)} pipElement={} /> -
-
+
+ +
+ + handleLinks('timer', event)} pipElement={} />
-
); } diff --git a/apps/client/src/features/control/message/TimerStatus.module.scss b/apps/client/src/features/control/message/TimerStatus.module.scss index 3446e7ef9..97d1250f5 100644 --- a/apps/client/src/features/control/message/TimerStatus.module.scss +++ b/apps/client/src/features/control/message/TimerStatus.module.scss @@ -1,5 +1,10 @@ .timerStatus { + position: absolute; + top: 0; + left: 0; + margin: 0.5rem 0.25rem; display: flex; + flex-direction: column; gap: 0.25rem; } diff --git a/apps/client/src/views/editor/pip-timer/PipTimer.tsx b/apps/client/src/views/editor/pip-timer/PipTimer.tsx index a8a977947..4756596d2 100644 --- a/apps/client/src/views/editor/pip-timer/PipTimer.tsx +++ b/apps/client/src/views/editor/pip-timer/PipTimer.tsx @@ -64,7 +64,9 @@ export function PipTimer({ viewSettings }: PipTimerProps) { // gather presentation styles const resolvedTimerColour = getTimerColour(viewSettings, undefined, showWarning, showDanger); + // the estimate is tuned for a 16:9 screen, so cap it by height for containers wider than that const timerFontSize = getEstimatedFontSize(display, secondaryContent); + const timerFontRule = `min(${timerFontSize}cqw, ${((timerFontSize * 16) / 9).toFixed(2)}cqh)`; const userStyles = { ...(resolvedTimerColour && { '--timer-colour': resolvedTimerColour }), }; @@ -82,7 +84,7 @@ export function PipTimer({ viewSettings }: PipTimerProps) {
{display}