From 27f67c945708cc60d5dfba9592c7c21f79787f3a Mon Sep 17 00:00:00 2001 From: Piotr Monwid-Olechnowicz Date: Fri, 27 Jun 2025 17:09:23 +0200 Subject: [PATCH 1/8] Sync speakers --- scripts/sync-sched/schedule-2025.json | 2 +- scripts/sync-sched/speakers.json | 82 ++++++++++++++++----------- 2 files changed, 49 insertions(+), 35 deletions(-) diff --git a/scripts/sync-sched/schedule-2025.json b/scripts/sync-sched/schedule-2025.json index 7f8155a483..07eff7b0f2 100644 --- a/scripts/sync-sched/schedule-2025.json +++ b/scripts/sync-sched/schedule-2025.json @@ -894,7 +894,7 @@ "event_end": "2025-09-08 14:55", "event_type": "GraphQL in Production", "description": "In Booking.com we are heavily using Federated GraphQL approach, more than 150 backend sub-graph services are integrated from different domains of the company such as accommodations, partner, flights, cars, trips, and fintech.\n \n \nOur federated GraphQL layer hosts daily 11b+ incoming requests, Federation in the back distributes 14b+ requests to the sub-graphs per day. We have a diverse set of clients such as Booking traveller, partner native apps/web clients, 140+ SSR (Server Side Rendering) services for Web/Mobile rendering, and AI chatbots. This level of adoption brings unique challenges in terms of security and traffic management. In Booking.com we have a large attack surface since our GraphQL schema is huge, to be specific we have ~7k types with 27k+ fields. In this session, we will share our schema driven approaches to mitigate risks due to authN/Z leaks, DDoS attacks or exposure of sensitive PII/PCI data. These methodologies are designed with a high degree of generality, ensuring their applicability and scalability across every other Federated GraphQL system.", - "goers": "0", + "goers": "1", "seats": "0", "invite_only": "N", "venue": "Studio", diff --git a/scripts/sync-sched/speakers.json b/scripts/sync-sched/speakers.json index 7a2d0026a9..de86ebfe74 100644 --- a/scripts/sync-sched/speakers.json +++ b/scripts/sync-sched/speakers.json @@ -739,7 +739,7 @@ "_years": [ 2025 ], - "~syncedDetailsAt": 1750181396120 + "~syncedDetailsAt": 1751036945383 }, { "username": "christian.ernst", @@ -843,7 +843,7 @@ "_years": [ 2025 ], - "~syncedDetailsAt": 1750181396119 + "~syncedDetailsAt": 1751036922058 }, { "username": "danielle.man", @@ -905,11 +905,20 @@ "location": "", "url": "", "avatar": "//avatars.sched.co/3/1e/23098735/avatar.jpg.320x320px.jpg?7a3", - "socialurls": [], + "socialurls": [ + { + "service": "Twitter", + "url": "https://x.com/dotansimha" + }, + { + "service": "LinkedIn", + "url": "https://www.linkedin.com/in/dotan-simha-36767b29/" + } + ], "_years": [ 2025 ], - "~syncedDetailsAt": 1750181396119 + "~syncedDetailsAt": 1751036922058 }, { "username": "dotansimha", @@ -944,7 +953,7 @@ "_years": [ 2025 ], - "~syncedDetailsAt": 1750181396119 + "~syncedDetailsAt": 1751036922058 }, { "username": "eitan15", @@ -1071,7 +1080,7 @@ "_years": [ 2025 ], - "~syncedDetailsAt": 1750181396119 + "~syncedDetailsAt": 1751036922058 }, { "username": "fionabronwen", @@ -1106,7 +1115,7 @@ "_years": [ 2025 ], - "~syncedDetailsAt": 1750181396119 + "~syncedDetailsAt": 1751036922058 }, { "username": "gabrielschulhof", @@ -1228,7 +1237,7 @@ "_years": [ 2025 ], - "~syncedDetailsAt": 1750181396119 + "~syncedDetailsAt": 1751036922058 }, { "username": "hello2358", @@ -1308,7 +1317,7 @@ "_years": [ 2025 ], - "~syncedDetailsAt": 1750181396119 + "~syncedDetailsAt": 1751036922058 }, { "username": "jamie855", @@ -1362,7 +1371,7 @@ "_years": [ 2025 ], - "~syncedDetailsAt": 1750181396119 + "~syncedDetailsAt": 1751036922058 }, { "username": "jared_cheney.7rad60v", @@ -1439,11 +1448,16 @@ "location": "", "url": "", "avatar": "//avatars.sched.co/3/b5/23098759/avatar.jpg.320x320px.jpg?613", - "socialurls": [], + "socialurls": [ + { + "service": "LinkedIn", + "url": "https://linkedin.com/in/jeffdolle" + } + ], "_years": [ 2025 ], - "~syncedDetailsAt": 1750181396119 + "~syncedDetailsAt": 1751036922058 }, { "username": "jens63", @@ -1482,7 +1496,7 @@ "_years": [ 2025 ], - "~syncedDetailsAt": 1750181396119 + "~syncedDetailsAt": 1751036922058 }, { "username": "jesperrasmussen", @@ -1541,7 +1555,7 @@ "_years": [ 2025 ], - "~syncedDetailsAt": 1750181396119 + "~syncedDetailsAt": 1751036941512 }, { "username": "jordaneldredge", @@ -1580,7 +1594,7 @@ "_years": [ 2025 ], - "~syncedDetailsAt": 1750181396119 + "~syncedDetailsAt": 1751036941512 }, { "username": "juancarlosjr97", @@ -1604,7 +1618,7 @@ "_years": [ 2025 ], - "~syncedDetailsAt": 1750181396120 + "~syncedDetailsAt": 1751036945383 }, { "username": "kamilkisiela", @@ -1634,7 +1648,7 @@ 2024, 2025 ], - "~syncedDetailsAt": 1750181396119 + "~syncedDetailsAt": 1751036941512 }, { "username": "keerthan.ekbote", @@ -1781,7 +1795,7 @@ "about": "Laurin Quast is a developer that started exploring GraphQL, by leading API development at a start-up. Realizing that there are still many unsolved problems and challenges within the space, he started contributing to famous JavaScript libraries, such as GraphQL Code Generator and Tools. Diving deeper, the transition into becoming a full-time open-source developer at The Guild was inevitable. Currently, he is working on Hive helping teams scale GraphQL across teams and organizations.", "location": "", "url": "https://the-guild.dev/", - "avatar": "//avatars.sched.co/2/a6/18743819/avatar.jpg.320x320px.jpg?705", + "avatar": "//avatars.sched.co/2/a6/18743819/avatar.jpg.320x320px.jpg?ebc", "socialurls": [ { "service": "Twitter", @@ -1797,7 +1811,7 @@ 2024, 2025 ], - "~syncedDetailsAt": 1750181396119 + "~syncedDetailsAt": 1751036941512 }, { "username": "ldebruijn", @@ -1833,7 +1847,7 @@ 2024, 2025 ], - "~syncedDetailsAt": 1750181396119 + "~syncedDetailsAt": 1751036941512 }, { "username": "lee_byron.25krdom6", @@ -1887,7 +1901,7 @@ "_years": [ 2025 ], - "~syncedDetailsAt": 1750181396120 + "~syncedDetailsAt": 1751036941512 }, { "username": "lyonwj1", @@ -1936,7 +1950,7 @@ 2024, 2025 ], - "~syncedDetailsAt": 1750181396119 + "~syncedDetailsAt": 1751036941512 }, { "username": "mail1232", @@ -1951,7 +1965,7 @@ "_years": [ 2025 ], - "~syncedDetailsAt": 1750181396120 + "~syncedDetailsAt": 1751036941512 }, { "username": "mansi.mittal", @@ -2026,7 +2040,7 @@ 2024, 2025 ], - "~syncedDetailsAt": 1750181396119 + "~syncedDetailsAt": 1751036941512 }, { "username": "martinbonnin42", @@ -2156,7 +2170,7 @@ 2023, 2025 ], - "~syncedDetailsAt": 1750181396120 + "~syncedDetailsAt": 1751036945383 }, { "username": "mgiroux7", @@ -2206,7 +2220,7 @@ 2024, 2025 ], - "~syncedDetailsAt": 1750181396120 + "~syncedDetailsAt": 1751036945383 }, { "username": "michael.astle", @@ -2291,7 +2305,7 @@ 2024, 2025 ], - "~syncedDetailsAt": 1750181396120 + "~syncedDetailsAt": 1751036945383 }, { "username": "patrick.arminio", @@ -2505,7 +2519,7 @@ 2024, 2025 ], - "~syncedDetailsAt": 1750181396120 + "~syncedDetailsAt": 1751036945383 }, { "username": "robrichard87", @@ -2521,7 +2535,7 @@ 2024, 2025 ], - "~syncedDetailsAt": 1750181915102 + "~syncedDetailsAt": 1751036945383 }, { "username": "ruben.cagnie", @@ -2552,7 +2566,7 @@ 2024, 2025 ], - "~syncedDetailsAt": 1750181953774 + "~syncedDetailsAt": 1751036945383 }, { "username": "saihaj", @@ -2614,7 +2628,7 @@ "position": "Senior Software Engineer 2", "name": "Sanver Tarmur", "about": "Sanver is a Senior Software Engineer II at Booking.com with 15 years of industry experience. In recent years, he has been leading the Federated GraphQL transformation at Booking.com, focusing on scaling, enhancing the security of the GraphQL platform, and improving the developer experience for internal Graph users.", - "location": "", + "location": "Amsterdam", "url": "", "avatar": "//avatars.sched.co/0/9e/23098798/avatar.jpg.320x320px.jpg?318", "socialurls": [], @@ -2856,7 +2870,7 @@ 2024, 2025 ], - "~syncedDetailsAt": 1750181966765 + "~syncedDetailsAt": 1751036945383 }, { "username": "stefan239", @@ -3142,7 +3156,7 @@ 2024, 2025 ], - "~syncedDetailsAt": 1750181973559 + "~syncedDetailsAt": 1751036945383 }, { "username": "vincent.desmares", @@ -3192,7 +3206,7 @@ "_years": [ 2025 ], - "~syncedDetailsAt": 1750181396119 + "~syncedDetailsAt": 1751036941512 }, { "username": "watson17", From 5225c4e433d51f9cc0cca8be5f46168e200ec261 Mon Sep 17 00:00:00 2001 From: Piotr Monwid-Olechnowicz Date: Fri, 27 Jun 2025 17:17:44 +0200 Subject: [PATCH 2/8] Display time range in session details --- src/app/conf/2025/schedule/[id]/page.tsx | 8 +++++- .../_components/format-block-time.tsx | 13 +++++++++ .../schedule/_components/schedule-list.tsx | 28 +++++++++---------- 3 files changed, 33 insertions(+), 16 deletions(-) create mode 100644 src/app/conf/2025/schedule/_components/format-block-time.tsx diff --git a/src/app/conf/2025/schedule/[id]/page.tsx b/src/app/conf/2025/schedule/[id]/page.tsx index a7a2a928c6..c64649d3c6 100644 --- a/src/app/conf/2025/schedule/[id]/page.tsx +++ b/src/app/conf/2025/schedule/[id]/page.tsx @@ -22,6 +22,7 @@ import { CtaCardSection } from "../../components/cta-card-section" import { Button } from "@/app/conf/_design-system/button" import { SessionTags } from "../../components/session-tags" import { formatDescription } from "./format-description" +import { formatBlockTime } from "../_components/format-block-time" type SessionProps = { params: { id: string } } @@ -194,10 +195,15 @@ function SessionHeader({
diff --git a/src/app/conf/2025/schedule/_components/format-block-time.tsx b/src/app/conf/2025/schedule/_components/format-block-time.tsx new file mode 100644 index 0000000000..709ebd10b6 --- /dev/null +++ b/src/app/conf/2025/schedule/_components/format-block-time.tsx @@ -0,0 +1,13 @@ +import { parseISO } from "date-fns" + +const timeFormat = new Intl.DateTimeFormat(undefined, { + hour: "2-digit", + minute: "2-digit", +}) +export const formatBlockTime = (start: string, end?: Date) => { + const startDate = parseISO(start) + if (end) { + return timeFormat.formatRange(startDate, end) + } + return timeFormat.format(startDate) +} diff --git a/src/app/conf/2025/schedule/_components/schedule-list.tsx b/src/app/conf/2025/schedule/_components/schedule-list.tsx index e2fedb469b..bc4997546b 100644 --- a/src/app/conf/2025/schedule/_components/schedule-list.tsx +++ b/src/app/conf/2025/schedule/_components/schedule-list.tsx @@ -16,6 +16,7 @@ import { FilterStates, ResetFiltersButton, } from "./filters" +import { formatBlockTime } from "./format-block-time" export interface FiltersConfig extends Partial< @@ -101,19 +102,6 @@ function getSessionsByDay( } } -const timeFormat = new Intl.DateTimeFormat(undefined, { - hour: "2-digit", - minute: "2-digit", -}) -const formatBlockTime = (start: string, end?: string) => { - const startDate = parseISO(start) - if (end) { - const endDate = parseISO(end) - return timeFormat.formatRange(startDate, endDate) - } - return timeFormat.format(startDate) -} - export interface ScheduleListProps { showFilter?: boolean scheduleData: ScheduleSession[] @@ -205,8 +193,18 @@ export function ScheduleList({ {Object.entries(concurrentSessionsGroup).map( ([sessionDate, sessions], i, blocks) => { - const blockEnd = sessions[0]?.event_end - const nextBlockStart = blocks[i + 1]?.[0] + const blockEnd = new Date( + Math.max( + ...sessions.map(session => + new Date(session.event_end).getTime(), + ), + ), + ) + + const nextBlock = blocks[i + 1] + const nextBlockStart = nextBlock?.[0] + ? new Date(nextBlock[0]) + : undefined const isBreak = sessions[0]?.event_type From df1aa0729a3988ba0a38d0c671b37397cde62077 Mon Sep 17 00:00:00 2001 From: Piotr Monwid-Olechnowicz Date: Fri, 27 Jun 2025 17:29:35 +0200 Subject: [PATCH 3/8] Add ics links to Schedule cards --- .../_components/schedule-session-card.tsx | 52 +++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/src/app/conf/2025/schedule/_components/schedule-session-card.tsx b/src/app/conf/2025/schedule/_components/schedule-session-card.tsx index 7a77fac0e7..cc6f40e1f8 100644 --- a/src/app/conf/2025/schedule/_components/schedule-session-card.tsx +++ b/src/app/conf/2025/schedule/_components/schedule-session-card.tsx @@ -1,4 +1,6 @@ import React from "react" +import { ics } from "calendar-link" +import { clsx } from "clsx" import { SchedSpeaker, ScheduleSession } from "@/app/conf/_api/sched-types" import { Anchor } from "@/app/conf/_design-system/anchor" @@ -7,6 +9,7 @@ import { Tag } from "@/app/conf/_design-system/tag" import { PinIcon } from "@/app/conf/_design-system/pixelarticons/pin-icon" import { getEventTitle } from "../../utils" +import { CalendarIcon } from "@/app/conf/_design-system/pixelarticons/calendar-icon" function isString(x: unknown): x is string { return Object.prototype.toString.call(x) === "[object String]" @@ -83,9 +86,16 @@ export function ScheduleSessionCard({ ))} )} - - - {session.venue} + + + + {session.venue} + + @@ -93,3 +103,39 @@ export function ScheduleSessionCard({
) } + +function AddToCalendarLink({ + eventTitle, + session, + speakers, + className, +}: { + eventTitle: string + session: ScheduleSession + speakers: SchedSpeaker[] + className?: string +}) { + return ( + s.name), + })} + > + + Add to calendar + + ) +} From f1c8b74621e55151632acfa2976441b7a85ca6ce Mon Sep 17 00:00:00 2001 From: Piotr Monwid-Olechnowicz Date: Fri, 27 Jun 2025 17:45:03 +0200 Subject: [PATCH 4/8] Display clock icon and duration for lightning talks --- .../schedule/_components/schedule-list.tsx | 5 +++- .../_components/schedule-session-card.tsx | 30 ++++++++++++++++++- .../_design-system/pixelarticons/clock.svg | 3 +- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/app/conf/2025/schedule/_components/schedule-list.tsx b/src/app/conf/2025/schedule/_components/schedule-list.tsx index bc4997546b..d1d497915e 100644 --- a/src/app/conf/2025/schedule/_components/schedule-list.tsx +++ b/src/app/conf/2025/schedule/_components/schedule-list.tsx @@ -214,7 +214,9 @@ export function ScheduleList({ ?.toLowerCase() .includes("break") const hasDashedBorder = - blockEnd && blockEnd === nextBlockStart && !isBreak + blockEnd && + blockEnd.getTime() === nextBlockStart?.getTime() && + !isBreak return (
))}
diff --git a/src/app/conf/2025/schedule/_components/schedule-session-card.tsx b/src/app/conf/2025/schedule/_components/schedule-session-card.tsx index cc6f40e1f8..6fbe4598be 100644 --- a/src/app/conf/2025/schedule/_components/schedule-session-card.tsx +++ b/src/app/conf/2025/schedule/_components/schedule-session-card.tsx @@ -7,6 +7,7 @@ import { Anchor } from "@/app/conf/_design-system/anchor" import { Tag } from "@/app/conf/_design-system/tag" import { PinIcon } from "@/app/conf/_design-system/pixelarticons/pin-icon" +import ClockIcon from "@/app/conf/_design-system/pixelarticons/clock.svg?svgr" import { getEventTitle } from "../../utils" import { CalendarIcon } from "@/app/conf/_design-system/pixelarticons/calendar-icon" @@ -19,10 +20,12 @@ export function ScheduleSessionCard({ session, year, eventsColors, + blockEnd, }: { session: ScheduleSession year: `202${number}` eventsColors: Record + blockEnd: Date }) { let eventType = session.event_type @@ -43,6 +46,19 @@ export function ScheduleSessionCard({ const eventColor = eventsColors[session.event_type] + let blockTimeFraction = 1 + if (blockEnd.getTime() !== new Date(session.event_end).getTime()) { + blockTimeFraction = + (new Date(session.event_end).getTime() - + new Date(session.event_start).getTime()) / + (blockEnd.getTime() - new Date(session.event_start).getTime()) + + console.log({ + eventTitle, + blockTimeFraction, + }) + } + return session.event_type === "Breaks" ? (
{eventTitle} @@ -86,15 +102,27 @@ export function ScheduleSessionCard({ ))} )} - + {session.venue} + {blockTimeFraction < 1 && ( + + + {Math.round( + (new Date(session.event_end).getTime() - + new Date(session.event_start).getTime()) / + (1000 * 60), + )}{" "} + min + + )} diff --git a/src/app/conf/_design-system/pixelarticons/clock.svg b/src/app/conf/_design-system/pixelarticons/clock.svg index 9f0e6b1f9a..bfc82287a8 100644 --- a/src/app/conf/_design-system/pixelarticons/clock.svg +++ b/src/app/conf/_design-system/pixelarticons/clock.svg @@ -3,10 +3,9 @@ width="16" height="16" viewBox="0 0 16 16" - fill="none" + fill="currentColor" > From 0e636ea6eace31d2df165c5a73b8b1c70b4f6150 Mon Sep 17 00:00:00 2001 From: Piotr Monwid-Olechnowicz Date: Fri, 27 Jun 2025 18:15:41 +0200 Subject: [PATCH 5/8] Show a gradient in schedule cards if the talk is shorter than block --- .../_components/schedule-session-card.tsx | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/app/conf/2025/schedule/_components/schedule-session-card.tsx b/src/app/conf/2025/schedule/_components/schedule-session-card.tsx index 6fbe4598be..d78dc9f2e8 100644 --- a/src/app/conf/2025/schedule/_components/schedule-session-card.tsx +++ b/src/app/conf/2025/schedule/_components/schedule-session-card.tsx @@ -64,7 +64,23 @@ export function ScheduleSessionCard({ {eventTitle}
) : ( -
+
a:hover)]:[--bg:hsl(var(--color-neu-0)/.9)] dark:[&:has(>a:hover)]:[--bg:hsl(var(--color-neu-0)/.8)]", + "group relative size-full p-4 font-normal no-underline ring-neu-400 focus-visible:z-[1] dark:ring-neu-100 [&:has(>a:hover)]:ring-1", + blockTimeFraction < 1 && "[--bg:hsl(var(--color-neu-0)/50)]", + )} + style={ + { + "--time": `${blockTimeFraction * 100}%`, + background: + blockTimeFraction < 1 + ? `linear-gradient(to bottom, var(--bg), var(--bg) var(--time), hsl(var(--color-neu-0)/.8) var(--time), hsl(var(--color-neu-0)/.8))` + : "var(--bg)", + } as {} + } + > Date: Fri, 27 Jun 2025 18:26:03 +0200 Subject: [PATCH 6/8] skip AM before PM --- src/app/conf/2025/schedule/_components/format-block-time.tsx | 2 +- src/app/conf/2025/schedule/_components/schedule-list.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/conf/2025/schedule/_components/format-block-time.tsx b/src/app/conf/2025/schedule/_components/format-block-time.tsx index 709ebd10b6..135278e43e 100644 --- a/src/app/conf/2025/schedule/_components/format-block-time.tsx +++ b/src/app/conf/2025/schedule/_components/format-block-time.tsx @@ -7,7 +7,7 @@ const timeFormat = new Intl.DateTimeFormat(undefined, { export const formatBlockTime = (start: string, end?: Date) => { const startDate = parseISO(start) if (end) { - return timeFormat.formatRange(startDate, end) + return timeFormat.formatRange(startDate, end).replace("AM –", "–") } return timeFormat.format(startDate) } diff --git a/src/app/conf/2025/schedule/_components/schedule-list.tsx b/src/app/conf/2025/schedule/_components/schedule-list.tsx index d1d497915e..24aacce712 100644 --- a/src/app/conf/2025/schedule/_components/schedule-list.tsx +++ b/src/app/conf/2025/schedule/_components/schedule-list.tsx @@ -225,7 +225,7 @@ export function ScheduleList({ >
- + {formatBlockTime(sessionDate, blockEnd)}
From 49fa4e500b66f44829f5ccaac99db0b4d000ed86 Mon Sep 17 00:00:00 2001 From: Piotr Monwid-Olechnowicz Date: Fri, 27 Jun 2025 19:05:57 +0200 Subject: [PATCH 7/8] Add more options to [Add to calendar] --- .../_components/schedule-session-card.tsx | 98 ++++++++++++++----- .../2025/speakers/[id]/long-session-card.tsx | 84 ++++++++++++---- src/globals.css | 3 +- 3 files changed, 141 insertions(+), 44 deletions(-) diff --git a/src/app/conf/2025/schedule/_components/schedule-session-card.tsx b/src/app/conf/2025/schedule/_components/schedule-session-card.tsx index d78dc9f2e8..451a49bcb3 100644 --- a/src/app/conf/2025/schedule/_components/schedule-session-card.tsx +++ b/src/app/conf/2025/schedule/_components/schedule-session-card.tsx @@ -1,6 +1,13 @@ -import React from "react" -import { ics } from "calendar-link" +import React, { Fragment } from "react" +import { ics, google, outlook, CalendarEvent } from "calendar-link" import { clsx } from "clsx" +import { + Menu, + MenuButton, + MenuItem, + MenuItems, + Transition, +} from "@headlessui/react" import { SchedSpeaker, ScheduleSession } from "@/app/conf/_api/sched-types" import { Anchor } from "@/app/conf/_design-system/anchor" @@ -85,7 +92,9 @@ export function ScheduleSessionCard({ id={`session-${session.id}`} href={`/conf/${year}/schedule/${session.id}?name=${session.name}`} className="absolute inset-0 z-[1] ring-inset ring-neu-400 hover:ring-1 dark:ring-neu-100" - aria-label={`Read more about "${eventTitle}" by ${speakers.map(s => s.name).join(", ")}`} + aria-label={`Read more about "${eventTitle}" by ${speakers + .map(s => s.name) + .join(", ")}`} /> {eventType && ( @@ -159,27 +168,70 @@ function AddToCalendarLink({ speakers: SchedSpeaker[] className?: string }) { + const calendarEvent: CalendarEvent = { + title: eventTitle, + start: session.event_start, + end: session.event_end, + description: session.description, + location: session.venue, + organizer: { + name: `GraphQLConf ${new Date().getFullYear()}`, + email: "graphql_events@linuxfoundation.org", + }, + guests: speakers.map(s => s.name), + } + + const calendars = { + ICS: ics, + Google: google, + Outlook: outlook, + } + return ( - s.name), - })} + - - Add to calendar - +
+ + + Add to calendar + +
+ + +
+ {Object.entries(calendars).map(([name, calendar]) => ( + + + {name} + + + ))} +
+
+
+
) } diff --git a/src/app/conf/2025/speakers/[id]/long-session-card.tsx b/src/app/conf/2025/speakers/[id]/long-session-card.tsx index 32ba47f9fd..fd6963afa1 100644 --- a/src/app/conf/2025/speakers/[id]/long-session-card.tsx +++ b/src/app/conf/2025/speakers/[id]/long-session-card.tsx @@ -1,5 +1,5 @@ import { clsx } from "clsx" -import { ics } from "calendar-link" +import { CalendarEvent, google, ics, outlook } from "calendar-link" import { SchedSpeaker, ScheduleSession } from "@/app/conf/2023/types" import { Button } from "@/app/conf/_design-system/button" @@ -11,8 +11,10 @@ import PlusIcon from "@/app/conf/_design-system/pixelarticons/plus.svg?svgr" import PlayIcon from "@/app/conf/_design-system/pixelarticons/play.svg?svgr" import { findVideo } from "../../schedule/[id]/session-video" import { getEventTitle } from "../../utils" -import React from "react" +import React, { Fragment } from "react" import { SessionTags } from "../../components/session-tags" +import { Menu, MenuItem, MenuItems, Transition } from "@headlessui/react" +import { MenuButton } from "@headlessui/react" export interface LongSessionCardProps extends React.HTMLAttributes { @@ -159,29 +161,71 @@ function AddToCalendarLink({ eventTitle, session, speakers, + className, }: { eventTitle: string session: ScheduleSession speakers: SchedSpeaker[] + className?: string }) { + const calendarEvent: CalendarEvent = { + title: eventTitle, + start: session.event_start, + end: session.event_end, + description: session.description, + location: session.venue, + organizer: { + name: `GraphQLConf ${new Date().getFullYear()}`, + email: "graphql_events@linuxfoundation.org", + }, + guests: speakers.map(s => s.name), + } + + const calendars = { + ICS: ics, + Google: google, + Outlook: outlook, + } + return ( - s.name), - })} - > - - Add to calendar - + + + + Add to calendar + + + +
+ {Object.entries(calendars).map(([name, calendar]) => ( + + + {name} + + + ))} +
+
+
+
) } diff --git a/src/globals.css b/src/globals.css index 8d33d859df..ac04ce6d8d 100644 --- a/src/globals.css +++ b/src/globals.css @@ -533,6 +533,7 @@ div[id^="headlessui-menu-items"] { } /* without this Headless UI breaks sticky navbar */ -html:has([role="listbox"][data-open]) { +html:has([role="listbox"][data-open]), +html:has([role="menu"][data-open]) { overflow: visible !important; } From cc561a074c3f0e2c60903f87eb8c000a07ba25ce Mon Sep 17 00:00:00 2001 From: Piotr Monwid-Olechnowicz Date: Fri, 27 Jun 2025 21:28:07 +0200 Subject: [PATCH 8/8] Fix colors in dark mode --- .../2025/schedule/_components/schedule-session-card.tsx | 9 ++------- src/app/conf/2025/speakers/[id]/long-session-card.tsx | 4 ++-- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/app/conf/2025/schedule/_components/schedule-session-card.tsx b/src/app/conf/2025/schedule/_components/schedule-session-card.tsx index 451a49bcb3..4416196a73 100644 --- a/src/app/conf/2025/schedule/_components/schedule-session-card.tsx +++ b/src/app/conf/2025/schedule/_components/schedule-session-card.tsx @@ -59,11 +59,6 @@ export function ScheduleSessionCard({ (new Date(session.event_end).getTime() - new Date(session.event_start).getTime()) / (blockEnd.getTime() - new Date(session.event_start).getTime()) - - console.log({ - eventTitle, - blockTimeFraction, - }) } return session.event_type === "Breaks" ? ( @@ -214,7 +209,7 @@ function AddToCalendarLink({ >
{Object.entries(calendars).map(([name, calendar]) => ( @@ -223,7 +218,7 @@ function AddToCalendarLink({ href={calendar(calendarEvent)} target="_blank" rel="noopener noreferrer" - className="group typography-body-xs flex w-full items-center px-2 py-1 text-neu-800 [&[data-active]]:bg-neu-100 [&[data-active]]:text-neu-900" + className="group typography-body-xs flex w-full items-center px-2 py-1 text-neu-800 [&[data-active]]:bg-neu-100 [&[data-active]]:text-neu-900 dark:[&[data-active]]:bg-neu-50" > {name} diff --git a/src/app/conf/2025/speakers/[id]/long-session-card.tsx b/src/app/conf/2025/speakers/[id]/long-session-card.tsx index fd6963afa1..6b046b9da2 100644 --- a/src/app/conf/2025/speakers/[id]/long-session-card.tsx +++ b/src/app/conf/2025/speakers/[id]/long-session-card.tsx @@ -208,7 +208,7 @@ function AddToCalendarLink({ >
{Object.entries(calendars).map(([name, calendar]) => ( @@ -217,7 +217,7 @@ function AddToCalendarLink({ href={calendar(calendarEvent)} target="_blank" rel="noopener noreferrer" - className="group typography-body-sm flex w-full items-center p-3 text-neu-800 [&[data-active]]:bg-neu-100 [&[data-active]]:text-neu-900" + className="group typography-body-sm flex w-full items-center p-3 text-neu-800 [&[data-active]]:bg-neu-100 [&[data-active]]:text-neu-900 dark:[&[data-active]]:bg-neu-50" > {name}