mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-11 02:13:48 +00:00
feat: V2 ontime menu (#259)
This commit is contained in:
@@ -1,116 +0,0 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { IconButton, Image } from '@chakra-ui/react';
|
||||
import { IoContract } from '@react-icons/all-files/io5/IoContract';
|
||||
import { IoExpand } from '@react-icons/all-files/io5/IoExpand';
|
||||
import { IoSync } from '@react-icons/all-files/io5/IoSync';
|
||||
import navlogo from 'assets/images/logos/LOGO-72.png';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { useAtom } from 'jotai';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { mirrorViewersAtom } from '../../atoms/ViewerSettings';
|
||||
import useFullscreen from '../../hooks/useFullscreen';
|
||||
|
||||
import navigatorConstants from './navigatorConstants';
|
||||
|
||||
import style from './NavLogo.module.scss';
|
||||
|
||||
/* Styling for action buttons */
|
||||
const navButtonStyle = {
|
||||
size: 'md',
|
||||
variant: 'outline',
|
||||
colorScheme: 'whiteAlpha',
|
||||
_hover: { bg: '#ebedf0', color: '#333' },
|
||||
};
|
||||
|
||||
export default function NavLogo(props) {
|
||||
const { isHidden } = props;
|
||||
const [showNav, setShowNav] = useState(false);
|
||||
const { isFullScreen, toggleFullScreen } = useFullscreen();
|
||||
const [isMirrored, setMirrored] = useAtom(mirrorViewersAtom);
|
||||
|
||||
const handleClick = useCallback(() => {
|
||||
setShowNav((prev) => !prev);
|
||||
}, []);
|
||||
|
||||
// Handle keyboard shortcuts
|
||||
const handleKeyPress = useCallback((e) => {
|
||||
// handle held key
|
||||
if (e.repeat) return;
|
||||
// Space bar
|
||||
if (e.keyCode === 32) {
|
||||
setShowNav((s) => !s);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// attach the event listener
|
||||
document.addEventListener('keydown', handleKeyPress);
|
||||
|
||||
// remove the event listener
|
||||
return () => {
|
||||
document.removeEventListener('keydown', handleKeyPress);
|
||||
};
|
||||
}, [handleKeyPress]);
|
||||
|
||||
const baseOpacity = isHidden ? 0 : 0.5;
|
||||
const tabProps = {
|
||||
className: style.navItem,
|
||||
tabIndex: 0,
|
||||
};
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ opacity: showNav ? 0.5 : baseOpacity }}
|
||||
whileHover={{ opacity: 1 }}
|
||||
className={style.navContainer}
|
||||
data-testid='nav-logo'
|
||||
>
|
||||
<Image alt='' src={navlogo} className={style.logo} onClick={handleClick} />
|
||||
<AnimatePresence>
|
||||
{showNav && (
|
||||
<>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scaleX: 0 }}
|
||||
animate={{ opacity: 1, scaleX: 1 }}
|
||||
whileInView={{ opacity: 1 }}
|
||||
exit={{ opacity: 0, scaleX: 0 }}
|
||||
className={style.actions}
|
||||
>
|
||||
<IconButton
|
||||
aria-label='Mirror screen'
|
||||
icon={<IoSync />}
|
||||
onClick={() => setMirrored((prev) => !prev)}
|
||||
{...navButtonStyle}
|
||||
/>
|
||||
<IconButton
|
||||
aria-label='Toggle Fullscreen'
|
||||
icon={isFullScreen ? <IoContract /> : <IoExpand />}
|
||||
onClick={toggleFullScreen}
|
||||
{...navButtonStyle}
|
||||
/>
|
||||
</motion.div>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0, y: -50 }}
|
||||
animate={{ opacity: 1, scale: 1, y: 0 }}
|
||||
whileInView={{ opacity: 1 }}
|
||||
exit={{ opacity: 0, scaleY: 0, y: -50 }}
|
||||
className={style.nav}
|
||||
>
|
||||
{navigatorConstants.map((route) => (
|
||||
<Link to={route.url} key={route.url} {...tabProps}>
|
||||
{route.label}
|
||||
</Link>
|
||||
))}
|
||||
</motion.div>
|
||||
</>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
NavLogo.propTypes = {
|
||||
isHidden: PropTypes.bool,
|
||||
};
|
||||
@@ -1,41 +0,0 @@
|
||||
@use '../../../theme/main' as *;
|
||||
|
||||
.navContainer {
|
||||
position: absolute;
|
||||
right: 2vw;
|
||||
top: 1vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
font-size: max(1vw, 16px);
|
||||
z-index: 10;
|
||||
|
||||
.logo {
|
||||
width: max(3vw, 32px);
|
||||
opacity: 0.5;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nav,
|
||||
.showNav {
|
||||
margin-top: 2vh;
|
||||
gap: 2vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.navItem {
|
||||
background-color: $bg-overlay;
|
||||
padding: 0.5vh 1vw;
|
||||
border-radius: 4px;
|
||||
color: $text-white;
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
position: absolute;
|
||||
top: 0.5vw;
|
||||
right: 75px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
$action-text-color: #87A3EF;
|
||||
$border-color: rgba(white, 0.1);
|
||||
$menu-bg: #202020;
|
||||
$menu-hover-bg: #101010;
|
||||
$menu-focus-bg: #181818;
|
||||
$menu-box-shadow: rgba(0, 0, 0, 0.15) 0 3px 3px 0;
|
||||
|
||||
$icon-color: #f6f6f6;
|
||||
$button-bg: #303030;
|
||||
$button-size: 48px;
|
||||
|
||||
$ontime-pink: #ff7597;
|
||||
|
||||
// Todo: remove important once style is retired
|
||||
a {
|
||||
&::after {
|
||||
content: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.mirror {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.navButton {
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
left: 0.5em;
|
||||
top: 0.5em;
|
||||
transition-property: opacity;
|
||||
transition-duration: 0.3s;
|
||||
opacity: 1;
|
||||
font-size: 24px;
|
||||
color: $icon-color;
|
||||
background-color: $button-bg;
|
||||
width: $button-size;
|
||||
height: $button-size;
|
||||
display: grid;
|
||||
place-content: center;
|
||||
border-radius: 3px;
|
||||
|
||||
&.hidden {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.menuContainer {
|
||||
top: 0;
|
||||
left: 0;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
height: fit-content;
|
||||
position: absolute;
|
||||
background-color: $menu-bg;
|
||||
min-width: 200px;
|
||||
border-radius: 0 0 24px 0;
|
||||
border-right: 1px solid $border-color;
|
||||
|
||||
box-shadow: $menu-box-shadow;
|
||||
padding-bottom: 1rem;
|
||||
|
||||
max-height: 100vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.buttonsContainer {
|
||||
margin-top: calc(56px + 1rem);
|
||||
}
|
||||
|
||||
.link {
|
||||
color: $action-text-color;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0.5rem 1rem;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
|
||||
&:hover {
|
||||
background-color: $menu-hover-bg;
|
||||
color: $ontime-pink;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: $border-color;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
background-color: $menu-focus-bg;
|
||||
border-left: 2px solid $action-text-color;
|
||||
}
|
||||
|
||||
&.current {
|
||||
background-color: $menu-hover-bg;
|
||||
border-left: 4px solid $action-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.linkIcon {
|
||||
display: inline-block;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.separator {
|
||||
border-color: $border-color;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
import { KeyboardEvent, useEffect, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { IoApps } from '@react-icons/all-files/io5/IoApps';
|
||||
import { IoArrowUp } from '@react-icons/all-files/io5/IoArrowUp';
|
||||
import { IoContract } from '@react-icons/all-files/io5/IoContract';
|
||||
import { IoExpand } from '@react-icons/all-files/io5/IoExpand';
|
||||
import { IoSwapVertical } from '@react-icons/all-files/io5/IoSwapVertical';
|
||||
import { useAtom } from 'jotai';
|
||||
|
||||
import { navigatorConstants } from '../../../viewerConfig';
|
||||
import { mirrorViewersAtom } from '../../atoms/ViewerSettings';
|
||||
import useFullscreen from '../../hooks/useFullscreen';
|
||||
import { useKeyDown } from '../../hooks/useKeyDown';
|
||||
|
||||
import style from './NavigationMenu.module.scss';
|
||||
|
||||
// Todo: restyle _main.scss links
|
||||
export default function NavigationMenu() {
|
||||
const location = useLocation();
|
||||
|
||||
const { isFullScreen, toggleFullScreen } = useFullscreen();
|
||||
const [isMirrored, setMirrored] = useAtom(mirrorViewersAtom);
|
||||
const [showButton, setShowButton] = useState(false);
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
|
||||
const toggleMenu = () => setShowMenu((prev) => !prev);
|
||||
useKeyDown(toggleMenu, ' ');
|
||||
|
||||
useEffect(() => {
|
||||
let fadeOut: NodeJS.Timeout | null = null;
|
||||
const setShowMenuTrue = () => {
|
||||
setShowButton(true);
|
||||
if (fadeOut) {
|
||||
clearTimeout(fadeOut);
|
||||
}
|
||||
fadeOut = setTimeout(() => setShowButton(false), 3000);
|
||||
};
|
||||
document.addEventListener('mousemove', setShowMenuTrue);
|
||||
return () => {
|
||||
document.removeEventListener('mousemove', setShowMenuTrue);
|
||||
if (fadeOut) {
|
||||
clearTimeout(fadeOut);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
const isKeyEnter = (event: KeyboardEvent<HTMLDivElement>) => event.key === 'Enter';
|
||||
const handleFullscreen = () => toggleFullScreen();
|
||||
const handleMirror = () => setMirrored((prev) => !prev);
|
||||
|
||||
return createPortal(
|
||||
<div id='navigation-menu-portal' className={isMirrored ? style.mirror : ''}>
|
||||
<button
|
||||
onClick={toggleMenu}
|
||||
aria-label='toggle menu'
|
||||
className={`${style.navButton} ${!showButton && !showMenu ? style.hidden : ''}`}
|
||||
>
|
||||
<IoApps />
|
||||
</button>
|
||||
|
||||
{showMenu && (
|
||||
<div className={style.menuContainer} data-testid='navigation-menu'>
|
||||
<div className={style.buttonsContainer}>
|
||||
<div
|
||||
className={style.link}
|
||||
tabIndex={0}
|
||||
onClick={handleFullscreen}
|
||||
onKeyDown={(event) => {
|
||||
isKeyEnter(event) && handleFullscreen();
|
||||
}}
|
||||
>
|
||||
Toggle Fullscreen
|
||||
{isFullScreen ? <IoContract /> : <IoExpand />}
|
||||
</div>
|
||||
<div
|
||||
className={style.link}
|
||||
tabIndex={0}
|
||||
onClick={handleMirror}
|
||||
onKeyDown={(event) => {
|
||||
isKeyEnter(event) && handleMirror();
|
||||
}}>
|
||||
Mirror Screen
|
||||
<IoSwapVertical />
|
||||
</div>
|
||||
{/*<div className={style.link} tabIndex={0}>*/}
|
||||
{/* Rename Client*/}
|
||||
{/*</div>*/}
|
||||
</div>
|
||||
<hr className={style.separator} />
|
||||
{navigatorConstants.map((route) => (
|
||||
<Link
|
||||
key={route.url}
|
||||
to={route.url}
|
||||
className={`${style.link} ${route.url === location.pathname ? style.current : undefined}`}
|
||||
tabIndex={0}>
|
||||
{route.label}
|
||||
<IoArrowUp className={style.linkIcon} />
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>, document.body);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export const useKeyDown = (callback: () => void, targetKey: string) => {
|
||||
const onKeyDown = (event: KeyboardEvent) => {
|
||||
const targetKeyPressed = event.key === targetKey && !event.repeat;
|
||||
if (targetKeyPressed) {
|
||||
event.preventDefault();
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener('keydown', onKeyDown);
|
||||
return () => {
|
||||
document.removeEventListener('keydown', onKeyDown);
|
||||
};
|
||||
}, [onKeyDown]);
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
// Vitest Snapshot v1
|
||||
|
||||
exports[`cx() > ignores falsy values 1`] = `""`;
|
||||
|
||||
exports[`cx() > merges styles 1`] = `"_test_98a1e0 _another_98a1e0"`;
|
||||
@@ -0,0 +1,2 @@
|
||||
.test {}
|
||||
.another {}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { cx } from '../styleUtils';
|
||||
|
||||
import style from './styleUtils.module.scss';
|
||||
|
||||
describe('cx()', () => {
|
||||
test('merges styles', () => {
|
||||
const merged = cx([style.test, style.another]);
|
||||
expect(merged).toMatchSnapshot();
|
||||
});
|
||||
test('ignores falsy values', () => {
|
||||
const falsyStuff = false;
|
||||
const merged = cx([undefined, false, 0, null, falsyStuff ? style.test : null]);
|
||||
console.log(merged)
|
||||
expect(merged).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -26,4 +26,4 @@ export const getAccessibleColour = (bgColour: string): ColourCombination => {
|
||||
* @description Creates a list of classnames from array of css module conditions
|
||||
* @param classNames - css modules objects
|
||||
*/
|
||||
export const cx = (...classNames: any[]) => classNames.filter(Boolean).join(" ")
|
||||
export const cx = (classNames: any[]) => classNames.filter(Boolean).join(" ");
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import QRCode from 'react-qr-code';
|
||||
import NavLogo from 'common/components/nav/NavLogo';
|
||||
import TitleSide from 'common/components/title-side/TitleSide';
|
||||
import { formatDisplay } from 'common/utils/dateConfig';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
@@ -9,6 +8,7 @@ import PropTypes from 'prop-types';
|
||||
|
||||
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
||||
import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings';
|
||||
import NavigationMenu from '../../../common/components/navigation-menu/NavigationMenu';
|
||||
import Paginator from '../../../common/components/paginator/Paginator';
|
||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||
import { getEventsWithDelay } from '../../../common/utils/eventsManager';
|
||||
@@ -62,7 +62,7 @@ export default function Backstage(props) {
|
||||
|
||||
return (
|
||||
<div className={`backstage ${isMirrored ? 'mirror' : ''}`} data-testid='backstage-view'>
|
||||
<NavLogo />
|
||||
<NavigationMenu />
|
||||
|
||||
<div className='event-title'>{general.title}</div>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useAtom } from 'jotai';
|
||||
|
||||
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
||||
import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings';
|
||||
import NavLogo from '../../../common/components/nav/NavLogo';
|
||||
import NavigationMenu from '../../../common/components/navigation-menu/NavigationMenu';
|
||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||
import { TimeManagerType } from '../../../common/models/TimeManaget.type';
|
||||
import { ViewSettingsType } from '../../../common/models/ViewSettings.type';
|
||||
@@ -120,9 +120,6 @@ export default function Clock(props: ClockProps) {
|
||||
}
|
||||
}
|
||||
|
||||
const hideNav = searchParams.get('hidenav');
|
||||
userOptions.hideNav = Boolean(hideNav);
|
||||
|
||||
const clock = formatTime(time.clock, formatOptions);
|
||||
const clean = clock.replace('/:/g', '');
|
||||
|
||||
@@ -137,7 +134,7 @@ export default function Clock(props: ClockProps) {
|
||||
}}
|
||||
data-testid='clock-view'
|
||||
>
|
||||
{!userOptions?.hideNav && <NavLogo />}
|
||||
<NavigationMenu />
|
||||
<div
|
||||
className='clock'
|
||||
style={{
|
||||
|
||||
@@ -5,7 +5,7 @@ import PropTypes from 'prop-types';
|
||||
|
||||
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
||||
import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings';
|
||||
import NavLogo from '../../../common/components/nav/NavLogo';
|
||||
import NavigationMenu from '../../../common/components/navigation-menu/NavigationMenu';
|
||||
import Empty from '../../../common/components/state/Empty';
|
||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||
import { formatDisplay, millisToSeconds } from '../../../common/utils/dateConfig';
|
||||
@@ -94,7 +94,7 @@ export default function Countdown(props) {
|
||||
|
||||
return (
|
||||
<div className={`countdown ${isMirrored ? 'mirror' : ''}`} data-testid='countdown-view'>
|
||||
<NavLogo />
|
||||
<NavigationMenu />
|
||||
{follow === null ? (
|
||||
<div className='event-select' data-testid='countdown-select'>
|
||||
<span className='event-select__title'>Select an event to follow</span>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
|
||||
import NavLogo from "../../../common/components/nav/NavLogo";
|
||||
import NavigationMenu from '../../../common/components/navigation-menu/NavigationMenu';
|
||||
|
||||
import './LowerClean.scss';
|
||||
|
||||
@@ -87,7 +87,7 @@ export default function LowerClean(props) {
|
||||
}}
|
||||
>
|
||||
|
||||
<NavLogo isHidden />
|
||||
<NavigationMenu />
|
||||
|
||||
<AnimatePresence>
|
||||
{showLower && (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
|
||||
import NavLogo from "../../../common/components/nav/NavLogo";
|
||||
import NavigationMenu from '../../../common/components/navigation-menu/NavigationMenu';
|
||||
|
||||
import './LowerLines.scss';
|
||||
|
||||
@@ -130,7 +130,7 @@ export default function LowerLines(props) {
|
||||
}}
|
||||
>
|
||||
|
||||
<NavLogo isHidden />
|
||||
<NavigationMenu />
|
||||
|
||||
<AnimatePresence>
|
||||
{showLower && (
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useAtom } from 'jotai';
|
||||
|
||||
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
||||
import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings';
|
||||
import NavLogo from '../../../common/components/nav/NavLogo';
|
||||
import NavigationMenu from '../../../common/components/navigation-menu/NavigationMenu';
|
||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||
import { PresenterMessageType } from '../../../common/models/PresenterMessage.type';
|
||||
import { TimeManagerType } from '../../../common/models/TimeManaget.type';
|
||||
@@ -117,9 +117,6 @@ export default function MinimalTimer(props: MinimalTimerProps) {
|
||||
}
|
||||
}
|
||||
|
||||
const hideNav = searchParams.get('hidenav');
|
||||
userOptions.hideNav = Boolean(hideNav);
|
||||
|
||||
const hideOvertime = searchParams.get('hideovertime');
|
||||
userOptions.hideOvertime = Boolean(hideOvertime);
|
||||
|
||||
@@ -144,6 +141,7 @@ export default function MinimalTimer(props: MinimalTimerProps) {
|
||||
}}
|
||||
data-testid='minimal-timer'
|
||||
>
|
||||
<NavigationMenu />
|
||||
{!hideMessagesOverlay && (
|
||||
<div
|
||||
className={showOverlay ? 'message-overlay message-overlay--active' : 'message-overlay'}
|
||||
@@ -151,7 +149,6 @@ export default function MinimalTimer(props: MinimalTimerProps) {
|
||||
<div className='message'>{pres.text}</div>
|
||||
</div>
|
||||
)}
|
||||
{!userOptions?.hideNav && <NavLogo />}
|
||||
<div
|
||||
className={`timer ${!isPlaying ? 'timer--paused' : ''} ${
|
||||
showFinished ? 'timer--finished' : ''
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import QRCode from 'react-qr-code';
|
||||
import { ReactComponent as Emptyimage } from 'assets/images/empty.svg';
|
||||
import NavLogo from 'common/components/nav/NavLogo';
|
||||
import { formatDisplay } from 'common/utils/dateConfig';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { useAtom } from 'jotai';
|
||||
@@ -9,6 +8,7 @@ import PropTypes from 'prop-types';
|
||||
|
||||
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
||||
import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings';
|
||||
import NavigationMenu from '../../../common/components/navigation-menu/NavigationMenu';
|
||||
import Paginator from '../../../common/components/paginator/Paginator';
|
||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||
import { formatTime } from '../../../common/utils/time';
|
||||
@@ -69,7 +69,7 @@ export default function Pip(props) {
|
||||
|
||||
return (
|
||||
<div className={`pip ${isMirrored ? 'mirror' : ''}`} data-testid='pip-view'>
|
||||
<NavLogo />
|
||||
<NavigationMenu />
|
||||
|
||||
<div className='event-title'>{general.title}</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import QRCode from 'react-qr-code';
|
||||
import NavLogo from 'common/components/nav/NavLogo';
|
||||
import TitleSide from 'common/components/title-side/TitleSide';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { useAtom } from 'jotai';
|
||||
@@ -8,6 +7,7 @@ import PropTypes from 'prop-types';
|
||||
|
||||
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
||||
import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings';
|
||||
import NavigationMenu from '../../../common/components/navigation-menu/NavigationMenu';
|
||||
import Paginator from '../../../common/components/paginator/Paginator';
|
||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||
import { formatTime } from '../../../common/utils/time';
|
||||
@@ -42,7 +42,7 @@ export default function Public(props) {
|
||||
|
||||
return (
|
||||
<div className={`public-screen ${isMirrored ? 'mirror' : ''}`} data-testid='public-view'>
|
||||
<NavLogo />
|
||||
<NavigationMenu />
|
||||
|
||||
<div className='event-title'>{general.title}</div>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
|
||||
|
||||
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
||||
import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings';
|
||||
import NavLogo from '../../../common/components/nav/NavLogo';
|
||||
import NavigationMenu from '../../../common/components/navigation-menu/NavigationMenu';
|
||||
import useFitText from '../../../common/hooks/useFitText';
|
||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||
import { formatDisplay } from '../../../common/utils/dateConfig';
|
||||
@@ -58,7 +58,7 @@ export default function StudioClock(props) {
|
||||
|
||||
return (
|
||||
<div className={`studio-clock ${isMirrored ? 'mirror' : ''}`} data-testid='studio-view'>
|
||||
<NavLogo />
|
||||
<NavigationMenu />
|
||||
<div className='clock-container'>
|
||||
<div className='studio-timer'>{clock}</div>
|
||||
<div
|
||||
|
||||
@@ -2,7 +2,6 @@ import { useEffect, useState } from 'react';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import TimerDisplay from 'common/components/countdown/TimerDisplay';
|
||||
import MyProgressBar from 'common/components/myProgressBar/MyProgressBar';
|
||||
import NavLogo from 'common/components/nav/NavLogo';
|
||||
import TitleCard from 'common/components/title-card/TitleCard';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { useAtom } from 'jotai';
|
||||
@@ -10,6 +9,7 @@ import PropTypes from 'prop-types';
|
||||
|
||||
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
||||
import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings';
|
||||
import NavigationMenu from '../../../common/components/navigation-menu/NavigationMenu';
|
||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||
import { formatTime } from '../../../common/utils/time';
|
||||
|
||||
@@ -72,12 +72,12 @@ export default function Timer(props) {
|
||||
return (
|
||||
<div className={time.finished ? `${baseClasses} stage-timer--finished` : baseClasses}
|
||||
data-testid='timer-view'>
|
||||
<div className={showOverlay ? 'message-overlay message-overlay--active' : 'message-overlay'}>
|
||||
<NavigationMenu />
|
||||
<div
|
||||
className={showOverlay ? 'message-overlay message-overlay--active' : 'message-overlay'}>
|
||||
<div className='message'>{pres.text}</div>
|
||||
</div>
|
||||
|
||||
<NavLogo />
|
||||
|
||||
<div className='clock-container'>
|
||||
<div className='label'>Time Now</div>
|
||||
<div className='clock'>{clock}</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const navigatorConstants = [
|
||||
export const navigatorConstants = [
|
||||
{ url: '/timer', label: 'Timer' },
|
||||
{ url: '/clock', label: 'Clock' },
|
||||
{ url: '/minimal', label: 'Minimal Timer' },
|
||||
@@ -9,5 +9,3 @@ const navigatorConstants = [
|
||||
{ url: '/studio', label: 'Studio Clock' },
|
||||
{ url: '/countdown', label: 'Countdown' },
|
||||
];
|
||||
|
||||
export default navigatorConstants;
|
||||
Reference in New Issue
Block a user