From 57c6b11db1bf2932cef72b591cafb5921a1f7530 Mon Sep 17 00:00:00 2001 From: cv <34649812+cpvalente@users.noreply.github.com> Date: Wed, 21 Apr 2021 19:11:43 +0200 Subject: [PATCH] style improvements - added empty state to list - styled scrollbars - progressbar shows time elapsed - timers are monospace - prevent overflow in titles --- client/src/App.css | 2 +- client/src/assets/images/empty.svg | 21 ++ .../components/buttons/SettingsIconBtn.jsx | 14 ++ .../myProgressBar/MyProgressBar.jsx | 7 +- .../src/common/input/EditableTimer.module.css | 5 +- client/src/common/state/Empty.jsx | 12 + client/src/common/state/Empty.module.css | 16 ++ .../src/features/control/MessageControl.jsx | 12 +- .../control/MessageControl.module.css | 5 +- client/src/features/editors/Editor.jsx | 223 ++++++++---------- client/src/features/editors/Editor.module.css | 105 ++++++++- .../features/editors/list/Block.module.css | 7 +- .../src/features/editors/list/EventList.jsx | 8 + .../src/features/editors/list/List.module.css | 7 + client/src/features/menu/EventListMenu.jsx | 19 +- .../features/menu/EventListMenu.module.css | 7 +- .../src/features/viewers/PreviewContainer.jsx | 5 +- client/src/features/viewers/ViewWrapper.jsx | 5 +- .../features/viewers/backstage/Paginator.jsx | 20 +- .../viewers/backstage/Paginator.module.css | 1 - .../viewers/backstage/StageManager.module.css | 16 +- .../features/viewers/backstage/TodayItem.jsx | 4 +- .../features/viewers/lower/Lower.module.css | 15 +- .../viewers/presenter/PresenterView.jsx | 1 + .../presenter/PresenterView.module.css | 12 + client/src/features/viewers/viewers.css | 41 ---- 26 files changed, 381 insertions(+), 209 deletions(-) create mode 100644 client/src/assets/images/empty.svg create mode 100644 client/src/common/components/buttons/SettingsIconBtn.jsx create mode 100644 client/src/common/state/Empty.jsx create mode 100644 client/src/common/state/Empty.module.css delete mode 100644 client/src/features/viewers/viewers.css diff --git a/client/src/App.css b/client/src/App.css index 27b6f4c02..d49c3757f 100644 --- a/client/src/App.css +++ b/client/src/App.css @@ -8,4 +8,4 @@ overflow: hidden; background-color: rgba(0, 0, 0, 0); height: 100vh; -} +} \ No newline at end of file diff --git a/client/src/assets/images/empty.svg b/client/src/assets/images/empty.svg new file mode 100644 index 000000000..913948ced --- /dev/null +++ b/client/src/assets/images/empty.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/common/components/buttons/SettingsIconBtn.jsx b/client/src/common/components/buttons/SettingsIconBtn.jsx new file mode 100644 index 000000000..738aab8b3 --- /dev/null +++ b/client/src/common/components/buttons/SettingsIconBtn.jsx @@ -0,0 +1,14 @@ +import { IconButton } from '@chakra-ui/button'; +import { FiSettings } from 'react-icons/fi'; + +export default function SettingsIconBtn(props) { + return ( + } + isRound + variant='outline' + onClick={props.clickHandler} + /> + ); +} diff --git a/client/src/common/components/myProgressBar/MyProgressBar.jsx b/client/src/common/components/myProgressBar/MyProgressBar.jsx index 840af36e0..df76f5108 100644 --- a/client/src/common/components/myProgressBar/MyProgressBar.jsx +++ b/client/src/common/components/myProgressBar/MyProgressBar.jsx @@ -2,8 +2,11 @@ import { clamp } from '../../../app/utils'; import styles from './MyProgressBar.module.css'; export default function MyProgressBar(props) { - const { now, complete } = props; - const percentComplete = clamp((now * 100) / complete - 1, 0, 100); + const { now, complete, showElapsed } = props; + const percentComplete = showElapsed + ? clamp((100 - (now * 100) / complete - 1), 0, 100) + : clamp((now * 100) / complete - 1, 0, 100) + return (
diff --git a/client/src/common/input/EditableTimer.module.css b/client/src/common/input/EditableTimer.module.css index e38fb9cde..4ce165612 100644 --- a/client/src/common/input/EditableTimer.module.css +++ b/client/src/common/input/EditableTimer.module.css @@ -13,7 +13,7 @@ } .delayedEditable { - border: 1px solid #d69e2e88; + border: 1px solid #d69e2e55; } .delayValue { @@ -22,6 +22,5 @@ padding: 0.3em 0; text-align: center; align-self: flex-start; - border: 1px solid #d69e2e88; - background-color: #d69e2e22; + background-color: #d69e2e55; } diff --git a/client/src/common/state/Empty.jsx b/client/src/common/state/Empty.jsx new file mode 100644 index 000000000..f76965d63 --- /dev/null +++ b/client/src/common/state/Empty.jsx @@ -0,0 +1,12 @@ +import { ReactComponent as Emptyimage } from '../../assets/images/empty.svg'; +import style from './Empty.module.css'; + +export default function Empty(props) { + const { text } = props; + return ( +
+ + {text} +
+ ); +} diff --git a/client/src/common/state/Empty.module.css b/client/src/common/state/Empty.module.css new file mode 100644 index 000000000..1d66c890a --- /dev/null +++ b/client/src/common/state/Empty.module.css @@ -0,0 +1,16 @@ +.emptyContainer { + text-align: center; + color: rgba(0, 0, 0, 0.17); + font-weight: 600; + font-size: 2em; + width: 100%; +} +.empty { + width: 100%; + margin: auto 0; + opacity: 0.3; +} + +.text { + text-align: center; +} diff --git a/client/src/features/control/MessageControl.jsx b/client/src/features/control/MessageControl.jsx index 602e57ae6..615543808 100644 --- a/client/src/features/control/MessageControl.jsx +++ b/client/src/features/control/MessageControl.jsx @@ -89,8 +89,8 @@ export default function MessageControl() { placeholder='only the presenter screens see this' className={style.inline} > - - + + - - + + - - + + - - - - - Event List - - -
- -
-
-
+
+ + + Event List + + +
+ +
+
- - - - Preview Displays - - -
- -
-
-
+ + + Preview Displays + + +
+ +
+
- - - - Display Messages - - -
- -
-
-
+ + + Display Messages + + +
+ +
+
- - - - Time Control - - -
- -
-
-
+ + + Time Control + + +
+ +
+
- - + +
+
- } - isRound - variant='outline' - onClick={onOpen} - /> -
-
-
-
-
-
-
- - - + /> +
+
+
+
+
+
+ +
); } diff --git a/client/src/features/editors/Editor.module.css b/client/src/features/editors/Editor.module.css index 0462d6261..1b606b809 100644 --- a/client/src/features/editors/Editor.module.css +++ b/client/src/features/editors/Editor.module.css @@ -1,12 +1,71 @@ .mainContainer { background: linear-gradient(90deg, #202020 0%, #121212 100%); width: 100%; + height: 100%; margin: auto; - height: 95vh; color: #fffd; + padding: 2vh; + + display: grid; + grid-template-rows: 1fr 1fr 1fr; + grid-template-columns: 1fr 25vw 25vw 5vw; + grid-template-areas: + 'even mess play sett' + 'even prev prev sett' + 'even prev prev sett'; + gap: 2vh; } -.editor { +/* 2/3 window, hide previews */ +@media (max-width: 1250px) and (min-height: 700px) { + .mainContainer { + grid-template-rows: 1fr 1fr; + grid-template-columns: 1fr 1fr 1fr; + grid-template-areas: + 'even play sett' + 'even mess sett'; + } + + .preview { + visibility: hidden; + } +} + +/* 1/3 window, show control only */ +@media (max-width: 750px) and (min-height: 500px) { + .mainContainer { + grid-template-rows: auto 1fr; + grid-template-columns: 100%; + grid-template-areas: + 'mess' + 'play'; + } + + .editor, + .preview, + .settings { + visibility: hidden; + } +} + +/* 1/3 corner window, playback only */ +@media (max-width: 900px) and (max-height: 500px) { + .mainContainer { + grid-template-rows: 1fr; + grid-template-columns: 1fr; + grid-template-areas: 'play'; + } + + .editor, + .messages, + .preview, + .settings { + visibility: hidden; + } +} + +.mainContainer > div { + border-radius: 0.5em; height: 100%; margin-top: 1.5vh; background-color: rgba(255, 255, 255, 0.13); @@ -16,6 +75,26 @@ flex-direction: column; } +.editor { + grid-area: even; +} + +.preview { + grid-area: prev; +} + +.messages { + grid-area: mess; +} + +.playback { + grid-area: play; +} + +.settings { + grid-area: sett; +} + .content { padding-top: 1.5em; } @@ -32,3 +111,25 @@ display: flex; justify-content: flex-end; } + +/* width */ +::-webkit-scrollbar { + width: 0.5em; +} + +/* Track */ +::-webkit-scrollbar-track { + background: rgba(255, 255, 255, 0.01); + border-radius: 4px; +} + +/* Handle */ +::-webkit-scrollbar-thumb { + background: rgba(255, 255, 255, 0.15); + border-radius: 4px; +} + +/* Handle on hover */ +::-webkit-scrollbar-thumb:hover { + background: rgba(255, 255, 255, 0.35); +} diff --git a/client/src/features/editors/list/Block.module.css b/client/src/features/editors/list/Block.module.css index 93c0740eb..1fc7d4737 100644 --- a/client/src/features/editors/list/Block.module.css +++ b/client/src/features/editors/list/Block.module.css @@ -17,7 +17,6 @@ padding: 0.2em 1em; box-sizing: border-box; display: flex; - margin: auto; gap: 1em; } @@ -68,10 +67,8 @@ background-color: rgba(255, 255, 255, 0.36); background: linear-gradient( 180deg, - #4bffabcc 0%, - #227c52aa 09%, - #4bffab11 10%, - #4bffab11 89%, + #00000000 10%, + #4bffab10 89%, #227c52aa 90%, #4bffabcc 100% ); diff --git a/client/src/features/editors/list/EventList.jsx b/client/src/features/editors/list/EventList.jsx index 9f507d8f9..11be77df4 100644 --- a/client/src/features/editors/list/EventList.jsx +++ b/client/src/features/editors/list/EventList.jsx @@ -4,6 +4,8 @@ import BlockBlock from './BlockBlock'; import EventBlock from './EventBlock'; import { useEffect, useState } from 'react'; import { useSocket } from '../../../app/context/socketContext'; +import Empty from '../../../common/state/Empty'; + export default function EventList(props) { const { events, eventsHandler } = props; @@ -28,6 +30,12 @@ export default function EventList(props) { }; }, [socket]); + if (events.length < 1) { + return ( + + ); + } + console.log('EventList: events in event list', events); let cumulativeDelay = 0; let eventCount = -1; diff --git a/client/src/features/editors/list/List.module.css b/client/src/features/editors/list/List.module.css index a8c20abd2..0cee5f3de 100644 --- a/client/src/features/editors/list/List.module.css +++ b/client/src/features/editors/list/List.module.css @@ -7,4 +7,11 @@ border: 1px solid rgba(0, 0, 0, 0.05); border-radius: 4px; padding: 8px; + overflow-y: scroll; + height: 71vh; +} + +.empty { + opacity: 0.3; + align-self: center; } diff --git a/client/src/features/menu/EventListMenu.jsx b/client/src/features/menu/EventListMenu.jsx index b28fba79f..aab5270f1 100644 --- a/client/src/features/menu/EventListMenu.jsx +++ b/client/src/features/menu/EventListMenu.jsx @@ -16,7 +16,12 @@ export default function EventListMenu(props) { size: 'sm', variant: 'outline', colorScheme: 'whiteAlpha', - backgroundColor: '#ffffff05' + backgroundColor: '#ffffff05', + }; + + const menuStyle = { + color: 'initial', + backgroundColor: 'rgba(255,255,255,0.67)', }; const addHandler = () => { @@ -25,16 +30,14 @@ export default function EventListMenu(props) { return (
- + - + - + Upload Excel Upload CSV @@ -42,11 +45,11 @@ export default function EventListMenu(props) { - + - + Download Excel Download CSV diff --git a/client/src/features/menu/EventListMenu.module.css b/client/src/features/menu/EventListMenu.module.css index 608188698..fea55453a 100644 --- a/client/src/features/menu/EventListMenu.module.css +++ b/client/src/features/menu/EventListMenu.module.css @@ -3,4 +3,9 @@ gap: 0.5em; align-content: center; justify-content: flex-end; -} \ No newline at end of file +} + +.menu { + color: #000; + background-color: rgba(255, 255, 255, 0.67); +} diff --git a/client/src/features/viewers/PreviewContainer.jsx b/client/src/features/viewers/PreviewContainer.jsx index d13b429ec..2d8684141 100644 --- a/client/src/features/viewers/PreviewContainer.jsx +++ b/client/src/features/viewers/PreviewContainer.jsx @@ -20,7 +20,10 @@ export default function PreviewContainer() {
Stage Manager
- +
Lower third
diff --git a/client/src/features/viewers/ViewWrapper.jsx b/client/src/features/viewers/ViewWrapper.jsx index 96034b1df..32c7ce525 100644 --- a/client/src/features/viewers/ViewWrapper.jsx +++ b/client/src/features/viewers/ViewWrapper.jsx @@ -115,7 +115,10 @@ const withSocket = (Component) => { // Filter events only to pass down useEffect(() => { if (eventsData == null) return; - const e = eventsData.filter((d) => d.type === 'event'); + + // filter just events with title + const e = eventsData.filter((d) => d.type === 'event' && d.title !== ''); + setEvents(e); }, [eventsData]); diff --git a/client/src/features/viewers/backstage/Paginator.jsx b/client/src/features/viewers/backstage/Paginator.jsx index 395b8aeab..4f707b61e 100644 --- a/client/src/features/viewers/backstage/Paginator.jsx +++ b/client/src/features/viewers/backstage/Paginator.jsx @@ -5,7 +5,7 @@ import { useInterval } from '../../../app/hooks/useInterval'; export default function Paginator(props) { const { events, selectedId } = props; - const LIMIT_PER_PAGE = 3; + const LIMIT_PER_PAGE = 7; const SCROLL_TIME = 5000; const SCROLL_PAST = false; const [numEvents, setNumEvents] = useState(0); @@ -49,14 +49,16 @@ export default function Paginator(props) { return ( <> -
- {[...Array(pages)].map((p, i) => ( -
- ))} -
+ {pages > 1 && ( +
+ {[...Array(pages)].map((p, i) => ( +
+ ))} +
+ )}
{page.map((e) => { diff --git a/client/src/features/viewers/backstage/Paginator.module.css b/client/src/features/viewers/backstage/Paginator.module.css index 3e2f9380d..9a23ae659 100644 --- a/client/src/features/viewers/backstage/Paginator.module.css +++ b/client/src/features/viewers/backstage/Paginator.module.css @@ -2,7 +2,6 @@ display: flex; flex-direction: column; gap: 1.5vh; - padding-top: 2vh; } .navItem, diff --git a/client/src/features/viewers/backstage/StageManager.module.css b/client/src/features/viewers/backstage/StageManager.module.css index 2e6a790f3..93e18faa7 100644 --- a/client/src/features/viewers/backstage/StageManager.module.css +++ b/client/src/features/viewers/backstage/StageManager.module.css @@ -41,6 +41,17 @@ /* =================== TITLES ===================*/ +.infoContainer > div { + overflow:hidden; +} + +.nextContainer > div, +.nowContainer > div { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + .nowContainer, .nextContainer, .todayContainer { @@ -157,8 +168,10 @@ .entryStart, .entryEnd { font-size: 1.5vw; + min-width: 3.5vw; } + .entryTitle { align-self: center; } @@ -183,7 +196,7 @@ .entryNow { font-size: 1.3vw; color: #fff; - line-height: 7vh; + line-height: 4vh; background-color: rgba(255, 255, 255, 0.09); border-bottom: 0.5vh solid #ff7597aa; margin-left: -0.5vw; @@ -212,6 +225,7 @@ .infoMessages { grid-area: binf; font-size: 1.5vw; + line-height: 2vw; white-space: pre-line; } diff --git a/client/src/features/viewers/backstage/TodayItem.jsx b/client/src/features/viewers/backstage/TodayItem.jsx index 23b808d50..939a11ce5 100644 --- a/client/src/features/viewers/backstage/TodayItem.jsx +++ b/client/src/features/viewers/backstage/TodayItem.jsx @@ -4,8 +4,8 @@ export default function TodayItem(props) { const { selected, timeStart, timeEnd, title } = props; // Format timers - const start = timeStart ? stringFromMillis(timeStart, false) : ''; - const end = timeEnd ? stringFromMillis(timeEnd, false) : ''; + const start = stringFromMillis(timeStart, false) || ''; + const end = stringFromMillis(timeEnd, false) || ''; // select styling let selectStyle = style.entryPast; diff --git a/client/src/features/viewers/lower/Lower.module.css b/client/src/features/viewers/lower/Lower.module.css index 51898e9cd..708bc40b0 100644 --- a/client/src/features/viewers/lower/Lower.module.css +++ b/client/src/features/viewers/lower/Lower.module.css @@ -1,8 +1,12 @@ .lowerThird { + margin: 0; + box-sizing: border-box; /* reset */ + overflow: hidden; + width: 100%; /* restrict the page width to viewport */ + height: 100%; + color: #fffffa; font-size: 4vh; - width: 100%; - height: 100%; } .lowerContainer { @@ -36,6 +40,13 @@ position: relative; } +.titleContainer, +.subtitleContainer { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + .titleDecor, .subDecor { grid-area: decor; diff --git a/client/src/features/viewers/presenter/PresenterView.jsx b/client/src/features/viewers/presenter/PresenterView.jsx index 77ed48a29..ba8e966d0 100644 --- a/client/src/features/viewers/presenter/PresenterView.jsx +++ b/client/src/features/viewers/presenter/PresenterView.jsx @@ -41,6 +41,7 @@ export default function PresenterView(props) {
)} diff --git a/client/src/features/viewers/presenter/PresenterView.module.css b/client/src/features/viewers/presenter/PresenterView.module.css index dbc6a2f44..033d6a2b6 100644 --- a/client/src/features/viewers/presenter/PresenterView.module.css +++ b/client/src/features/viewers/presenter/PresenterView.module.css @@ -1,3 +1,5 @@ +@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;800&display=swap'); + .container__gray, .container__grayFinished { margin: 0; @@ -55,9 +57,18 @@ grid-area: next; } +.title, +.subtitle, +.presenter { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + .title { color: #ddd; font-size: 2.5vw; + flex: 1; } .subtitle, @@ -147,6 +158,7 @@ } .clock { + font-family: 'Open Sans', sans-serif; font-size: 4vw; letter-spacing: 0.4vw; color: #ddd; diff --git a/client/src/features/viewers/viewers.css b/client/src/features/viewers/viewers.css deleted file mode 100644 index 820096bed..000000000 --- a/client/src/features/viewers/viewers.css +++ /dev/null @@ -1,41 +0,0 @@ -@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;800&display=swap'); - -.presenter { - font-size: 1vh; - height: 100%; - color: #ffffff; - display: flex; - flex-direction: column; - padding-left: 4vh; -} - -.presentationTitle { - font-size: 5vw; - text-align: left; -} - -.presentationSub { - font-size: 3vw; - text-align: left; -} - -.userMessage { - font-size: 10vw; - text-align: center; -} - -.hidden { - display: none; -} - -.extra { - width: 100%; - position: absolute; - bottom: 3vh; - left: 0; - - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-around; -}