diff options
author | Marcin Zelent <marcin@zelent.net> | 2021-01-08 19:47:37 +0100 |
---|---|---|
committer | Marcin Zelent <marcin@zelent.net> | 2021-01-08 19:47:37 +0100 |
commit | 628632ff5092f1e3cf6c968d9bdfbd9a24f59541 (patch) | |
tree | feddb4e82267bba700a15a6a7091f922f48cae40 /components/Sidebar |
Initial commit
Diffstat (limited to 'components/Sidebar')
-rw-r--r-- | components/Sidebar/Sidebar.module.css | 54 | ||||
-rw-r--r-- | components/Sidebar/Sidebar.tsx | 71 |
2 files changed, 125 insertions, 0 deletions
diff --git a/components/Sidebar/Sidebar.module.css b/components/Sidebar/Sidebar.module.css new file mode 100644 index 0000000..a3c8a1a --- /dev/null +++ b/components/Sidebar/Sidebar.module.css @@ -0,0 +1,54 @@ +.aside { + min-width: 272px; + height: 100%; + padding: 5px; + display: flex; + flex-direction: column; + border-right: 1px solid #e5e5e5; + box-shadow: -2px 0 10px #000; + z-index: 9999; + background-color: #fff; +} + +.aside h2 { + padding-left: 1.5rem; +} + +.list { + margin: 0; + padding: 0; + list-style: none; + overflow-y: auto; +} + +.listItem { + margin-bottom: 5px; + padding: 1rem 2rem 1rem 1.5rem; + display: block; + border-radius: 10px; + cursor: pointer; + user-select: none; + outline: currentcolor none medium; +} + +.listItem:hover { + background-color: #f5f5f5; +} + +.listItemActive { + background-color: #e9f3ff !important; +} + +@media only screen and (max-width: 500px) { + .aside { + position: absolute; + top: 0; + bottom: 0; + left: -100vw; + transition: left 0.3s ease-in; + } + + .asideOpen { + left: 0; + } +} diff --git a/components/Sidebar/Sidebar.tsx b/components/Sidebar/Sidebar.tsx new file mode 100644 index 0000000..6b0473a --- /dev/null +++ b/components/Sidebar/Sidebar.tsx @@ -0,0 +1,71 @@ +import { useEffect, useRef } from 'react'; + +import { Trip } from 'models'; +import { secondsToTimeString } from 'lib/util'; + +import styles from './Sidebar.module.css'; + +interface Props { + trips: Trip[]; + currentTrip: Trip; + asideOpen: boolean; + handleClose: () => void; + setCurrentTrip: (trip: Trip) => void; +} + +export default function Sidebar({ + trips, + currentTrip, + asideOpen, + handleClose, + setCurrentTrip, +}: Props): JSX.Element { + const wrapperRef = useRef(null); + + useEffect(() => { + function handleClickOutside(e: MouseEvent) { + if (wrapperRef.current && !wrapperRef.current.contains(e.target)) { + handleClose(); + } + } + + document.addEventListener('mousedown', handleClickOutside); + return () => { + document.removeEventListener('mousedown', handleClickOutside); + }; + }, [wrapperRef]); + + function handleTripChange(trip: Trip): void { + setCurrentTrip(trip); + handleClose(); + } + + return ( + <aside ref={wrapperRef} className={`${styles.aside} ${asideOpen && styles.asideOpen}`}> + <h2>Trips</h2> + <ul className={styles.list}> + {trips.map((t) => ( + <li key={t.name}> + <a + onClick={() => handleTripChange(t)} + onKeyPress={() => handleTripChange(t)} + tabIndex={0} + role="menuitem" + className={`${styles.listItem} ${ + t.name === currentTrip.name && styles.listItemActive + }`} + > + <b>{new Date(t.start).toDateString()}</b> + <br /> + Total distance: {t.distance} km + <br /> + Duration: {secondsToTimeString(t.duration)} + <br /> + Average speed: {t.speed} km/h + </a> + </li> + ))} + </ul> + </aside> + ); +} |