mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-31 20:09:11 +00:00
feat(ui): make blink/blackout exclusive and put the buttons beside the preview
Blink and blackout are two ways of hiding the same timer, and having both on does not mean anything the audience can read differently from either alone. Turning one on now turns the other off, enforced where the two toggles are sent so the invariant holds regardless of which control calls it. The screen buttons move from a row below the stage to a column on its right, which is where they act and costs less height than a row. The stage and the button column live in a grid so the buttons can be a fixed, content-sized width instead of stretching to match the stage's height. A container query against the panel's own width collapses back to a stacked layout, buttons in a row below the stage, for a narrower fit (a resized /messagecontrol window, for instance) where the two can't sit side by side. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011CHxSQ6nWHuyar8feieRra
This commit is contained in:
@@ -51,8 +51,11 @@ export const setMessage = {
|
|||||||
timerText: (payload: string) => sendSocket('message', { timer: { text: payload } }),
|
timerText: (payload: string) => sendSocket('message', { timer: { text: payload } }),
|
||||||
timerVisible: (payload: boolean) => sendSocket('message', { timer: { visible: payload } }),
|
timerVisible: (payload: boolean) => sendSocket('message', { timer: { visible: payload } }),
|
||||||
secondaryMessage: (payload: string) => sendSocket('message', { secondary: payload }),
|
secondaryMessage: (payload: string) => sendSocket('message', { secondary: payload }),
|
||||||
timerBlink: (payload: boolean) => sendSocket('message', { timer: { blink: payload } }),
|
// blink and blackout are mutually exclusive stage states, so turning one on turns the other off
|
||||||
timerBlackout: (payload: boolean) => sendSocket('message', { timer: { blackout: payload } }),
|
timerBlink: (payload: boolean) =>
|
||||||
|
sendSocket('message', payload ? { timer: { blink: true, blackout: false } } : { timer: { blink: false } }),
|
||||||
|
timerBlackout: (payload: boolean) =>
|
||||||
|
sendSocket('message', payload ? { timer: { blackout: true, blink: false } } : { timer: { blackout: false } }),
|
||||||
timerSecondarySource: (payload: TimerMessage['secondarySource']) =>
|
timerSecondarySource: (payload: TimerMessage['secondarySource']) =>
|
||||||
sendSocket('message', { timer: { secondarySource: payload } }),
|
sendSocket('message', { timer: { secondarySource: payload } }),
|
||||||
/** returns the stage to a plain timer, keeping whatever the operator has typed */
|
/** returns the stage to a plain timer, keeping whatever the operator has typed */
|
||||||
|
|||||||
@@ -1,8 +1,18 @@
|
|||||||
/* the screen state buttons belong with the preview they act on, not with the message inputs */
|
/* the screen state buttons belong with the preview they act on, not with the message inputs.
|
||||||
|
buttons sit in a column to the right of the stage by default; once the container narrows
|
||||||
|
too far for that (e.g. an extracted window resized narrow), they drop into a row below it */
|
||||||
.screenGroup {
|
.screenGroup {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-direction: column;
|
grid-template-columns: 1fr auto;
|
||||||
gap: $element-inner-spacing;
|
grid-template-rows: 1fr;
|
||||||
|
gap: $element-spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
@container (max-width: 22rem) {
|
||||||
|
.screenGroup {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-rows: 1fr auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,16 @@
|
|||||||
.screenControl {
|
.screenControl {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-auto-flow: column;
|
grid-auto-flow: row;
|
||||||
grid-auto-columns: 1fr;
|
|
||||||
gap: $element-spacing;
|
gap: $element-spacing;
|
||||||
|
align-self: center;
|
||||||
|
width: 8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@container (max-width: 22rem) {
|
||||||
|
.screenControl {
|
||||||
|
grid-auto-flow: column;
|
||||||
|
grid-auto-columns: 1fr;
|
||||||
|
align-self: stretch;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* the stage is the only elastic element in the panel, the controls below it keep their size */
|
/* the stage is the only elastic element in the panel, the controls below it keep their size */
|
||||||
.stage {
|
.stage {
|
||||||
flex: 1 1 auto;
|
min-width: 0;
|
||||||
min-height: 3rem;
|
min-height: 3rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
/* a query container so that the embedded timer scales to the preview, not to the viewport */
|
/* a query container so that the embedded timer scales to the preview, not to the viewport */
|
||||||
|
|||||||
Reference in New Issue
Block a user