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
@@ -6,6 +6,7 @@ $skip-opacity: 0.2;
@include block-styling;
background-color: $block-bg;
margin-block: 0.25rem;
overflow: initial;
display: grid;
grid-template-areas:
@@ -15,7 +16,7 @@ $skip-opacity: 0.2;
'binder pb-actions estatus estatus'
'binder ... ... ...';
grid-template-columns: $block-binder-width 3rem 1fr auto;
grid-template-columns: $block-binder-width 3rem 1fr 3rem;
grid-template-rows: 0.125rem 2rem 2rem auto 0.125rem;
align-items: center;
padding-right: $block-clearance;
@@ -92,11 +93,10 @@ $skip-opacity: 0.2;
position: relative;
cursor: pointer;
border-radius: $block-border-radius 0 0 $block-border-radius;
background-color: $gray-1050; // to override inline
color: $section-white;
font-size: 1rem;
border-radius: 3px 0 0 3px;
.drag {
@include drag-style;
@@ -10,11 +10,10 @@ import {
IoPlaySkipForward,
IoTime,
} from 'react-icons/io5';
import { Tooltip } from '@chakra-ui/react';
import { EndAction, Playback, TimerType, TimeStrategy } from 'ontime-types';
import Tooltip from '../../../common/components/tooltip/Tooltip';
import { cx } from '../../../common/utils/styleUtils';
import { tooltipDelayMid } from '../../../ontimeConfig';
import EditableBlockTitle from '../common/EditableBlockTitle';
import TimeInputFlow from '../time-input-flow/TimeInputFlow';
@@ -137,25 +136,17 @@ function RundownEventInner({
{loaded && <EventBlockProgressBar />}
</div>
<div className={style.eventStatus} tabIndex={-1}>
<Tooltip label={`Time type: ${timerType}`} openDelay={tooltipDelayMid}>
<span>
<TimerIcon type={timerType} className={style.statusIcon} />
</span>
<Tooltip text={`Time type: ${timerType}`} render={<span />}>
<TimerIcon type={timerType} className={style.statusIcon} />
</Tooltip>
<Tooltip label={`End action: ${endAction}`} openDelay={tooltipDelayMid}>
<span>
<EndActionIcon action={endAction} className={style.statusIcon} />
</span>
<Tooltip text={`End action: ${endAction}`} render={<span />}>
<EndActionIcon action={endAction} className={style.statusIcon} />
</Tooltip>
<Tooltip label={`${countToEnd ? 'Count to End' : 'Count duration'}`} openDelay={tooltipDelayMid}>
<span>
<IoFlag className={`${style.statusIcon} ${countToEnd ? style.active : style.disabled}`} />
</span>
<Tooltip text={`${countToEnd ? 'Count to End' : 'Count duration'}`} render={<span />}>
<IoFlag className={`${style.statusIcon} ${countToEnd ? style.active : style.disabled}`} />
</Tooltip>
<Tooltip label='Event has Triggers' openDelay={tooltipDelayMid}>
<span>
<IoFlash className={`${style.statusIcon} ${hasTriggers ? style.active : style.disabled}`} />
</span>
<Tooltip text='Event has Triggers' render={<span />}>
<IoFlash className={`${style.statusIcon} ${hasTriggers ? style.active : style.disabled}`} />
</Tooltip>
</div>
</div>
@@ -5,7 +5,7 @@ $gap-left: calc(2rem + 0.25rem + 3rem);
font-size: calc(1rem - 5px);
position: absolute;
top: -1em;
z-index: $zindex-floating;;
z-index: $zindex-floating;
margin-left: $gap-left;
display: flex;
@@ -1,11 +1,9 @@
.chip {
background-color: $gray-1100;
white-space: nowrap;
font-size: calc(1rem - 3px);
color: $label-gray;
padding: 0.125rem 0.5rem;
border-radius: 2px;
justify-self: end;
&.over {
color: $ontime-delay-text;
@@ -1,13 +1,12 @@
import { useMemo } from 'react';
import { IoCheckmarkCircle } from 'react-icons/io5';
import { Tooltip } from '@chakra-ui/react';
import { isPlaybackActive, MILLIS_PER_MINUTE, MILLIS_PER_SECOND } from 'ontime-utils';
import Tooltip from '../../../../common/components/tooltip/Tooltip';
import { usePlayback } from '../../../../common/hooks/useSocket';
import useReport from '../../../../common/hooks-query/useReport';
import { cx } from '../../../../common/utils/styleUtils';
import { formatDuration, formatTime, useTimeUntilStart } from '../../../../common/utils/time';
import { tooltipDelayFast } from '../../../../ontimeConfig';
import style from './RundownEventChip.module.scss';
@@ -39,7 +38,7 @@ export default function RundownEventChip({
const { playback } = usePlayback();
if (isLoaded) {
return null; //TODO: the is a small flash of 'DUE' on the loaded event as clock data arrives before isLoaded propagates
return null;
}
const playbackActive = isPlaybackActive(playback);
@@ -51,16 +50,14 @@ export default function RundownEventChip({
if (playbackActive) {
// we extracted the component to avoid unnecessary calculations and re-renders
return (
<Tooltip label='Expected time until start' openDelay={tooltipDelayFast}>
<div className={className}>
<EventUntil
timeStart={timeStart}
delay={delay}
dayOffset={dayOffset}
totalGap={totalGap}
isLinkedToLoaded={isLinkedToLoaded}
/>
</div>
<Tooltip text='Expected time until start' render={<span />} className={className}>
<EventUntil
timeStart={timeStart}
delay={delay}
dayOffset={dayOffset}
totalGap={totalGap}
isLinkedToLoaded={isLinkedToLoaded}
/>
</Tooltip>
);
}
@@ -113,7 +110,7 @@ function EventReport(props: EventReportProps) {
const absDifference = Math.abs(difference);
if (absDifference < MILLIS_PER_SECOND) {
return ['ontime', 'ontime', 'Event finished ontime'];
return ['ontime', 'under', 'Event finished on time'];
}
const isOver = difference > 0;
@@ -131,10 +128,8 @@ function EventReport(props: EventReportProps) {
}
return (
<Tooltip label={tooltip} openDelay={tooltipDelayFast}>
<div className={cx([style.chip, style[overUnderStyle], className])}>
{value === 'ontime' ? <IoCheckmarkCircle size='1.1rem' /> : value}
</div>
<Tooltip text={tooltip} render={<span />} className={cx([style.chip, style[overUnderStyle], className])}>
{value === 'ontime' ? <IoCheckmarkCircle size='1.1rem' /> : value}
</Tooltip>
);
}
@@ -1,28 +1,13 @@
import { memo, MouseEvent } from 'react';
import { IoPause, IoPlay, IoReload, IoRemoveCircle, IoRemoveCircleOutline } from 'react-icons/io5';
import TooltipActionBtn from '../../../../common/components/buttons/TooltipActionBtn';
import IconButton from '../../../../common/components/buttons/IconButton';
import Tooltip from '../../../../common/components/tooltip/Tooltip';
import { useEntryActions } from '../../../../common/hooks/useEntryAction';
import { setEventPlayback } from '../../../../common/hooks/useSocket';
import { tooltipDelayMid } from '../../../../ontimeConfig';
import style from '../RundownEvent.module.scss';
const blockBtnStyle = {
size: 'sm',
};
type StyleVariant = {
'aria-label': string;
tooltip: string;
backgroundColor: string;
_hover: { backgroundColor?: string };
};
const tooltipProps = {
openDelay: tooltipDelayMid,
};
interface RundownEventPlaybackProps {
eventId: string;
skip: boolean;
@@ -67,67 +52,66 @@ function RundownEventPlayback({
setEventPlayback.loadEvent(eventId);
};
const buttonVariant: Partial<StyleVariant> = {};
if (isPaused) {
// continue
buttonVariant['aria-label'] = 'Continue event';
buttonVariant.tooltip = 'Continue event';
buttonVariant.backgroundColor = '#339E4E';
buttonVariant._hover = { backgroundColor: '#339E4Eee' };
} else if (isPlaying) {
// pause
buttonVariant['aria-label'] = 'Pause event';
buttonVariant.tooltip = 'Pause event';
buttonVariant.backgroundColor = '#c05621';
buttonVariant._hover = { backgroundColor: '#c05621ee' };
} else {
// start
buttonVariant['aria-label'] = 'Start event';
buttonVariant.tooltip = 'Start event';
if (!disablePlayback) {
buttonVariant._hover = { backgroundColor: '#339E4E' };
const playButtonStyles: { tooltip: string; backgroundColor: string | undefined } = (() => {
if (isPaused) {
return {
tooltip: 'Continue event',
backgroundColor: '#339E4E',
};
}
}
if (isPlaying) {
return {
tooltip: 'Pause event',
backgroundColor: '#c05621',
};
}
return {
tooltip: 'Start event',
backgroundColor: undefined,
};
})();
return (
<div className={style.playbackActions}>
<TooltipActionBtn
variant='ontime-subtle-white'
<Tooltip
text='Skip event'
render={<IconButton variant='subtle-white' />}
onClick={toggleSkip}
tabIndex={-1}
disabled={loaded}
style={{
background: skip ? '#9A0000' : undefined,
}}
aria-label='Skip event'
tooltip='Skip event'
icon={skip ? <IoRemoveCircle /> : <IoRemoveCircleOutline />}
backgroundColor={skip ? '#B20000' : undefined}
_hover={{ backgroundColor: '#FF7878' }}
{...tooltipProps}
{...blockBtnStyle}
clickHandler={toggleSkip}
>
{skip ? <IoRemoveCircle /> : <IoRemoveCircleOutline />}
</Tooltip>
<Tooltip
text='Load event'
render={<IconButton variant='subtle-white' />}
onClick={load}
tabIndex={-1}
isDisabled={loaded}
/>
<TooltipActionBtn
variant='ontime-subtle-white'
disabled={disablePlayback}
aria-label='Load event'
tooltip='Load event'
icon={<IoReload className={style.flip} />}
isDisabled={disablePlayback}
{...tooltipProps}
{...blockBtnStyle}
clickHandler={load}
>
<IoReload className={style.flip} />
</Tooltip>
<Tooltip
text={playButtonStyles.tooltip}
render={<IconButton variant='subtle-white' />}
onClick={actionHandler}
tabIndex={-1}
/>
<TooltipActionBtn
variant='ontime-subtle-white'
aria-label='Start event'
tooltip='Start event'
icon={!isPlaying ? <IoPlay /> : <IoPause />}
isDisabled={disablePlayback}
{...tooltipProps}
{...blockBtnStyle}
{...buttonVariant}
clickHandler={actionHandler}
tabIndex={-1}
/>
disabled={disablePlayback}
style={{
backgroundColor: playButtonStyles.backgroundColor,
}}
aria-label={isPlaying ? 'Pause event' : 'Start event'}
>
{!isPlaying ? <IoPlay /> : <IoPause />}
</Tooltip>
</div>
);
}