diff --git a/client/src/common/components/buttons/ActionButtons.tsx b/client/src/common/components/buttons/ActionButtons.tsx index 056dfebe8..62344a52c 100644 --- a/client/src/common/components/buttons/ActionButtons.tsx +++ b/client/src/common/components/buttons/ActionButtons.tsx @@ -3,8 +3,6 @@ import { FiClock } from '@react-icons/all-files/fi/FiClock'; import { FiMinusCircle } from '@react-icons/all-files/fi/FiMinusCircle'; import { FiPlus } from '@react-icons/all-files/fi/FiPlus'; -import { tooltipDelayMid } from '../../../ontimeConfig'; - interface ActionButtonProps { showAdd?: boolean; showDelay?: boolean; @@ -22,14 +20,14 @@ export default function ActionButtons(props: ActionButtonProps) { return ( - + } - colorScheme='blue' - variant='ghost' + colorScheme='white' + variant='outline' /> diff --git a/client/src/common/components/buttons/TooltipLoadingActionBtn.jsx b/client/src/common/components/buttons/TooltipLoadingActionBtn.jsx deleted file mode 100644 index 5516ed1ee..000000000 --- a/client/src/common/components/buttons/TooltipLoadingActionBtn.jsx +++ /dev/null @@ -1,34 +0,0 @@ -import { useCallback, useState } from 'react'; -import { IconButton, Tooltip } from '@chakra-ui/react'; -import PropTypes from 'prop-types'; - -export default function TooltipLoadingActionBtn(props) { - const { clickHandler, icon, size = 'xs', tooltip, ...rest } = props; - const [loading, setLoading] = useState(false); - - const handleClick = useCallback(() => { - setLoading(true); - clickHandler(); - }, [clickHandler, setLoading]); - - return ( - - - - ); -} - -TooltipLoadingActionBtn.propTypes = { - clickHandler: PropTypes.func, - icon: PropTypes.element, - size: PropTypes.oneOf(['xs', 'sm', 'md', 'lg']), - tooltip: PropTypes.string, -}; diff --git a/client/src/common/components/buttons/TooltipLoadingActionBtn.tsx b/client/src/common/components/buttons/TooltipLoadingActionBtn.tsx new file mode 100644 index 000000000..b1832ffde --- /dev/null +++ b/client/src/common/components/buttons/TooltipLoadingActionBtn.tsx @@ -0,0 +1,33 @@ +import { useCallback, useState } from 'react'; +import { IconButton, IconButtonProps, Tooltip } from '@chakra-ui/react'; + +interface TooltipLoadingActionBtnProps extends IconButtonProps { + clickHandler: () => void; + tooltip: string; + openDelay?: number; +} + +export default function TooltipLoadingActionBtn(props: TooltipLoadingActionBtnProps) { + const { clickHandler, icon, size = 'xs', tooltip, openDelay = 0, ...rest } = props; + const [loading, setLoading] = useState(false); + + const handleClick = useCallback(() => { + setLoading(true); + clickHandler(); + }, [clickHandler, setLoading]); + + return ( + + + + ); +} + diff --git a/client/src/common/components/collapseBar/CollapseBar.module.scss b/client/src/common/components/collapseBar/CollapseBar.module.scss index 8ff33fca1..cda8e11e4 100644 --- a/client/src/common/components/collapseBar/CollapseBar.module.scss +++ b/client/src/common/components/collapseBar/CollapseBar.module.scss @@ -1,21 +1,14 @@ @use '../../../theme/main' as *; -.header, -.headerRoll { +.header { padding: 0; margin: 0; font-size: 0.9em; display: flex; justify-content: space-between; -} - -.header { color: $header-gray; } -.headerRoll { - color: $ontime-roll; -} .moreExpanded, .moreCollapsed { diff --git a/client/src/common/components/input/TimeInput.jsx b/client/src/common/components/input/TimeInput.jsx index b94b67e50..8232b7cc7 100644 --- a/client/src/common/components/input/TimeInput.jsx +++ b/client/src/common/components/input/TimeInput.jsx @@ -1,11 +1,12 @@ import { useCallback, useContext, useEffect, useRef, useState } from 'react'; -import { IconButton, Input, InputGroup, InputLeftElement } from '@chakra-ui/react'; -import { IoLink } from '@react-icons/all-files/io5/IoLink'; +import { Button, Input, InputGroup, InputLeftElement, Tooltip } from '@chakra-ui/react'; import { LoggingContext } from 'common/context/LoggingContext'; import { forgivingStringToMillis } from 'common/utils/dateConfig'; import { stringFromMillis } from 'common/utils/time'; import PropTypes from 'prop-types'; +import { tooltipDelayFast } from '../../../ontimeConfig'; + import style from './TimeInput.module.scss'; export default function TimeInput(props) { @@ -126,18 +127,46 @@ export default function TimeInput(props) { const isDelayed = delay != null && delay !== 0; +/* + + */ + + const buttonInitial = () => { + if (name === 'timeStart') return 'S'; + if (name === 'timeEnd') return 'E'; + if (name === 'duration') return 'D'; + } + + const buttonTooltip = () => { + if (name === 'timeStart') return 'Start'; + if (name === 'timeEnd') return 'End'; + if (name === 'duration') return 'Duration'; + } + return ( - + + ) { + const { label, className, children } = props; + + return ( + + + + ); +} diff --git a/client/src/common/utils/dateConfig.js b/client/src/common/utils/dateConfig.js index 7da9e9fda..09408574c 100644 --- a/client/src/common/utils/dateConfig.js +++ b/client/src/common/utils/dateConfig.js @@ -28,10 +28,13 @@ export function formatDisplay(seconds, hideZero = false) { /** * @description Converts milliseconds to seconds - * @param {number} millis - time in seconds + * @param {number | null} millis - time in seconds * @returns {number} Amount in seconds */ export const millisToSeconds = (millis) => { + if (millis === null) { + return 0; + } return millis < 0 ? Math.ceil(millis / mts) : Math.floor(millis / mts); }; diff --git a/client/src/common/utils/time.js b/client/src/common/utils/time.js index 89be76ada..76df9c98e 100644 --- a/client/src/common/utils/time.js +++ b/client/src/common/utils/time.js @@ -24,7 +24,7 @@ export const nowInMillis = () => { /** * @description Converts milliseconds to string representing time - * @param {number} ms - time in milliseconds + * @param {number | null} ms - time in milliseconds * @param {boolean} showSeconds - weather to show the seconds * @param {string} delim - character between HH MM SS * @param {string} ifNull - what to return if value is null diff --git a/client/src/features/control/message/MessageControl.jsx b/client/src/features/control/message/MessageControl.jsx index a4c4227a1..622878217 100644 --- a/client/src/features/control/message/MessageControl.jsx +++ b/client/src/features/control/message/MessageControl.jsx @@ -2,6 +2,7 @@ import { IconButton, Tooltip } from '@chakra-ui/react'; import { IoMicOffOutline } from '@react-icons/all-files/io5/IoMicOffOutline'; import { IoMicSharp } from '@react-icons/all-files/io5/IoMicSharp'; +import CopyTag from '../../../common/components/osc-tag/CopyTag'; import { useMessageControlProvider } from '../../../common/hooks/useSocketProvider'; import { tooltipDelayMid } from '../../../ontimeConfig'; @@ -52,8 +53,11 @@ export default function MessageControl() { aria-label='Toggle On Air' /> - On Air - {`/ontime/offAir << OSC >> /ontime/onAir`} +
On Air
+
+ /ontime/offAir + /ontime/offAir +
); diff --git a/client/src/features/control/message/MessageControl.module.scss b/client/src/features/control/message/MessageControl.module.scss index 79c6746cc..d146c2ab1 100644 --- a/client/src/features/control/message/MessageControl.module.scss +++ b/client/src/features/control/message/MessageControl.module.scss @@ -1,15 +1,20 @@ @use '../../../theme/main' as *; @use '../../../theme/mixins' as *; + +@mixin message-control-label() { + font-size: 0.9em; + color: $label-gray; +} .messageContainer, .onAirToggle { display: flex; - gap: 0.5em; padding: 0.5em; } .messageContainer { flex-direction: column; + gap: 4px; .inputItems { display: grid; @@ -20,8 +25,7 @@ .label { padding: 0; margin: 0; - font-size: 0.9em; - color: $label-gray; + @include message-control-label; } .inputRowActive { @@ -33,25 +37,30 @@ .onAirToggle { margin-top: 1em; - align-items: center; display: grid; grid-template-areas: - 'btn label' - 'btn osc'; - grid-template-columns: 2.5em 1fr; - grid-template-rows: 1.2em 0.8em; + 'btn label' + 'btn osc'; + grid-template-columns: auto 1fr; + grid-template-rows: 1fr 1fr; + align-items: center; .btn { + aspect-ratio: 1; grid-area: btn; + height: 100%; + margin-right: 16px; } .onAirLabel { grid-area: label; - font-size: 1.2em; + @include message-control-label; } .oscLabel { - @include osc-label; grid-area: osc; + display: flex; + gap: 4px; } } + diff --git a/client/src/features/control/playback/Playback.jsx b/client/src/features/control/playback/Playback.jsx deleted file mode 100644 index 97e9335ee..000000000 --- a/client/src/features/control/playback/Playback.jsx +++ /dev/null @@ -1,43 +0,0 @@ -import PropTypes from 'prop-types'; - -import PauseIconBtn from '../../../common/components/buttons/PauseIconBtn'; -import RollIconBtn from '../../../common/components/buttons/RollIconBtn'; -import StartIconBtn from '../../../common/components/buttons/StartIconBtn'; - -import style from './PlaybackControl.module.scss'; - -export default function Playback(props) { - const { playback, selectedId, playbackControl, noEvents } = props; - const isRolling = playback === 'roll'; - - return ( -
- playbackControl.start()} - disabled={!selectedId || isRolling || noEvents} - /> - playbackControl.pause()} - disabled={!selectedId || isRolling || noEvents || playback !== 'start'} - /> - playbackControl.roll()} - /> -
- ); -} - -Playback.propTypes = { - playback: PropTypes.string, - selectedId: PropTypes.string, - playbackControl: PropTypes.shape({ - start: PropTypes.func, - pause: PropTypes.func, - roll: PropTypes.func, - }).isRequired, - noEvents: PropTypes.bool.isRequired, -}; diff --git a/client/src/features/control/playback/Playback.tsx b/client/src/features/control/playback/Playback.tsx new file mode 100644 index 000000000..3d4f3cad0 --- /dev/null +++ b/client/src/features/control/playback/Playback.tsx @@ -0,0 +1,61 @@ +import { Tooltip } from '@chakra-ui/react'; +import { IoPause } from '@react-icons/all-files/io5/IoPause'; +import { IoPlay } from '@react-icons/all-files/io5/IoPlay'; +import { IoTimeOutline } from '@react-icons/all-files/io5/IoTimeOutline'; + +import { usePlaybackControlProvider } from '../../../common/hooks/useSocketProvider'; +import { Playstate } from '../../../common/models/OntimeTypes'; +import { tooltipDelayMid } from '../../../ontimeConfig'; + +import TapButton from './TapButton'; + +import style from './PlaybackControl.module.scss'; + +interface PlaybackProps { + playback: Playstate; + selectedId: string; + noEvents: boolean; +} + +export default function Playback(props: PlaybackProps) { + const { playback, selectedId, noEvents } = props; + const isRolling = playback === 'roll'; + const { setPlayback } = usePlaybackControlProvider(); + + return ( +
+ + setPlayback.start()} + disabled={!selectedId || isRolling || noEvents} + theme='start' + active={playback === 'start'} + > + + + + + + setPlayback.pause()} + disabled={!selectedId || isRolling || noEvents || playback !== 'start'} + theme='pause' + active={playback === 'pause'} + > + + + + + + setPlayback.roll()} + disabled={playback === 'roll' || noEvents} + theme='roll' + active={isRolling} + > + + + +
+ ); +} diff --git a/client/src/features/control/playback/PlaybackControl.module.scss b/client/src/features/control/playback/PlaybackControl.module.scss index 8f1089de6..f04f637f9 100644 --- a/client/src/features/control/playback/PlaybackControl.module.scss +++ b/client/src/features/control/playback/PlaybackControl.module.scss @@ -8,9 +8,6 @@ gap: 4px; } -.playbackContainer { - padding: 0.5em; -} .timeContainer { display: grid; @@ -65,7 +62,7 @@ } .indNegativeActive { - background-color: $ontime-pink; + background-color: $ontime-pink-variant; } .indDelayActive { @@ -74,11 +71,11 @@ .btn { grid-area: btn; - display: flex; - flex-direction: row; - flex-wrap: wrap; - align-items: center; - justify-content: space-around; + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-rows: 1fr 1fr; + width: 100%; + gap: 4px; } .minus { @@ -87,6 +84,12 @@ flex-direction: column; } +.start, +.finish, +.roll { + height: 24px; +} + .start { grid-area: sta; } diff --git a/client/src/features/control/playback/PlaybackControl.jsx b/client/src/features/control/playback/PlaybackControl.tsx similarity index 74% rename from client/src/features/control/playback/PlaybackControl.jsx rename to client/src/features/control/playback/PlaybackControl.tsx index 5f2cdc510..082975ede 100644 --- a/client/src/features/control/playback/PlaybackControl.jsx +++ b/client/src/features/control/playback/PlaybackControl.tsx @@ -1,4 +1,5 @@ import { usePlaybackControlProvider } from '../../../common/hooks/useSocketProvider'; +import { Playstate } from '../../../common/models/OntimeTypes'; import PlaybackButtons from './PlaybackButtons'; import PlaybackTimer from './PlaybackTimer'; @@ -6,20 +7,18 @@ import PlaybackTimer from './PlaybackTimer'; import style from './PlaybackControl.module.scss'; export default function PlaybackControl() { - const { data, setPlayback } = usePlaybackControlProvider(); + const { data } = usePlaybackControlProvider(); return (
setPlayback.delay(amount)} />
); diff --git a/client/src/features/control/playback/PlaybackTimer.jsx b/client/src/features/control/playback/PlaybackTimer.tsx similarity index 50% rename from client/src/features/control/playback/PlaybackTimer.jsx rename to client/src/features/control/playback/PlaybackTimer.tsx index f6937dcec..0f13362c0 100644 --- a/client/src/features/control/playback/PlaybackTimer.jsx +++ b/client/src/features/control/playback/PlaybackTimer.tsx @@ -1,39 +1,34 @@ -import { memo } from 'react'; -import { Button, Tooltip } from '@chakra-ui/react'; +import { Tooltip } from '@chakra-ui/react'; import TimerDisplay from 'common/components/countdown/TimerDisplay'; -import PropTypes from 'prop-types'; -import { useTimerProvider } from '../../../common/hooks/useSocketProvider'; +import { + usePlaybackControlProvider, + useTimerProvider, +} from '../../../common/hooks/useSocketProvider'; +import { Playstate } from '../../../common/models/OntimeTypes'; import { millisToSeconds } from '../../../common/utils/dateConfig'; import { stringFromMillis } from '../../../common/utils/time'; import { tooltipDelayMid } from '../../../ontimeConfig'; +import TapButton from './TapButton'; + import style from './PlaybackControl.module.scss'; -const areEqual = (prevProps, nextProps) => { - return ( - prevProps.playback === nextProps.playback && - prevProps.selectedId === nextProps.selectedId - ); -}; +interface PlaybackTimerProps { + playback: Playstate; + selectedId: string | null; +} -const incrementProps = { - size: 'sm', - width: '2em', - colorScheme: 'white', - variant: 'outline', - fontSize: '12px', -}; - -const PlaybackTimer = (props) => { - const { playback, handleIncrement, selectedId } = props; +export default function PlaybackTimer(props: PlaybackTimerProps) { + const { playback, selectedId } = props; + const { setPlayback } = usePlaybackControlProvider(); const timerData = useTimerProvider(); const started = stringFromMillis(timerData.startedAt, true); const finish = stringFromMillis(timerData.expectedFinish, true); const isRolling = playback === 'roll'; - const isWaiting = timerData.secondaryTimer > 0 && timerData.current == null; + const isWaiting = timerData.secondaryTimer !== null && timerData.secondaryTimer > 0 && timerData.current === null; const disableButtons = selectedId == null || isRolling; - const isOvertime = timerData.current < 0; + const isOvertime = timerData.current !== null && timerData.current < 0; return (
@@ -68,55 +63,43 @@ const PlaybackTimer = (props) => { )}
- - - - - - - - + - - + square> + -1 + + + + setPlayback.delay(-5)} + disabled={disableButtons} + square> + 1 + + + + setPlayback.delay(-5)} + disabled={disableButtons} + square> + 5 +
); }; - -export default memo(PlaybackTimer, areEqual); - -PlaybackTimer.propTypes = { - playback: PropTypes.string, - handleIncrement: PropTypes.func.isRequired, - selectedId: PropTypes.string, -}; diff --git a/client/src/features/control/playback/TapButton.module.scss b/client/src/features/control/playback/TapButton.module.scss new file mode 100644 index 000000000..f208c59e8 --- /dev/null +++ b/client/src/features/control/playback/TapButton.module.scss @@ -0,0 +1,65 @@ +@use '../../../theme/main' as *; + +@mixin tap-factory($theme-front, $theme-bg, $theme-high) { + font-family: "Open Sans", sans-serif; + font-size: 22px; + background-color: $theme-bg; + color: $theme-front; + border-radius: 3px; + width: 100%; + aspect-ratio: 3/1; + box-shadow: $theme-high 0 0 2px; + transition: background-color 0.3s; + display: grid; + place-content: center; + + &:disabled { + cursor: not-allowed; + background-color: $opacity-disabled; + box-shadow: none; + opacity: $opacity-disabled; + } + + &:hover:not(:disabled) { + background-color: $theme-high; + } + + &:active:not(:disabled) { + color: $theme-bg; + background-color: $theme-front; + transition: background-color 0.15s; + } + + &.active { + background-color: $theme-high; + } +} + +.tapButton.neutral{ + @include tap-factory(rgba(255, 255, 255, 0.867), #303030, #363636); +} + +.tapButton.start { + @include tap-factory(rgba(255, 255, 255, 0.867), #303030, $ontime-accent); +} + +.tapButton.roll { + @include tap-factory(rgba(255, 255, 255, 0.867), #303030, $ontime-roll); +} + +.tapButton.pause { + @include tap-factory(rgba(255, 255, 255, 0.867), #303030, $ontime-paused); +} + +.tapButton.ontime { + @include tap-factory(rgba(255, 255, 255, 0.867), #303030, $ontime-pink); +} + +.tapButton.stop { + @include tap-factory(rgba(255, 255, 255, 0.867), #303030, $ontime-red); +} + +.tapButton.square { + aspect-ratio: 1; + font-size: 14px; +} diff --git a/client/src/features/control/playback/TapButton.tsx b/client/src/features/control/playback/TapButton.tsx new file mode 100644 index 000000000..6c0a18e35 --- /dev/null +++ b/client/src/features/control/playback/TapButton.tsx @@ -0,0 +1,31 @@ +import { ForwardedRef, forwardRef, PropsWithChildren } from 'react'; + +import { Playstate } from '../../../common/models/OntimeTypes'; + +import style from './TapButton.module.scss'; + +interface TapButtonProps { + disabled?: boolean; + square?: boolean; + onClick: () => void; + theme?: Playstate | 'neutral'; + active?: boolean; +} + +const TapButton = forwardRef((props: PropsWithChildren, ref: ForwardedRef ) => { + const { children, disabled, onClick, theme = 'neutral', square, active } = props; + return ( + + ); +}); + +TapButton.displayName = "TabButton"; +export default TapButton; diff --git a/client/src/features/control/playback/Transport.jsx b/client/src/features/control/playback/Transport.jsx deleted file mode 100644 index 2dddb107b..000000000 --- a/client/src/features/control/playback/Transport.jsx +++ /dev/null @@ -1,53 +0,0 @@ -import { IoPlayBack } from '@react-icons/all-files/io5/IoPlayBack'; -import { IoPlaySkipBack } from '@react-icons/all-files/io5/IoPlaySkipBack'; -import { IoPlaySkipForward } from '@react-icons/all-files/io5/IoPlaySkipForward'; -import PropTypes from 'prop-types'; - -import TransportIconBtn from '../../../common/components/buttons/TransportIconBtn'; -import UnloadIconBtn from '../../../common/components/buttons/UnloadIconBtn'; - -import style from './PlaybackControl.module.scss'; - -export default function Transport(props) { - const { playback, selectedId, playbackControl, noEvents } = props; - const isRolling = playback === 'roll'; - - return ( -
- playbackControl.previous()} - disabled={isRolling || noEvents} - tooltip='Previous event' - icon={} - /> - playbackControl.next()} - disabled={isRolling || noEvents} - tooltip='Next event' - icon={} - /> - playbackControl.reload()} - disabled={selectedId == null || isRolling || noEvents} - tooltip='Reload event' - icon={} - /> - playbackControl.stop()} - disabled={(selectedId == null && !isRolling) || noEvents} - /> -
- ); -} - -Transport.propTypes = { - playback: PropTypes.string, - selectedId: PropTypes.string, - playbackControl: PropTypes.shape({ - previous: PropTypes.func, - next: PropTypes.func, - reload: PropTypes.func, - stop: PropTypes.func, - }).isRequired, - noEvents: PropTypes.bool.isRequired, -}; diff --git a/client/src/features/control/playback/Transport.tsx b/client/src/features/control/playback/Transport.tsx new file mode 100644 index 000000000..c4944b174 --- /dev/null +++ b/client/src/features/control/playback/Transport.tsx @@ -0,0 +1,63 @@ +import { Tooltip } from '@chakra-ui/react'; +import { IoPlayBack } from '@react-icons/all-files/io5/IoPlayBack'; +import { IoPlaySkipBack } from '@react-icons/all-files/io5/IoPlaySkipBack'; +import { IoPlaySkipForward } from '@react-icons/all-files/io5/IoPlaySkipForward'; +import { IoStop } from '@react-icons/all-files/io5/IoStop'; + +import { usePlaybackControlProvider } from '../../../common/hooks/useSocketProvider'; +import { Playstate } from '../../../common/models/OntimeTypes'; +import { tooltipDelayMid } from '../../../ontimeConfig'; + +import TapButton from './TapButton'; + +import style from './PlaybackControl.module.scss'; + +interface TransportProps { + playback: Playstate; + selectedId: string; + noEvents: boolean; +} + +export default function Transport(props: TransportProps) { + const { playback, selectedId, noEvents } = props; + const { setPlayback } = usePlaybackControlProvider(); + const isRolling = playback === 'roll'; + + return ( +
+ + setPlayback.previous()} + disabled={isRolling || noEvents} + > + + + + + setPlayback.next()} + disabled={isRolling || noEvents} + > + + + + + setPlayback.reload()} + disabled={selectedId == null || isRolling || noEvents} + > + + + + + setPlayback.stop()} + disabled={(selectedId == null && !isRolling) || noEvents} + theme='stop' + > + + + +
+ ); +} diff --git a/client/src/features/editors/Editor.module.scss b/client/src/features/editors/Editor.module.scss index 0f6701871..bcfb7d468 100644 --- a/client/src/features/editors/Editor.module.scss +++ b/client/src/features/editors/Editor.module.scss @@ -131,7 +131,7 @@ .eventEditor { border-radius: 3px 3px 0 0; - background-color: $bg-container-l1; + background-color: $bg-black; border-top: 1px solid $bg-gray-900; position: absolute; bottom: 0; @@ -152,7 +152,7 @@ } .header { - background-color: $bg-container-l2; + background-color: $bg-black; padding: 8px; border-left: 1px solid $bg-container-l3; } @@ -186,8 +186,8 @@ .playback { grid-area: play; - min-height: 270px; - max-height: 270px; + min-height: 275px; + max-height: 380px; min-width: 480px; } diff --git a/client/src/features/editors/_blockMixins.scss b/client/src/features/editors/_blockMixins.scss index d580685f0..658201ad9 100644 --- a/client/src/features/editors/_blockMixins.scss +++ b/client/src/features/editors/_blockMixins.scss @@ -14,7 +14,7 @@ $block-border-radius: 3px; flex-direction: row; flex-wrap: wrap; align-content: center; - opacity: 0.8; + opacity: 0.6; transition: linear 0.1s; } @@ -26,7 +26,7 @@ $block-border-radius: 3px; @mixin drag-style() { font-size: 20px; text-align: center; - opacity: 0.1; + opacity: 0.3; cursor: grab; transition: opacity 0.3s; &:hover { diff --git a/client/src/features/editors/block-block/BlockBlock.jsx b/client/src/features/editors/block-block/BlockBlock.jsx index cb53b4c3b..e551fe28b 100644 --- a/client/src/features/editors/block-block/BlockBlock.jsx +++ b/client/src/features/editors/block-block/BlockBlock.jsx @@ -24,10 +24,10 @@ export default function BlockBlock(props) { clickHandler={() => actionHandler('delete')} icon={} tooltip='Delete' - variant='ghost' - _hover={{ bg: 'red.400', color: 'white' }} - color='red.500' + variant='outline' + colorScheme='white' size='sm' + aria-label='Delete' /> diff --git a/client/src/features/editors/block-block/BlockBlock.module.scss b/client/src/features/editors/block-block/BlockBlock.module.scss index 00c364821..44d25be79 100644 --- a/client/src/features/editors/block-block/BlockBlock.module.scss +++ b/client/src/features/editors/block-block/BlockBlock.module.scss @@ -6,24 +6,21 @@ .block { @include block-spacing; + box-sizing: content-box; display: grid; grid-template-columns: 40px 1fr; align-items: center; height: 40px; - - border-radius: 2px 2px $block-border-radius $block-border-radius; - background-color: rgba(107, 70, 193, 0.4); - background: linear-gradient( - 0deg, - rgba(107, 70, 193, 0.4) 0%, - rgba(128, 90, 213, 0.4) 20%, - rgba(107, 70, 193, 0.15) 21% - ); + border-radius: 2px; + border: $border-l3; + border-bottom: 4px solid $block-block-color; + background-color: $bg-container-l2; } /* ================ DRAG ================ */ .drag { @include drag-style; + color: $block-block-color; } /* ============== ACTION ================ */ diff --git a/client/src/features/editors/delay-block/DelayBlock.jsx b/client/src/features/editors/delay-block/DelayBlock.jsx index 5aa491cab..992c3ab2d 100644 --- a/client/src/features/editors/delay-block/DelayBlock.jsx +++ b/client/src/features/editors/delay-block/DelayBlock.jsx @@ -55,9 +55,10 @@ export default function DelayBlock(props) { @@ -65,9 +66,8 @@ export default function DelayBlock(props) { clickHandler={deleteHandler} icon={} tooltip='Delete' - variant='ghost' - _hover={{ bg: 'red.400', color: 'white' }} - color='red.500' + variant='outline' + colorScheme='white' size='sm' /> diff --git a/client/src/features/editors/delay-block/DelayBlock.module.scss b/client/src/features/editors/delay-block/DelayBlock.module.scss index 086b7ac7f..cca87c0a0 100644 --- a/client/src/features/editors/delay-block/DelayBlock.module.scss +++ b/client/src/features/editors/delay-block/DelayBlock.module.scss @@ -6,20 +6,17 @@ .delay { @include block-spacing; + box-sizing: content-box; display: grid; grid-template-columns: 32px 1fr auto; grid-template-areas: 'drag inpt btns'; align-items: center; height: 40px; + border-radius: 2px; + border: $border-l3; + border-top: 4px solid $block-delay-color; + background-color: $bg-container-l2; - border-radius: $block-border-radius $block-border-radius 2px 2px; - background-color: rgba(214, 158, 46, 0.4); - background: linear-gradient( - 180deg, - rgba(214, 158, 46, 0.4) 0%, - rgba(214, 158, 46, 0.4) 20%, - rgba(214, 158, 46, 0.17) 21% - ); } /* ================ DRAG ================ */ @@ -27,6 +24,7 @@ .drag { grid-area: drag; @include drag-style; + color: $block-delay-color; } /* =============== INPUT ================ */ diff --git a/client/src/features/editors/event-block/EventBlock.module.scss b/client/src/features/editors/event-block/EventBlock.module.scss index 7be28a670..dfa3ebbed 100644 --- a/client/src/features/editors/event-block/EventBlock.module.scss +++ b/client/src/features/editors/event-block/EventBlock.module.scss @@ -12,7 +12,7 @@ grid-template-columns: $binder-width auto 1fr auto; grid-template-rows: 36px 36px 36px $element-spacing; align-items: center; - margin: 2px 2px; + margin:4px 2px; padding-right: $clearance; // style - general @@ -26,7 +26,6 @@ // variant &.selected { background-color: $bg-container-l3; - box-shadow: 0 0 1px 2px $ontime-accent; } &.skip { @@ -87,7 +86,7 @@ height: 100%; .delayNote { - font-size: 10px; + font-size: 11px; color: $text-delay; } } @@ -148,9 +147,8 @@ border: 1px solid transparent; &.enabled { - color: $ontime-accent; - border: 1px solid $ontime-accent; - background-color: $bg-gray-1100; + color: $text-white; + background-color: $ontime-accent; } } diff --git a/client/src/features/editors/event-block/EventBlock.tsx b/client/src/features/editors/event-block/EventBlock.tsx index 0ad309d4c..d917dd751 100644 --- a/client/src/features/editors/event-block/EventBlock.tsx +++ b/client/src/features/editors/event-block/EventBlock.tsx @@ -3,7 +3,7 @@ import { Draggable } from 'react-beautiful-dnd'; import { Editable, EditableInput, EditablePreview, Tooltip } from '@chakra-ui/react'; import { FiUsers } from '@react-icons/all-files/fi/FiUsers'; import { IoOptions } from '@react-icons/all-files/io5/IoOptions'; -import { IoPause } from '@react-icons/all-files/io5/IoPause'; +import { IoPlay } from '@react-icons/all-files/io5/IoPlay'; import { IoPlayBackOutline } from '@react-icons/all-files/io5/IoPlayBackOutline'; import { IoPlayOutline } from '@react-icons/all-files/io5/IoPlayOutline'; import { IoReload } from '@react-icons/all-files/io5/IoReload'; @@ -108,7 +108,7 @@ export default function EventBlock(props: EventBlockProps) { if (!skip && eventIsPlaying) { playBtnStyles._hover = { bg: '#c05621' }; } else if (!skip && !eventIsPlaying) { - playBtnStyles._hover = { bg: '#4bffab' }; + playBtnStyles._hover = { }; } return ( @@ -161,19 +161,15 @@ export default function EventBlock(props: EventBlockProps) { tabIndex={-1} /> : } + icon={eventIsPlaying ? : } disabled={skip} {...blockBtnStyle} variant={eventIsPlaying ? 'solid' : 'ghost'} - clickHandler={ - eventIsPlaying - ? () => setPlayback.pause() - : () => setPlayback.startEvent() - } - {...playBtnStyles} + clickHandler={() => setPlayback.startEvent()} + backgroundColor={eventIsPlaying ? '#58A151' : undefined} tabIndex={-1} /> diff --git a/client/src/features/editors/event-block/composite/EventBlockActionMenu.jsx b/client/src/features/editors/event-block/composite/EventBlockActionMenu.jsx index ffcc034a9..b1c10a265 100644 --- a/client/src/features/editors/event-block/composite/EventBlockActionMenu.jsx +++ b/client/src/features/editors/event-block/composite/EventBlockActionMenu.jsx @@ -27,8 +27,8 @@ export default function EventBlockActionMenu(props) { const blockBtnStyle = { size: 'sm', - variant: 'ghost', - colorScheme: 'blue', + variant: 'outline', + colorScheme: 'whiteAlpha', }; return ( diff --git a/client/src/features/editors/list/EventList.jsx b/client/src/features/editors/list/EventList.jsx index 9eafd7a0e..7cd92f440 100644 --- a/client/src/features/editors/list/EventList.jsx +++ b/client/src/features/editors/list/EventList.jsx @@ -15,7 +15,7 @@ import { useAtomValue } from 'jotai'; import PropTypes from 'prop-types'; import useSubscription from '../../../common/hooks/useSubscription'; -import EntryBlock from '../entry-block/EntryBlock'; +import QuickAddBlock from '../quick-add-block/QuickAddBlock'; import EventListItem from './EventListItem'; @@ -231,7 +231,7 @@ export default function EventList(props) { /> {((showQuickEntry && index === cursor) || isLast) && ( - +
-
- - - - - - +
+
+ + + + + + +
+
+ + + + +
@@ -199,7 +217,7 @@ export default function EventEditor() { />
-
{`OSC Trigger /ontime/gotoid/${event.id}`}
+ {`/ontime/gotoid/${event.id}`}
); diff --git a/client/src/features/event-editor/EventEditor.module.scss b/client/src/features/event-editor/EventEditor.module.scss index 5abf8a530..1a692be4c 100644 --- a/client/src/features/event-editor/EventEditor.module.scss +++ b/client/src/features/event-editor/EventEditor.module.scss @@ -8,26 +8,39 @@ gap: max(16px, 2vh); display: grid; - grid-template-areas: 'timers titles'; + grid-template-areas: 'timeOptions titles'; grid-template-columns: auto 1fr; - - .timers, + + .timeOptions, .titles { - background-color: $bg-container-l2; + background-color: $bg-container-over; border-radius: 2px; padding: 8px 16px; } - .timers { - grid-area: timers; + .timeOptions { + grid-area: timeOptions; + display: flex; + gap: 24px; + } + + .timers, .timeSettings { display: flex; flex-direction: column; gap: 8px; } - .timers label:nth-child(1) { + .timers label:nth-child(1), + .timeSettings label:nth-child(1), + { margin-top: 4px; } + .timeSettings { + display: flex; + flex-direction: column; + gap: 8px; + } + .titles { grid-area: titles; display: grid; @@ -57,10 +70,7 @@ .osc { grid-area: tag; - font-size: 14px; - color: $ontime-accent; - text-align: right; - user-select: text; + justify-self: end; } } diff --git a/client/src/features/info/Info.jsx b/client/src/features/info/Info.jsx index edfc4f6cb..8adced29f 100644 --- a/client/src/features/info/Info.jsx +++ b/client/src/features/info/Info.jsx @@ -36,8 +36,8 @@ export default function Info() { {selected} - - + + ); diff --git a/client/src/features/info/Info.module.scss b/client/src/features/info/Info.module.scss index d0ca345a4..a1c51912a 100644 --- a/client/src/features/info/Info.module.scss +++ b/client/src/features/info/Info.module.scss @@ -11,7 +11,6 @@ @include container; } - .main { font-size: 0.9em; color: $label-gray; @@ -19,20 +18,6 @@ justify-content: space-between; } -.header, -.headerRoll { - padding: 0; - margin: 0; - font-size: 0.9em; - color: $header-gray; - display: flex; - justify-content: space-between; -} - -.header { - color: $header-gray; -} - .collapsedTitle { font-size: inherit; diff --git a/client/src/features/info/InfoLogger.module.scss b/client/src/features/info/InfoLogger.module.scss index 3ee7afe26..ce98b1b67 100644 --- a/client/src/features/info/InfoLogger.module.scss +++ b/client/src/features/info/InfoLogger.module.scss @@ -18,7 +18,6 @@ overflow-y: scroll; font-size: 0.8em; user-select: text; - @include third-container; padding: 0 0.5em; margin: 0 0.5em; @@ -78,8 +77,8 @@ } div.active { - background: $ontime-accent; - color: darken($ontime-accent, 70%); + background: $ontime-roll; + color: white; } .clear { diff --git a/client/src/features/menu/EventListMenu.module.scss b/client/src/features/menu/EventListMenu.module.scss index d57d3ceac..e7e5e6887 100644 --- a/client/src/features/menu/EventListMenu.module.scss +++ b/client/src/features/menu/EventListMenu.module.scss @@ -4,3 +4,9 @@ gap: 8px; padding-top: 24px; } + +.labelledSwitch { + display: flex; + align-items: center; + gap: 8px; +} \ No newline at end of file diff --git a/client/src/features/menu/EventListMenu.tsx b/client/src/features/menu/EventListMenu.tsx index 875d79a1e..a73bc5fa5 100644 --- a/client/src/features/menu/EventListMenu.tsx +++ b/client/src/features/menu/EventListMenu.tsx @@ -1,6 +1,5 @@ import { memo, useCallback, useContext } from 'react'; import { - Button, Divider, HStack, IconButton, @@ -8,6 +7,7 @@ import { MenuButton, MenuItem, MenuList, + Switch, Tooltip, } from '@chakra-ui/react'; import { FiClock } from '@react-icons/all-files/fi/FiClock'; @@ -29,13 +29,10 @@ const EventListMenu = () => { const { isCursorLocked, toggleCursorLocked } = useContext(CursorContext); const { addEvent, deleteAllEvents } = useEventAction(); - type ActionTypes = 'event' | 'delay' | 'block' | 'delete-all' | 'toggle-lock'; - const actionHandler = useCallback( + type ActionTypes = 'event' | 'delay' | 'block' | 'delete-all'; + const eventAction = useCallback( (action: ActionTypes) => { switch (action) { - case 'toggle-lock': - toggleCursorLocked(); - break; case 'event': addEvent({ type: action }); break; @@ -55,14 +52,14 @@ const EventListMenu = () => { return ( - + { aria-label='Create Menu' size='sm' icon={} - colorScheme='blue' + colorScheme='white' variant='outline' /> - } onClick={() => actionHandler('event')}> - Add Event first + } onClick={() => eventAction('event')}> + Add Event at start - } onClick={() => actionHandler('delay')}> - Add Delay first + } onClick={() => eventAction('delay')}> + Add Delay at start - } onClick={() => actionHandler('block')}> - Add Block first + } onClick={() => eventAction('block')}> + Add Block at start - } onClick={() => actionHandler('delete-all')} color='red.500'> + } onClick={() => eventAction('delete-all')} color='red.500'> Delete All diff --git a/client/src/theme/_main.scss b/client/src/theme/_main.scss index df9da6fa0..0986e39b4 100644 --- a/client/src/theme/_main.scss +++ b/client/src/theme/_main.scss @@ -17,15 +17,17 @@ $bg-gray-100: #c0c0c0; // borders and whatnot $bg-overlay: rgba(0, 0, 0, 0.85); -$ontime-accent: #4bffab; +// $ontime-accent: #4bffab); +$ontime-accent: #58A151; $ontime-accent-text: mix($bg-black, $ontime-accent, 10%); $ontime-pink: #ff7597; $ontime-pink-variant: #ff6969; -$ontime-roll: #2b6cb0; -$ontime-delay: #dd6b20; +$ontime-roll: #0274B6; +$ontime-delay: #F57C13; $action-blue: #3182ce; $ontime-paused: #c05621; $opacity-disabled: 0.4; +$ontime-red: #E4281E; //rgba(255, 255, 255, 0.39); - $bg-gray-700 //rgba(255, 255, 255, 0.13); - $bg-gray-900 @@ -40,15 +42,15 @@ $opacity-disabled: 0.4; // outdent in level2 - $bg-gray-950 //////////////////////////////////// editor -$notes-color: #d69e2e; +$notes-color: #9fd8ff; $text-white: #fffffa; $text-gray-disabled: #505050; -$header-gray: #ccc; $label-gray: #aaa; +$header-gray: $label-gray; $clocks: #ddd; $bg-gray: #f4f4f8; -$text-delay: #a97d24; +$text-delay: #F57C13; $light-bg: #2b6cb0; $light-bg-transparent: #2b6cb055; @@ -65,16 +67,18 @@ $title-gray: #ddd; $subtitle-gray: #aaa; //////////////////////////////////// block elements +$bg-container-over: #0b1521; +$bg-container-over-l1: #132337; $bg-container-l1: #202020; $bg-container-l2: #232323; $bg-container-l3: #2b2b2b; $border-l1: 1px solid $bg-gray-1000; $border-l3: 1px solid $bg-gray-900; -$block-delay-color: #ecc94b; +$block-delay-color: #E2720D; $delay-text: #d69e2e; $block-delay-border: #d69e2e55; -$block-block-color: #805ad5; +$block-block-color: #7347AD; $block-border: 1px solid $bg-gray-1100; //////////////////////////////////// viewer cards diff --git a/client/src/theme/_mixins.scss b/client/src/theme/_mixins.scss index 44f0b194c..581698374 100644 --- a/client/src/theme/_mixins.scss +++ b/client/src/theme/_mixins.scss @@ -18,10 +18,3 @@ border: 1px solid rgba(0, 0, 0, 0.05); border-radius: 2px; } - -@mixin osc-label { - color: $ontime-accent-text; - font-size: 0.8em; - -webkit-user-select: text; - user-select: text; -}