mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-08 17:03:53 +00:00
refactor: small style tweaks
refactor: consistent font size on inputs refactor: style tweaks for block spacing refactor: improve skipped styles fix: improve responsiveness in extracted rundown refactor: style tweaks to overview refactor: simplify group target duration
This commit is contained in:
committed by
Carlos Valente
parent
524721002a
commit
a358ec0f17
@@ -9,7 +9,7 @@ import style from './TimeInput.module.scss';
|
||||
interface NullableTimeInputProps<T extends string> {
|
||||
id?: T;
|
||||
name: T;
|
||||
submitHandler: (field: T, value: string) => void;
|
||||
submitHandler: (field: T, value: number) => void;
|
||||
time?: number | null;
|
||||
emptyDisplay: string;
|
||||
placeholder?: string;
|
||||
@@ -71,7 +71,7 @@ export default function NullableTimeInput<T extends string>({
|
||||
return false;
|
||||
}
|
||||
|
||||
submitHandler(name, newValue);
|
||||
submitHandler(name, valueInMillis);
|
||||
return true;
|
||||
},
|
||||
[name, submitHandler, time],
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
border: 1px solid transparent;
|
||||
|
||||
padding-inline: 0.5rem;
|
||||
font-size: calc(1rem - 2px);
|
||||
white-space: nowrap;
|
||||
|
||||
&:hover:not([data-disabled]) {
|
||||
@@ -57,7 +56,7 @@
|
||||
}
|
||||
|
||||
.popup {
|
||||
font-size: calc(1rem - 2px);
|
||||
font-size: 1rem;
|
||||
background-color: $gray-1200;
|
||||
box-sizing: border-box;
|
||||
padding: 2px;
|
||||
|
||||
@@ -19,7 +19,7 @@ export function getOffsetText(offset: MaybeNumber): string {
|
||||
}
|
||||
|
||||
export function getOffsetState(offset: MaybeNumber): 'over' | 'under' | 'muted' | null {
|
||||
if (offset === null) return null;
|
||||
if (offset === 0) return 'muted';
|
||||
if (offset === null) return 'muted';
|
||||
if (offset === 0) return null;
|
||||
return offset < 0 ? 'over' : 'under';
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ export function OffsetOverview() {
|
||||
|
||||
const isPlaying = isPlaybackActive(playback);
|
||||
const correctedOffset = offset * -1;
|
||||
const offsetState = getOffsetState(offset);
|
||||
const offsetState = getOffsetState(isPlaying ? offset : null);
|
||||
const offsetText = getOffsetText(isPlaying ? correctedOffset : null);
|
||||
|
||||
return <OverUnder state={offsetState} value={offsetText} testId='offset' />;
|
||||
|
||||
@@ -9,14 +9,11 @@
|
||||
letter-spacing: 0.5px;
|
||||
min-width: 5em;
|
||||
font-variant-numeric: tabular-nums;
|
||||
color: $ui-white;
|
||||
|
||||
&::after {
|
||||
content: '\200b';
|
||||
}
|
||||
|
||||
&.muted {
|
||||
color: $muted-gray;
|
||||
}
|
||||
}
|
||||
|
||||
.column {
|
||||
@@ -32,7 +29,7 @@
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
&[data-state="over"] {
|
||||
&[data-state='over'] {
|
||||
.label .over {
|
||||
color: $playback-over;
|
||||
}
|
||||
@@ -41,7 +38,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&[data-state="under"] {
|
||||
&[data-state='under'] {
|
||||
.label .under {
|
||||
color: $playback-under;
|
||||
}
|
||||
@@ -50,7 +47,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&[data-state="muted"] {
|
||||
&[data-state='muted'] {
|
||||
.clock {
|
||||
color: $muted-gray;
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ interface TimeLayoutProps {
|
||||
|
||||
export function TimeColumn({ label, value, muted, className, testId }: TimeLayoutProps) {
|
||||
return (
|
||||
<div className={style.column}>
|
||||
<div className={style.column} data-state={muted ? 'muted' : 'active'}>
|
||||
<span className={style.label}>{label}</span>
|
||||
<span className={cx([style.clock, muted && style.muted, className])} data-testid={testId}>
|
||||
<span className={cx([style.clock, className])} data-testid={testId}>
|
||||
{value}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -42,8 +42,8 @@ import { AppMode, sessionKeys } from '../../ontimeConfig';
|
||||
|
||||
import QuickAddButtons from './entry-editor/quick-add-buttons/QuickAddButtons';
|
||||
import QuickAddInline from './entry-editor/quick-add-cursor/QuickAddInline';
|
||||
import BlockEnd from './rundown-block/BlockEnd';
|
||||
import RundownBlock from './rundown-block/RundownBlock';
|
||||
import RundownBlockEnd from './rundown-block/RundownBlockEnd';
|
||||
import { canDrop, makeRundownMetadata, makeSortableList } from './rundown.utils';
|
||||
import RundownEmpty from './RundownEmpty';
|
||||
import { useEventSelection } from './useEventSelection';
|
||||
@@ -444,20 +444,23 @@ export default function Rundown({ data }: RundownProps) {
|
||||
|
||||
if (isBlockCollapsed) {
|
||||
return null;
|
||||
} else {
|
||||
const parentColour = (entries[parentId] as OntimeBlock | undefined)?.colour;
|
||||
// if the previous element is selected, it will have its own QuickAddInline
|
||||
// we use thisId instead of previousEntryId because the block end does not process
|
||||
// and it does not cause the reassignment of the iteration id to the previous entry
|
||||
return (
|
||||
<Fragment key={entryId}>
|
||||
{isEditMode && rundownMetadata.groupEntries === 0 && (
|
||||
<QuickAddButtons previousEventId={null} parentBlock={parentId} backgroundColor={parentColour} />
|
||||
)}
|
||||
<BlockEnd key={entryId} id={entryId} colour={parentColour} />
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
// if the previous element is selected, it will have its own QuickAddInline
|
||||
// we use thisId instead of previousEntryId because the block end does not process
|
||||
// and it does not cause the reassignment of the iteration id to the previous entry
|
||||
return (
|
||||
<Fragment key={entryId}>
|
||||
{isEditMode && rundownMetadata.groupEntries === 0 && (
|
||||
<QuickAddButtons
|
||||
previousEventId={null}
|
||||
parentBlock={parentId}
|
||||
backgroundColor={rundownMetadata.groupColour}
|
||||
/>
|
||||
)}
|
||||
<RundownBlockEnd key={entryId} id={entryId} colour={rundownMetadata.groupColour} />
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
// we iterate through a stateful copy of order to make the dnd operations smoother
|
||||
|
||||
@@ -37,7 +37,7 @@ function RundownExport() {
|
||||
>
|
||||
<FinderPlacement />
|
||||
<ViewNavigationMenu suppressSettings />
|
||||
<div className={style.content}>
|
||||
<div className={style.rundown}>
|
||||
<ErrorBoundary>
|
||||
<RundownContextMenu>
|
||||
<RundownWrapper isSmallDevice />
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
import { useCallback } from 'react';
|
||||
import { OntimeBlock } from 'ontime-types';
|
||||
import { millisToString, parseUserTime } from 'ontime-utils';
|
||||
import { MaybeNumber, OntimeBlock } from 'ontime-types';
|
||||
import { millisToString } from 'ontime-utils';
|
||||
|
||||
import * as Editor from '../../../common/components/editor-utils/EditorUtils';
|
||||
import SwatchSelect from '../../../common/components/input/colour-input/SwatchSelect';
|
||||
import NullableTimeInput from '../../../common/components/input/time-input/NullableTimeInput';
|
||||
import AppLink from '../../../common/components/link/app-link/AppLink';
|
||||
import { useEntryActions } from '../../../common/hooks/useEntryAction';
|
||||
import useCustomFields from '../../../common/hooks-query/useCustomFields';
|
||||
import { getOffsetState } from '../../../common/utils/offset';
|
||||
import { enDash, timerPlaceholder } from '../../../common/utils/styleUtils';
|
||||
import { cx, enDash, timerPlaceholder } from '../../../common/utils/styleUtils';
|
||||
import TextLikeInput from '../../../views/cuesheet/cuesheet-table/cuesheet-table-elements/TextLikeInput';
|
||||
|
||||
import EntryEditorCustomFields from './composite/EventEditorCustomFields';
|
||||
import EventTextArea from './composite/EventTextArea';
|
||||
import EntryEditorTextInput from './composite/EventTextInput';
|
||||
import TargetDurationInput from './composite/TargetDurationInput';
|
||||
|
||||
import style from './EntryEditor.module.scss';
|
||||
|
||||
// title + colour + custom field labels
|
||||
export type BlockEditorUpdateTextFields = 'targetDuration' | 'title' | 'colour' | string;
|
||||
export type BlockEditorUpdateTextFields = 'title' | 'colour' | string;
|
||||
export type BlockEditorUpdateMaybeNumberFields = 'targetDuration';
|
||||
|
||||
interface BlockEditorProps {
|
||||
@@ -31,7 +31,7 @@ export default function BlockEditor({ block }: BlockEditorProps) {
|
||||
const { updateEntry } = useEntryActions();
|
||||
|
||||
const handleSubmit = useCallback(
|
||||
(field: BlockEditorUpdateTextFields | BlockEditorUpdateMaybeNumberFields, value: string | boolean) => {
|
||||
(field: BlockEditorUpdateTextFields | BlockEditorUpdateMaybeNumberFields, value: string | MaybeNumber) => {
|
||||
// Handle custom fields
|
||||
if (typeof field === 'string' && field.startsWith('custom-')) {
|
||||
const fieldLabel = field.split('custom-')[1];
|
||||
@@ -40,11 +40,7 @@ export default function BlockEditor({ block }: BlockEditorProps) {
|
||||
}
|
||||
|
||||
if (field === 'targetDuration') {
|
||||
if (value === '') {
|
||||
return updateEntry({ id: block.id, targetDuration: null });
|
||||
}
|
||||
|
||||
return updateEntry({ id: block.id, targetDuration: parseUserTime(value as string) });
|
||||
return updateEntry({ id: block.id, targetDuration: value as MaybeNumber });
|
||||
}
|
||||
|
||||
// all other strings are text fields
|
||||
@@ -85,22 +81,22 @@ export default function BlockEditor({ block }: BlockEditorProps) {
|
||||
</div>
|
||||
</div>
|
||||
<div className={style.inline}>
|
||||
<div>
|
||||
<Editor.Label htmlFor='targetDuration'>Target duration</Editor.Label>
|
||||
<NullableTimeInput
|
||||
name='targetDuration'
|
||||
time={block.targetDuration}
|
||||
submitHandler={handleSubmit}
|
||||
emptyDisplay={enDash}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Editor.Label htmlFor='eventId'>Plan offset</Editor.Label>
|
||||
<TextLikeInput offset={planOffsetLabel} className={style.textLikeInput} tabIndex={-1}>
|
||||
<TextLikeInput
|
||||
offset={planOffsetLabel}
|
||||
className={cx([style.textLikeInput, planOffset === null && style.inactive])}
|
||||
tabIndex={-1}
|
||||
>
|
||||
{planOffset !== null && planOffset > 0 ? '+' : ''}
|
||||
{millisToString(planOffset, { fallback: enDash })}
|
||||
</TextLikeInput>
|
||||
</div>
|
||||
<TargetDurationInput
|
||||
duration={block.duration}
|
||||
targetDuration={block.targetDuration}
|
||||
submitHandler={handleSubmit}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -94,16 +94,21 @@
|
||||
|
||||
/* approximating the style of a disabled input */
|
||||
.textLikeInput {
|
||||
background-color: rgba($gray-1200, 0.4);
|
||||
font-weight: 400;
|
||||
color: $gray-200;
|
||||
border: 1px solid transparent;
|
||||
|
||||
justify-content: center;
|
||||
|
||||
background: transparent;
|
||||
justify-content: start;
|
||||
width: 7.5em;
|
||||
border: 1px solid transparent;
|
||||
border-bottom: 1px solid $gray-1100;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba($gray-1200, 0.4);
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.inactive {
|
||||
color: $muted-gray;
|
||||
}
|
||||
|
||||
.active {
|
||||
color: $active-indicator;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import { IoLockClosed, IoLockOpenOutline } from 'react-icons/io5';
|
||||
import { MaybeNumber } from 'ontime-types';
|
||||
|
||||
import IconButton from '../../../../common/components/buttons/IconButton';
|
||||
import * as Editor from '../../../../common/components/editor-utils/EditorUtils';
|
||||
import NullableTimeInput from '../../../../common/components/input/time-input/NullableTimeInput';
|
||||
import Tooltip from '../../../../common/components/tooltip/Tooltip';
|
||||
import { cx, enDash } from '../../../../common/utils/styleUtils';
|
||||
import TimeInputGroup from '../../time-input-flow/TimeInputGroup';
|
||||
|
||||
import style from '../EntryEditor.module.scss';
|
||||
|
||||
interface TargetDurationInputProps {
|
||||
duration: MaybeNumber;
|
||||
targetDuration: MaybeNumber;
|
||||
submitHandler: (field: 'targetDuration', value: MaybeNumber) => void;
|
||||
}
|
||||
|
||||
export default function TargetDurationInput({ duration, targetDuration, submitHandler }: TargetDurationInputProps) {
|
||||
const isBlocked = targetDuration !== null;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Editor.Label htmlFor='targetDuration'>Target duration</Editor.Label>
|
||||
<TimeInputGroup hasDelay={isBlocked && targetDuration !== duration}>
|
||||
<NullableTimeInput
|
||||
name='targetDuration'
|
||||
time={targetDuration}
|
||||
submitHandler={submitHandler}
|
||||
emptyDisplay={enDash}
|
||||
className={isBlocked ? '' : style.inactive}
|
||||
/>
|
||||
<Tooltip
|
||||
text='Lock to target duration'
|
||||
className={cx([style.timeAction, isBlocked && style.active])}
|
||||
onClick={() => submitHandler('targetDuration', isBlocked ? null : duration)}
|
||||
data-testid='lock__duration'
|
||||
render={<IconButton variant='subtle-white' className={isBlocked ? style.active : style.inactive} />}
|
||||
>
|
||||
{isBlocked ? <IoLockClosed /> : <IoLockOpenOutline />}
|
||||
</Tooltip>
|
||||
</TimeInputGroup>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
.block {
|
||||
@include block-styling;
|
||||
|
||||
margin-block: 1rem 0.25rem;
|
||||
margin-block: 0.5rem;
|
||||
display: grid;
|
||||
grid-template-columns: 2rem 1fr;
|
||||
grid-template-areas: 'binder header';
|
||||
@@ -14,7 +14,7 @@
|
||||
}
|
||||
|
||||
&.expanded {
|
||||
margin-block: 1rem 0;
|
||||
margin-block: 0.5rem 0;
|
||||
border-radius: $block-border-radius $block-border-radius 0 0;
|
||||
border-bottom: 0.25rem solid color-mix(in srgb, transparent 90%, var(--user-bg, transparent) 10%);
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,5 +6,5 @@
|
||||
background-color: var(--user-bg, $gray-1050);
|
||||
|
||||
border-radius: 0 0 $block-border-radius $block-border-radius;
|
||||
margin-bottom: 0.25rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
+2
-2
@@ -1,14 +1,14 @@
|
||||
import { useSortable } from '@dnd-kit/sortable';
|
||||
import { CSS } from '@dnd-kit/utilities';
|
||||
|
||||
import style from './BlockEnd.module.scss';
|
||||
import style from './RundownBlockEnd.module.scss';
|
||||
|
||||
interface BlockEndProps {
|
||||
id: string;
|
||||
colour?: string;
|
||||
}
|
||||
|
||||
export default function BlockEnd({ id, colour }: BlockEndProps) {
|
||||
export default function RundownBlockEnd({ id, colour }: BlockEndProps) {
|
||||
const {
|
||||
attributes: dragAttributes,
|
||||
listeners: dragListeners,
|
||||
@@ -37,10 +37,10 @@ function RundownHeader() {
|
||||
return (
|
||||
<Toolbar.Root className={style.header}>
|
||||
<ToggleGroup value={[editorMode]} onValueChange={toggleAppMode} className={style.group}>
|
||||
<Toolbar.Button render={<Toggle />} value={AppMode.Run} className={style.button}>
|
||||
<Toolbar.Button render={<Toggle />} value={AppMode.Run} className={style.radioButton}>
|
||||
Run
|
||||
</Toolbar.Button>
|
||||
<Toolbar.Button render={<Toggle />} value={AppMode.Edit} className={style.button}>
|
||||
<Toolbar.Button render={<Toggle />} value={AppMode.Edit} className={style.radioButton}>
|
||||
Edit
|
||||
</Toolbar.Button>
|
||||
</ToggleGroup>
|
||||
@@ -48,10 +48,10 @@ function RundownHeader() {
|
||||
<Editor.Separator className={style.separator} />
|
||||
|
||||
<ToggleGroup value={[offsetMode]} onValueChange={toggleOffsetMode} className={style.group}>
|
||||
<Toolbar.Button render={<Toggle />} value={OffsetMode.Absolute} className={style.button}>
|
||||
<Toolbar.Button render={<Toggle />} value={OffsetMode.Absolute} className={style.radioButton}>
|
||||
Absolute
|
||||
</Toolbar.Button>
|
||||
<Toolbar.Button render={<Toggle />} value={OffsetMode.Relative} className={style.button}>
|
||||
<Toolbar.Button render={<Toggle />} value={OffsetMode.Relative} className={style.radioButton}>
|
||||
Relative
|
||||
</Toolbar.Button>
|
||||
</ToggleGroup>
|
||||
|
||||
@@ -1,31 +1,3 @@
|
||||
.timeAction {
|
||||
background: $gray-1050;
|
||||
color: $gray-500;
|
||||
cursor: pointer;
|
||||
height: 2rem;
|
||||
width: 2rem;
|
||||
display: grid;
|
||||
place-content: center;
|
||||
aspect-ratio: 1;
|
||||
|
||||
&:hover:not(:disabled):not(:active) {
|
||||
background: $gray-1000;
|
||||
}
|
||||
|
||||
&:active:not(:disabled) {
|
||||
background: $gray-1300;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 1px solid $blue-500;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: var(--status-color-active-override, $active-indicator);
|
||||
}
|
||||
}
|
||||
|
||||
.fourtyfive {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
@@ -36,28 +8,10 @@
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.inputGroup {
|
||||
border: 1px solid transparent;
|
||||
width: fit-content;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: $component-border-radius-md;
|
||||
|
||||
&.delayed {
|
||||
border: 1px solid $ontime-delay-text;
|
||||
}
|
||||
|
||||
input {
|
||||
max-width: 6.5em;
|
||||
border-radius: $component-border-radius-md 0 0 $component-border-radius-md;
|
||||
border: none;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 1.5rem;
|
||||
height: 2rem;
|
||||
border-radius: 0 $component-border-radius-md $component-border-radius-md 0;
|
||||
border: none;
|
||||
}
|
||||
.inactive {
|
||||
color: $muted-gray;
|
||||
}
|
||||
|
||||
.active {
|
||||
color: $active-indicator;
|
||||
}
|
||||
|
||||
@@ -3,11 +3,13 @@ import { IoAlertCircleOutline, IoLink, IoLockClosed, IoLockOpenOutline, IoUnlink
|
||||
import { TimeField, TimeStrategy } from 'ontime-types';
|
||||
import { dayInMs } from 'ontime-utils';
|
||||
|
||||
import IconButton from '../../../common/components/buttons/IconButton';
|
||||
import * as Editor from '../../../common/components/editor-utils/EditorUtils';
|
||||
import TimeInput from '../../../common/components/input/time-input/TimeInput';
|
||||
import Tooltip from '../../../common/components/tooltip/Tooltip';
|
||||
import { useEntryActions } from '../../../common/hooks/useEntryAction';
|
||||
import { cx } from '../../../common/utils/styleUtils';
|
||||
|
||||
import TimeInputGroup from './TimeInputGroup';
|
||||
|
||||
import style from './TimeInputFlow.module.scss';
|
||||
|
||||
@@ -67,7 +69,7 @@ function TimeInputFlow({
|
||||
<>
|
||||
<div>
|
||||
{showLabels && <Editor.Label className={style.sectionTitle}>Start time</Editor.Label>}
|
||||
<div className={cx([style.inputGroup, hasDelay && style.delayed])}>
|
||||
<TimeInputGroup hasDelay={hasDelay}>
|
||||
<TimeInput
|
||||
name='timeStart'
|
||||
submitHandler={handleSubmit}
|
||||
@@ -78,17 +80,17 @@ function TimeInputFlow({
|
||||
/>
|
||||
<Tooltip
|
||||
text='Link start to previous end'
|
||||
className={cx([style.timeAction, linkStart && style.active])}
|
||||
onClick={() => handleLink(!linkStart)}
|
||||
render={<IconButton variant='subtle-white' className={linkStart ? style.active : style.inactive} />}
|
||||
>
|
||||
<span className={style.fourtyfive}>{linkStart ? <IoLink /> : <IoUnlink />}</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</TimeInputGroup>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{showLabels && <Editor.Label>End time</Editor.Label>}
|
||||
<div className={cx([style.inputGroup, hasDelay && style.delayed])}>
|
||||
<TimeInputGroup hasDelay={hasDelay}>
|
||||
<TimeInput
|
||||
name='timeEnd'
|
||||
submitHandler={handleSubmit}
|
||||
@@ -99,18 +101,18 @@ function TimeInputFlow({
|
||||
/>
|
||||
<Tooltip
|
||||
text='Lock end'
|
||||
className={cx([style.timeAction, isLockedEnd && style.active])}
|
||||
render={<IconButton variant='subtle-white' className={isLockedEnd ? style.active : style.inactive} />}
|
||||
onClick={() => handleChangeStrategy(TimeStrategy.LockEnd)}
|
||||
data-testid='lock__end'
|
||||
>
|
||||
{isLockedEnd ? <IoLockClosed /> : <IoLockOpenOutline />}
|
||||
</Tooltip>
|
||||
</div>
|
||||
</TimeInputGroup>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{showLabels && <Editor.Label>Duration</Editor.Label>}
|
||||
<div className={cx([style.inputGroup, hasDelay && style.delayed])}>
|
||||
<TimeInputGroup hasDelay={hasDelay}>
|
||||
<TimeInput
|
||||
name='duration'
|
||||
submitHandler={handleSubmit}
|
||||
@@ -121,13 +123,13 @@ function TimeInputFlow({
|
||||
/>
|
||||
<Tooltip
|
||||
text='Lock duration'
|
||||
className={cx([style.timeAction, isLockedDuration && style.active])}
|
||||
render={<IconButton variant='subtle-white' className={isLockedDuration ? style.active : style.inactive} />}
|
||||
onClick={() => handleChangeStrategy(TimeStrategy.LockDuration)}
|
||||
data-testid='lock__duration'
|
||||
>
|
||||
{isLockedDuration ? <IoLockClosed /> : <IoLockOpenOutline />}
|
||||
</Tooltip>
|
||||
</div>
|
||||
</TimeInputGroup>
|
||||
</div>
|
||||
|
||||
{warnings.length > 0 && (
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
.inputGroup {
|
||||
border: 1px solid transparent;
|
||||
width: fit-content;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: $component-border-radius-md;
|
||||
|
||||
&.delayed {
|
||||
border: 1px solid $ontime-delay-text;
|
||||
}
|
||||
|
||||
input {
|
||||
max-width: 6.5em;
|
||||
border-radius: $component-border-radius-md 0 0 $component-border-radius-md;
|
||||
border: none;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 1.5rem;
|
||||
height: 2rem;
|
||||
border-radius: 0 $component-border-radius-md $component-border-radius-md 0;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { PropsWithChildren } from 'react';
|
||||
|
||||
import { cx } from '../../../common/utils/styleUtils';
|
||||
|
||||
import style from './TimeInputGroup.module.scss';
|
||||
|
||||
interface TimeInputGroupProps {
|
||||
hasDelay?: boolean;
|
||||
}
|
||||
|
||||
export default function TimeInputGroup({ hasDelay, children }: PropsWithChildren<TimeInputGroupProps>) {
|
||||
return <div className={cx([style.inputGroup, hasDelay && style.delayed])}>{children}</div>;
|
||||
}
|
||||
+5
@@ -18,6 +18,11 @@
|
||||
&.skip {
|
||||
position: relative;
|
||||
|
||||
.indexColumn {
|
||||
text-decoration: line-through;
|
||||
opacity: $opacity-disabled;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
|
||||
Reference in New Issue
Block a user