@@ -8,15 +8,21 @@ import { metadata as layoutMetadata } from "@/app/conf/2023/layout"
8
8
import { speakers , schedule } from "../../_data"
9
9
import { ScheduleSession } from "../../../2023/types"
10
10
11
- import { SessionVideo } from "./session-video"
11
+ import ExternalLinkIcon from "@/app/conf/2025/pixelarticons/external-link.svg?svgr"
12
+
13
+ import { findVideo , SessionVideo } from "./session-video"
12
14
import { NavbarPlaceholder } from "../../components/navbar"
13
15
import { BackLink } from "../_components/back-link"
14
16
import { Tag } from "@/app/conf/_design-system/tag"
15
- import { eventsColors , getEventTitle } from "../../utils"
17
+ import { eventsColors , getEventTitle , HERO_MARQUEE_ITEMS } from "../../utils"
16
18
import { PinIcon } from "../../pixelarticons/pin-icon"
17
19
import { CalendarIcon } from "../../pixelarticons/calendar-icon"
18
20
import { SpeakerCard } from "../../components/speaker-card"
19
21
import { Anchor } from "@/app/conf/_design-system/anchor"
22
+ import { MarqueeRows } from "../../components/marquee-rows"
23
+ import { GET_TICKETS_LINK } from "../../links"
24
+ import { CtaCardSection } from "../../components/cta-card-section"
25
+ import { Button } from "@/app/conf/_design-system/button"
20
26
21
27
type SessionProps = { params : { id : string } }
22
28
@@ -60,48 +66,87 @@ export default function SessionPage({ params }: SessionProps) {
60
66
event . speakers ! . map ( s => s . name ) ,
61
67
)
62
68
69
+ const video = findVideo ( event , eventTitle )
70
+
63
71
return (
64
- < main className = "gql-all-anchors-focusable" >
65
- < NavbarPlaceholder className = "top-0 bg-neu-0 before:bg-white/40 dark:bg-neu-0 dark:before:bg-blk/30" />
66
- < div className = "gql-conf-container gql-conf-navbar-strip text-neu-900 before:bg-white/40 before:dark:bg-blk/30" >
67
- < div className = "gql-conf-section" >
68
- < div className = "mx-auto max-w-[1088px] py-10" >
69
- < section className = "mx-auto min-h-[80vh] flex-col justify-center px-2 sm:px-0 lg:justify-between" >
70
- < SessionHeader
71
- event = { event }
72
- eventTitle = { eventTitle }
73
- year = "2025"
74
- />
75
- < SessionVideo event = { event } eventTitle = { eventTitle } />
76
-
77
- < div className = "mt-8 flex gap-4 max-lg:flex-col lg:mt-16 lg:gap-8" >
78
- < h3 className = "typography-h2 min-w-[320px]" >
79
- Session description
72
+ < >
73
+ < NavbarPlaceholder className = "top-0 bg-neu-50 before:bg-white/40 dark:bg-neu-0 dark:before:bg-blk/30" />
74
+
75
+ < main className = "gql-all-anchors-focusable gql-conf-navbar-strip text-neu-900 before:bg-white/40 before:dark:bg-blk/30" >
76
+ < div className = "gql-conf-container" >
77
+ < div className = "gql-conf-section !pt-0" >
78
+ < div className = "border-x border-neu-200 pt-8 dark:border-neu-100 2xl:pt-16" >
79
+ < section className = "mx-auto min-h-[80vh] flex-col justify-center px-2 sm:px-0 lg:justify-between" >
80
+ < SessionHeader
81
+ event = { event }
82
+ eventTitle = { eventTitle }
83
+ year = "2025"
84
+ className = { clsx (
85
+ "px-2 sm:px-3" ,
86
+ video && "mx-auto max-w-[1088px]" ,
87
+ ) }
88
+ />
89
+ { video ? (
90
+ < SessionVideo video = { video } className = "mt-6" />
91
+ ) : (
92
+ < Hr className = "mt-10 2xl:mt-16" />
93
+ ) }
94
+
95
+ < div className = "mt-8 flex gap-4 px-2 max-lg:flex-col sm:px-3 lg:mt-16 lg:gap-8 xl:pb-16" >
96
+ < h3 className = "typography-h2 min-w-[320px]" >
97
+ Session description
98
+ </ h3 >
99
+ < p className = "typography-body-lg" > { event . description } </ p >
100
+ </ div >
101
+
102
+ < Hr />
103
+
104
+ < h3 className = "typography-h2 my-8 max-w-[408px] px-2 sm:px-3 lg:my-16" >
105
+ Session speakers
80
106
</ h3 >
81
- < p className = "typography-body-lg" > { event . description } </ p >
82
- </ div >
83
-
84
- < h3 className = "typography-h2 my-8 max-w-[408px] lg:mb-16" >
85
- Session speakers
86
- </ h3 >
87
- < SessionSpeakers event = { event } />
88
-
89
- < div className = "py-8" >
90
- { event . files ?. map ( ( { path } ) => (
91
- < div key = { path } >
92
- < a href = { path } target = "_blank" rel = "noreferrer" >
93
- View Full PDF{ " " }
94
- < span className = "font-sans text-2xl font-light" > ↗</ span >
95
- </ a >
96
- < iframe src = { path } className = "aspect-video size-full" />
97
- </ div >
98
- ) ) }
99
- </ div >
100
- </ section >
107
+ < SessionSpeakers event = { event } className = "-mx-px" />
108
+
109
+ < div className = "py-8 xl:mt-16" >
110
+ { event . files ?. map ( ( { path } ) => (
111
+ < div key = { path } className = "flex flex-col" >
112
+ < Button
113
+ variant = "tertiary"
114
+ href = { path }
115
+ target = "_blank"
116
+ rel = "noreferrer"
117
+ className = { clsx (
118
+ "m-1 h-fit items-center gap-x-2 self-end bg-neu-100 !p-2 text-neu-700 transition-opacity hover:bg-neu-200/80 hover:text-neu-900 disabled:opacity-0" ,
119
+ ) }
120
+ >
121
+ View full PDF
122
+ < ExternalLinkIcon className = "size-4" />
123
+ </ Button >
124
+ < iframe src = { path } className = "aspect-video size-full" />
125
+ </ div >
126
+ ) ) }
127
+ </ div >
128
+ </ section >
129
+ </ div >
101
130
</ div >
102
131
</ div >
103
- </ div >
104
- </ main >
132
+
133
+ < div className = "bg-neu-0 py-8 xl:py-16" >
134
+ < div className = "gql-conf-container" >
135
+ < CtaCardSection
136
+ title = "Get your ticket"
137
+ description = "Join three transformative days of expert insights and innovation to shape the next decade of APIs!"
138
+ >
139
+ < Button variant = "primary" href = { GET_TICKETS_LINK } >
140
+ Get tickets
141
+ </ Button >
142
+ </ CtaCardSection >
143
+ < div className = "py-8" >
144
+ < MarqueeRows variant = "secondary" items = { HERO_MARQUEE_ITEMS } />
145
+ </ div >
146
+ </ div >
147
+ </ div >
148
+ </ main >
149
+ </ >
105
150
)
106
151
}
107
152
@@ -139,15 +184,17 @@ function SessionHeader({
139
184
event,
140
185
eventTitle,
141
186
year,
187
+ className,
142
188
} : {
143
189
event : ScheduleSession
144
190
eventTitle : string | null
145
191
year : number | `${number } `
192
+ className ?: string
146
193
} ) {
147
194
const speakers = event . speakers || [ ]
148
195
149
196
return (
150
- < header >
197
+ < header className = { className } >
151
198
< BackLink year = "2025" kind = "schedule" />
152
199
< p
153
200
className = { clsx (
@@ -187,12 +234,29 @@ function SessionHeader({
187
234
)
188
235
}
189
236
190
- function SessionSpeakers ( { event } : { event : ScheduleSession } ) {
237
+ function SessionSpeakers ( {
238
+ event,
239
+ className,
240
+ } : {
241
+ event : ScheduleSession
242
+ className ?: string
243
+ } ) {
191
244
return (
192
- < div className = "grid gap-5 lg:grid-cols-2" >
245
+ < div className = { clsx ( "grid gap-5 lg:grid-cols-2" , className ) } >
193
246
{ event . speakers ?. map ( speaker => (
194
247
< SpeakerCard key = { speaker . username } speaker = { speaker } year = "2025" />
195
248
) ) }
196
249
</ div >
197
250
)
198
251
}
252
+
253
+ function Hr ( { className } : { className ?: string } ) {
254
+ return (
255
+ < hr
256
+ className = { clsx (
257
+ "ml-[-50vw] w-[200vw] border-neu-200 dark:border-neu-100" ,
258
+ className ,
259
+ ) }
260
+ />
261
+ )
262
+ }
0 commit comments