@@ -17,6 +17,8 @@ import {
17
17
ResetFiltersButton ,
18
18
} from "./filters"
19
19
import { formatBlockTime } from "./format-block-time"
20
+ import { useCurrentTimeMarker } from "./use-current-time-marker"
21
+ import { Button } from "@/app/conf/_design-system/button"
20
22
21
23
export interface FiltersConfig
22
24
extends Partial <
@@ -138,21 +140,32 @@ export function ScheduleList({
138
140
const firstDayIsDayZero = Object . keys ( firstDay ) . length < 3
139
141
const startIndex = firstDayIsDayZero ? 0 : 1
140
142
143
+ const { getTimeMarker } = useCurrentTimeMarker ( )
144
+
141
145
return (
142
146
< >
143
147
< div className = "flex justify-between gap-1 max-lg:flex-col" >
144
148
< BookmarkOnSched year = { year } />
145
- < ResetFiltersButton
146
- filters = { filtersState }
147
- onReset = { ( ) =>
148
- setFiltersState (
149
- FilterStates . initial (
150
- Object . keys ( filterFields ) as ( keyof ScheduleSession ) [ ] ,
151
- ) ,
152
- )
153
- }
154
- className = "max-lg:mb-4 max-lg:w-fit max-lg:self-end"
155
- />
149
+ < div className = "flex gap-2" >
150
+ < Button
151
+ href = "#current-time-marker"
152
+ variant = "tertiary"
153
+ className = "hidden h-fit items-center gap-x-2 bg-neu-100 !p-2 text-neu-700 transition-opacity hover:bg-neu-200/80 hover:text-neu-900 disabled:opacity-0 [body:has(#current-time-marker)_&]:flex"
154
+ >
155
+ Scroll to current block
156
+ </ Button >
157
+ < ResetFiltersButton
158
+ filters = { filtersState }
159
+ onReset = { ( ) =>
160
+ setFiltersState (
161
+ FilterStates . initial (
162
+ Object . keys ( filterFields ) as ( keyof ScheduleSession ) [ ] ,
163
+ ) ,
164
+ )
165
+ }
166
+ className = "max-lg:mb-4 max-lg:w-fit max-lg:self-end"
167
+ />
168
+ </ div >
156
169
</ div >
157
170
{ showFilter && (
158
171
< Filters
@@ -229,6 +242,16 @@ export function ScheduleList({
229
242
blockEnd . getTime ( ) ,
230
243
)
231
244
245
+ let timeMarker = getTimeMarker ( sessionDate , blockEnd )
246
+ // if end times differ and blockEnd is far from start, we treat this as a long event, like "solutions showcase"
247
+ if (
248
+ endTimesDiffer &&
249
+ blockEnd . getTime ( ) - new Date ( sessionDate ) . getTime ( ) >
250
+ 1000 * 60 * 60 * 2
251
+ ) {
252
+ timeMarker = null
253
+ }
254
+
232
255
return (
233
256
< div
234
257
key = { `concurrent sessions on ${ sessionDate } ` }
@@ -256,6 +279,18 @@ export function ScheduleList({
256
279
) ) }
257
280
</ div >
258
281
</ div >
282
+ { timeMarker && (
283
+ < div
284
+ id = "current-time-marker"
285
+ className = "typography-body-xs pointer-events-none absolute -right-1 z-10 -translate-y-full font-mono tabular-nums text-pri-base before:absolute before:inset-x-0 before:bottom-0 before:border-b before:border-pri-base before:opacity-80 after:absolute after:bottom-0 after:left-[-100vw] after:w-screen after:border-t after:border-pri-base after:opacity-20 dark:text-pri-light dark:before:border-pri-light dark:after:border-pri-light max-xl:bg-neu-0 xl:translate-x-full"
286
+ style = { {
287
+ top : `${ timeMarker . positionPercentage } %` ,
288
+ } }
289
+ >
290
+ < span className = "max-2xl:hidden" > now: </ span >
291
+ { timeMarker . currentTime }
292
+ </ div >
293
+ ) }
259
294
{ hasDashedBorder && (
260
295
< svg
261
296
className = "absolute -bottom-px left-0 h-px w-full text-neu-50"
0 commit comments