Skip to content

Commit 27cd41c

Browse files
feat: improve compact agenda display
1 parent 34c0b23 commit 27cd41c

3 files changed

Lines changed: 280 additions & 119 deletions

File tree

.speakup.jsonc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"providers": {
3+
"gemini": {
4+
"title_voice": "Nova"
5+
},
6+
"elevenlabs": {
7+
"title_voice": "n1PvBOwxb8X6m7tahp2h"
8+
}
9+
}
10+
}

src/components/compact-agenda.tsx

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/** @jsxRuntime classic */
22
/** @jsxImportSource theme-ui */
33
import { format } from "date-fns";
4-
import { useEffect, useMemo, useState } from "react";
4+
import { useEffect, useMemo, useRef, useState } from "react";
55
import { Box, Flex, Text, jsx } from "theme-ui";
66

77
import type { Event } from "~/data/schedule";
@@ -17,6 +17,8 @@ type ReferenceTime = {
1717
time: Date | null;
1818
};
1919

20+
export type ColorMode = "light" | "dark";
21+
2022
const 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

Comments
 (0)