refactor: style cleanups and migrations

fix: close modal with button
refactor: small type improvements
refactor: migrate time inputs
refactor: migrate tooltips
refactor: prevent component resizing
This commit is contained in:
Carlos Valente
2025-07-06 21:33:46 +02:00
committed by Carlos Valente
parent 6facd6a666
commit 17a7d035bf
54 changed files with 521 additions and 469 deletions
@@ -1,13 +1,12 @@
import { IoArrowDown, IoArrowUp, IoBan, IoFlag, IoTime } from 'react-icons/io5';
import { Tooltip } from '@chakra-ui/react';
import { TimerPhase, TimerType } from 'ontime-types';
import { Corner } from '../../../common/components/editor-utils/EditorUtils';
import Tooltip from '../../../common/components/tooltip/Tooltip';
import { useMessagePreview } from '../../../common/hooks/useSocket';
import useViewSettings from '../../../common/hooks-query/useViewSettings';
import { handleLinks } from '../../../common/utils/linkUtils';
import { cx, timerPlaceholder } from '../../../common/utils/styleUtils';
import { tooltipDelayMid } from '../../../ontimeConfig';
import style from './MessageControl.module.scss';
@@ -64,20 +63,45 @@ export default function TimerPreview() {
{secondary !== null && <div className={style.secondaryContent}>{secondary}</div>}
</div>
<div className={style.eventStatus}>
<Tooltip label='Time type: Count down' openDelay={tooltipDelayMid} shouldWrapChildren>
<IoArrowDown className={style.statusIcon} data-active={timerType === TimerType.CountDown} />
<Tooltip
text='Time type: Count down'
render={<span />}
className={style.statusIcon}
data-active={timerType === TimerType.CountDown}
>
<IoArrowDown />
</Tooltip>
<Tooltip label='Time type: Count up' openDelay={tooltipDelayMid} shouldWrapChildren>
<IoArrowUp className={style.statusIcon} data-active={timerType === TimerType.CountUp} />
<Tooltip
text='Time type: Count up'
render={<span />}
className={style.statusIcon}
data-active={timerType === TimerType.CountUp}
>
<IoArrowUp />
</Tooltip>
<Tooltip label='Time type: Clock' openDelay={tooltipDelayMid} shouldWrapChildren>
<IoTime className={style.statusIcon} data-active={timerType === TimerType.Clock} />
<Tooltip
text='Time type: Clock'
render={<span />}
className={style.statusIcon}
data-active={timerType === TimerType.Clock}
>
<IoTime />
</Tooltip>
<Tooltip label='Time type: None' openDelay={tooltipDelayMid} shouldWrapChildren>
<IoBan className={style.statusIcon} data-active={timerType === TimerType.None} />
<Tooltip
text='Time type: None'
render={<span />}
className={style.statusIcon}
data-active={timerType === TimerType.None}
>
<IoBan />
</Tooltip>
<Tooltip label={countToEnd ? 'Count to end' : 'Count duration'} openDelay={tooltipDelayMid} shouldWrapChildren>
<IoFlag className={style.statusIcon} data-active={countToEnd} />
<Tooltip
text={countToEnd ? 'Count to end' : 'Count duration'}
render={<span />}
className={style.statusIcon}
data-active={countToEnd}
>
<IoFlag />
</Tooltip>
</div>
</div>
@@ -4,6 +4,7 @@
}
.auxTimers {
display: flex;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 0.5rem;
}
@@ -1,12 +1,10 @@
import { IoAdd, IoRemove } from 'react-icons/io5';
import { Tooltip } from '@chakra-ui/react';
import { useLocalStorage } from '@mantine/hooks';
import { Playback } from 'ontime-types';
import { MILLIS_PER_HOUR, parseUserTime } from 'ontime-utils';
import TimeInput from '../../../../common/components/input/time-input/TimeInput';
import { setPlayback } from '../../../../common/hooks/useSocket';
import { tooltipDelayMid } from '../../../../ontimeConfig';
import TapButton from '../tap-button/TapButton';
import style from './AddTime.module.scss';
@@ -41,16 +39,12 @@ export default function AddTime(props: AddTimeProps) {
<div className={style.addTime}>
<TimeInput name='addtime' submitHandler={handleTimeChange} time={timeInMs} placeholder='Add time' />
<div className={style.addButtons}>
<Tooltip label='Remove time' openDelay={tooltipDelayMid} shouldWrapChildren>
<TapButton onClick={() => handleAddTime('remove')} disabled={doDisableButtons} className={style.tallButtons}>
<IoRemove />
</TapButton>
</Tooltip>
<Tooltip label='Add time' openDelay={tooltipDelayMid} shouldWrapChildren>
<TapButton onClick={() => handleAddTime('add')} disabled={doDisableButtons} className={style.tallButtons}>
<IoAdd />
</TapButton>
</Tooltip>
<TapButton onClick={() => handleAddTime('remove')} disabled={doDisableButtons} className={style.tallButtons}>
<IoRemove />
</TapButton>
<TapButton onClick={() => handleAddTime('add')} disabled={doDisableButtons} className={style.tallButtons}>
<IoAdd />
</TapButton>
</div>
</div>
);
@@ -22,3 +22,24 @@
gap: 0.25rem;
height: 1.5rem;
}
.fakeInput {
box-sizing: border-box;
width: 100%;
max-width: 7.5em;
height: 2rem;
display: grid;
place-content: center;
font-size: 1rem;
font-weight: 400;
color: $gray-200;
border-radius: $component-border-radius-md;
border: 1px solid transparent;
letter-spacing: 0.5px;
font-variant-numeric: tabular-nums;
padding-inline: 0.5em;
outline: none;
}
@@ -1,6 +1,6 @@
import { IoArrowDown, IoArrowUp, IoPause, IoPlay, IoStop } from 'react-icons/io5';
import { Playback, SimpleDirection, SimplePlayback } from 'ontime-types';
import { parseUserTime } from 'ontime-utils';
import { millisToString, parseUserTime } from 'ontime-utils';
import TimeInput from '../../../../common/components/input/time-input/TimeInput';
import { setAuxTimer, useAuxTimerControl, useAuxTimerTime } from '../../../../common/hooks/useSocket';
@@ -22,7 +22,7 @@ export function AuxTimer({ index }: AuxTimerProps) {
setDirection(index, newDirection);
};
const canStop = playback !== SimplePlayback.Stop;
const isActive = playback !== SimplePlayback.Stop;
const playbackAction = playback === SimplePlayback.Start ? 'pause' : 'play';
return (
@@ -30,15 +30,15 @@ export function AuxTimer({ index }: AuxTimerProps) {
Aux Timer {index}
<div className={style.controls}>
<div className={style.input}>
<AuxTimerInput index={index} />
<TapButton onClick={toggleDirection} aspect='tight'>
<AuxTimerInput index={index} isActive={isActive} />
<TapButton onClick={toggleDirection} aspect='tight' disabled={isActive}>
{direction === SimpleDirection.CountDown && <IoArrowDown data-testid={`aux-timer-direction-${index}`} />}
{direction === SimpleDirection.CountUp && <IoArrowUp data-testid={`aux-timer-direction-${index}`} />}
</TapButton>
</div>
<div className={style.twoSides}>
<AuxTogglePlay index={index} action={playbackAction} />
<TapButton onClick={() => stop(index)} theme={Playback.Stop} disabled={!canStop}>
<TapButton onClick={() => stop(index)} theme={Playback.Stop} disabled={!isActive}>
<IoStop data-testid={`aux-timer-stop-${index}`} />
</TapButton>
</div>
@@ -47,11 +47,12 @@ export function AuxTimer({ index }: AuxTimerProps) {
);
}
interface AuxTimerInput {
interface AuxTimerInputProps {
index: number;
isActive: boolean;
}
function AuxTimerInput({ index }: AuxTimerProps) {
function AuxTimerInput({ index, isActive }: AuxTimerInputProps) {
const newTimeInMs = useAuxTimerTime(index);
const { setDuration } = setAuxTimer;
@@ -60,6 +61,14 @@ function AuxTimerInput({ index }: AuxTimerProps) {
setDuration(index, newTimeInMs);
};
if (isActive) {
return (
<div className={style.fakeInput} data-testid={`time-label-aux${index}`}>
{millisToString(newTimeInMs)}
</div>
);
}
return (
<TimeInput submitHandler={handleTimeUpdate} name={`aux${index}`} time={newTimeInMs} placeholder={`Aux ${index}`} />
);
@@ -1,11 +1,9 @@
import { useMemo } from 'react';
import { IoPause, IoPlay, IoPlaySkipBack, IoPlaySkipForward, IoReload, IoStop, IoTime } from 'react-icons/io5';
import { Tooltip } from '@chakra-ui/react';
import { Playback, TimerPhase } from 'ontime-types';
import { validatePlayback } from 'ontime-utils';
import { setPlayback } from '../../../../common/hooks/useSocket';
import { tooltipDelayMid } from '../../../../ontimeConfig';
import TapButton from '../tap-button/TapButton';
import style from './PlaybackButtons.module.scss';
@@ -66,31 +64,23 @@ export default function PlaybackButtons(props: PlaybackButtonsProps) {
</TapButton>
</div>
<div className={style.transportContainer}>
<Tooltip label='Previous event' openDelay={tooltipDelayMid}>
<TapButton onClick={setPlayback.previous} disabled={disablePrev}>
<IoPlaySkipBack />
</TapButton>
</Tooltip>
<Tooltip label='Next event' openDelay={tooltipDelayMid}>
<TapButton onClick={setPlayback.next} disabled={disableNext}>
<IoPlaySkipForward />
</TapButton>
</Tooltip>
<TapButton onClick={setPlayback.previous} disabled={disablePrev}>
<IoPlaySkipBack />
</TapButton>
<TapButton onClick={setPlayback.next} disabled={disableNext}>
<IoPlaySkipForward />
</TapButton>
</div>
<div className={style.extra}>
<TapButton onClick={setPlayback.roll} disabled={disableRoll} theme={Playback.Roll} active={isRolling}>
<IoTime />
</TapButton>
<Tooltip label='Reload event' openDelay={tooltipDelayMid}>
<TapButton onClick={setPlayback.reload} disabled={disableReload}>
<IoReload className={style.invertX} />
</TapButton>
</Tooltip>
<Tooltip label='Unload Event' openDelay={tooltipDelayMid}>
<TapButton onClick={setPlayback.stop} disabled={disableStop} theme={Playback.Stop}>
<IoStop />
</TapButton>
</Tooltip>
<TapButton onClick={setPlayback.reload} disabled={disableReload}>
<IoReload className={style.invertX} />
</TapButton>
<TapButton onClick={setPlayback.stop} disabled={disableStop} theme={Playback.Stop}>
<IoStop />
</TapButton>
</div>
</div>
);
@@ -1,9 +1,9 @@
import { PropsWithChildren } from 'react';
import { Tooltip } from '@chakra-ui/react';
import { MaybeNumber, Playback, TimerPhase } from 'ontime-types';
import { dayInMs, millisToString } from 'ontime-utils';
import AppLink from '../../../../common/components/link/app-link/AppLink';
import Tooltip from '../../../../common/components/tooltip/Tooltip';
import { useTimer } from '../../../../common/hooks/useSocket';
import useReport from '../../../../common/hooks-query/useReport';
import { formatDuration } from '../../../../common/utils/time';
@@ -43,13 +43,9 @@ export default function PlaybackTimer(props: PropsWithChildren<PlaybackTimerProp
return (
<div className={style.timeContainer}>
<div className={style.indicators}>
<Tooltip label={rollLabel}>
<div className={style.indicatorRoll} data-active={isRolling} />
</Tooltip>
<Tooltip text={rollLabel} render={<div />} className={style.indicatorRoll} data-active={isRolling} />
<div className={style.indicatorNegative} data-active={isOvertime} />
<Tooltip label={addedTimeLabel}>
<div className={style.indicatorDelay} data-active={hasAddedTime} />
</Tooltip>
<Tooltip text={addedTimeLabel} render={<div />} className={style.indicatorDelay} data-active={hasAddedTime} />
</div>
<TimerDisplay time={isWaiting ? timer.secondaryTimer : timer.current} />
<div className={style.status}>