11/** @jsxRuntime classic */
22/** @jsxImportSource theme-ui */
33import { format } from "date-fns" ;
4- import { useEffect , useMemo , useState } from "react" ;
4+ import { useEffect , useMemo , useRef , useState } from "react" ;
55import { Box , Flex , Text , jsx } from "theme-ui" ;
66
77import type { Event } from "~/data/schedule" ;
@@ -17,6 +17,8 @@ type ReferenceTime = {
1717 time : Date | null ;
1818} ;
1919
20+ export type ColorMode = "light" | "dark" ;
21+
2022const getStartTime = ( event : Event ) =>
2123 event . when ? new Date ( event . when ) . getTime ( ) : Number . POSITIVE_INFINITY ;
2224
@@ -79,9 +81,12 @@ const getSpeakers = (event: Event) =>
7981 . filter ( Boolean )
8082 . join ( ", " ) ;
8183
82- export const CompactAgenda : React . FC < { schedule : Event [ ] } > = ( {
83- schedule,
84- } ) => {
84+ export const CompactAgenda : React . FC < {
85+ schedule : Event [ ] ;
86+ colorMode ?: ColorMode ;
87+ } > = ( { schedule, colorMode = "light" } ) => {
88+ const agendaItemRefs = useRef < ( HTMLElement | null ) [ ] > ( [ ] ) ;
89+ const hasScrolledToHighlight = useRef ( false ) ;
8590 const [ reference , setReference ] = useState < ReferenceTime > ( {
8691 isFixed : false ,
8792 time : null ,
@@ -123,6 +128,25 @@ export const CompactAgenda: React.FC<{ schedule: Event[] }> = ({
123128 [ schedule , reference . time ] ,
124129 ) ;
125130
131+ useEffect ( ( ) => {
132+ if ( hasScrolledToHighlight . current || ! reference . time ) {
133+ return ;
134+ }
135+
136+ const highlightedIndex = highlight . currentIndex ?? highlight . nextIndex ;
137+
138+ if ( highlightedIndex === null ) {
139+ return ;
140+ }
141+
142+ hasScrolledToHighlight . current = true ;
143+ window . requestAnimationFrame ( ( ) => {
144+ agendaItemRefs . current [ highlightedIndex ] ?. scrollIntoView ( {
145+ block : "center" ,
146+ } ) ;
147+ } ) ;
148+ } , [ highlight . currentIndex , highlight . nextIndex , reference . time ] ) ;
149+
126150 return (
127151 < Box
128152 as = "ol"
@@ -138,11 +162,15 @@ export const CompactAgenda: React.FC<{ schedule: Event[] }> = ({
138162 const isCurrent = highlight . currentIndex === index ;
139163 const isNext = highlight . nextIndex === index ;
140164 const speakers = getSpeakers ( event ) ;
165+ const isDark = colorMode === "dark" ;
141166
142167 return (
143168 < Box
144169 as = "li"
145170 key = { `${ event . when } -${ getTitle ( event ) } ` }
171+ ref = { ( element ) => {
172+ agendaItemRefs . current [ index ] = element ;
173+ } }
146174 sx = { {
147175 display : "grid" ,
148176 gridTemplateColumns : "4.2rem minmax(0, 1fr) auto" ,
@@ -154,17 +182,24 @@ export const CompactAgenda: React.FC<{ schedule: Event[] }> = ({
154182 px : ".75rem" ,
155183 py : ".5rem" ,
156184 border : "1px solid" ,
157- borderColor : isCurrent || isNext ? "primary" : "#eee" ,
185+ borderColor :
186+ isCurrent || isNext ? "primary" : isDark ? "#3a2725" : "#eee" ,
158187 borderRadius : ".8rem" ,
159188 backgroundColor : isCurrent
160189 ? "primary"
161190 : isNext
162- ? "#fff4f2"
163- : "white" ,
191+ ? isDark
192+ ? "#2c1d1b"
193+ : "#fff4f2"
194+ : isDark
195+ ? "#201817"
196+ : "white" ,
164197 boxShadow : isCurrent
165- ? "0 .8rem 2.4rem -1.6rem rgba(237, 67, 55, .75)"
198+ ? `0 .8rem 2.4rem -1.6rem rgba(237, 67, 55, ${
199+ isDark ? ".9" : ".75"
200+ } )`
166201 : undefined ,
167- color : isCurrent ? "white" : "text" ,
202+ color : isCurrent ? "white" : isDark ? "#f8ebe8" : "text" ,
168203 } }
169204 >
170205 < Text
0 commit comments