@@ -3,6 +3,8 @@ import clsx from "clsx"
3
3
4
4
import { useState , useEffect , ReactNode } from "react"
5
5
import Link from "next/link"
6
+ import { Button } from "../../_design-system/button"
7
+ import ArrowDownIcon from "../pixelarticons/arrow-down.svg?svgr"
6
8
7
9
function TabHeading ( {
8
10
children,
@@ -159,11 +161,7 @@ function NotesTab() {
159
161
great submission and if accepted, give the best presentation possible.
160
162
To help with this, we recommend viewing seasoned speaker Dawn Foster's
161
163
in-depth talk:{ " " }
162
- < a
163
- href = "https://youtu.be/2I5fYBLCfUA"
164
- target = "_blank"
165
- className = "underline hover:text-primary"
166
- >
164
+ < a href = "https://youtu.be/2I5fYBLCfUA" target = "_blank" >
167
165
Getting Over Your Imposter Syndrome to Become a Conference Speaker –
168
166
Dawn Foster, VMware
169
167
</ a >
@@ -177,13 +175,8 @@ function NotesTab() {
177
175
community and share your ideas and the work that you are doing and we
178
176
strongly encourage first-time speakers to submit talks for our events.
179
177
In the instance that you aren't sure about your abstract,{ " " }
180
- < a
181
- className = "underline hover:text-primary"
182
-
183
- >
184
- reach out to us
185
- </ a > { " " }
186
- and we will be more than happy to work with you on your proposal.
178
+ < a href = "mailto:[email protected] " > reach out to us
</ a > and we will
179
+ be more than happy to work with you on your proposal.
187
180
</ p >
188
181
</ >
189
182
)
@@ -283,10 +276,22 @@ function ProcessTab() {
283
276
)
284
277
}
285
278
286
- export function Speakers ( ) {
279
+ const tabs = {
280
+ dates : < DatesTab /> ,
281
+ topics : < TopicsTab /> ,
282
+ types : < TypesTab /> ,
283
+ notes : < NotesTab /> ,
284
+ process : < ProcessTab /> ,
285
+ }
286
+
287
+ type Tab = keyof typeof tabs
288
+
289
+ const tabsInOrder : Tab [ ] = [ "dates" , "topics" , "types" , "notes" , "process" ]
290
+
291
+ export function CallForProposals ( ) {
287
292
const [ buttonText , setButtonText ] = useState ( "Submit a Proposal" )
288
293
const [ isDisabled , setIsDisabled ] = useState ( false )
289
- const [ activeTab , setActiveTab ] = useState ( "dates" )
294
+ const [ activeTab , setActiveTab ] = useState < Tab > ( "dates" )
290
295
291
296
useEffect ( ( ) => {
292
297
const checkDate = ( ) => {
@@ -304,83 +309,90 @@ export function Speakers() {
304
309
return ( ) => clearInterval ( timer )
305
310
} , [ ] )
306
311
307
- const tabContent = {
308
- dates : < DatesTab /> ,
309
- topics : < TopicsTab /> ,
310
- types : < TypesTab /> ,
311
- notes : < NotesTab /> ,
312
- process : < ProcessTab /> ,
313
- }
314
-
315
312
return (
316
- < section id = "speakers" className = "" >
317
- < h1 className = "conf-heading" > Call for Proposals</ h1 >
318
- < p className = "mb-4" >
319
- Putting on an amazing conference depends on great content, which is
320
- where you come in! Join other GraphQL leaders and community members as a
321
- presenter by submitting to our Call for Proposals (CFP) and sharing your
322
- experience across a wide range of topics. Please click through all of
323
- the tabs below before submitting a proposal.
324
- </ p >
325
- < p className = "mb-4" >
326
- For any questions regarding the CFP process, please email{ " " }
327
- < a
328
-
329
- className = "underline hover:text-primary"
330
- >
331
-
332
- </ a >
333
- .
334
- </ p >
335
- < button
336
- disabled = { isDisabled }
337
- onClick = { ( ) =>
338
- window . open (
339
- "https://sessionize.com/graphqlconf-2025?utm_medium=website&utm_campaign=speaker_section" ,
340
- "_blank" ,
341
- )
342
- }
343
- className = { clsx (
344
- "px-20 py-4 text-center text-3xl font-semibold transition-colors md:px-28" ,
345
- isDisabled
346
- ? "cursor-not-allowed bg-gray-400"
347
- : "bg-primary/85 hover:bg-primary/100" ,
348
- ) }
349
- >
350
- { buttonText }
351
- </ button >
352
- < p className = "mb-8 mt-6" >
353
- Please be aware that the Linux Foundation uses Sessionize for CFP
354
- submissions. Sessionize is a cloud-based event content management
355
- software designed to be intuitive and user-friendly. If you need
356
- guidance, please review{ " " }
357
- < a
358
- className = "underline hover:text-primary"
359
- target = "_blank"
360
- href = "https://sessionize.com/playbook/submit-your-session-for-an-event"
361
- >
362
- how to submit your session
363
- </ a > { " " }
364
- for an event to see step-by-step instructions and helpful screenshots.
365
- </ p >
366
- < div className = "mb-6" >
367
- < div className = "flex border-b" >
368
- { [ "dates" , "topics" , "types" , "notes" , "process" ] . map ( tab => (
369
- < button
370
- key = { tab }
371
- className = { `px-4 py-2 font-semibold ${
372
- activeTab === tab
373
- ? "border-b-2 border-primary text-white"
374
- : "text-gray-400 hover:text-primary"
375
- } `}
376
- onClick = { ( ) => setActiveTab ( tab ) }
313
+ < section id = "speakers" className = "gql-conf-section gql-conf-container" >
314
+ < div className = "flex p-4 *:basis-1/2 max-md:flex-col" >
315
+ < div className = "border-sec-dark bg-sec-light dark:border-sec-lighter max-md:border-r md:p-8 lg:p-16" >
316
+ < h1 className = "typography-h2" > Call for Proposals</ h1 >
317
+ < p className = "mt-6 md:mt-10" >
318
+ Putting on an amazing conference depends on great content, which is
319
+ where you come in! Join other GraphQL leaders and community members
320
+ as a presenter by submitting to our Call for Proposals (CFP) and
321
+ sharing your experience across a wide range of topics. Please click
322
+ through all of the tabs below before submitting a proposal.
323
+ </ p >
324
+ < p className = "mt-6" >
325
+ For any questions regarding the CFP process, please email{ " " }
326
+ < a
327
+
328
+ className = "text-neu-800 underline hover:no-underline"
377
329
>
378
- { tab . charAt ( 0 ) . toUpperCase ( ) + tab . slice ( 1 ) }
379
- </ button >
380
- ) ) }
330
+
331
+ </ a >
332
+ .
333
+ </ p >
334
+ < p className = "mt-6 typography-body-sm md:mt-10" >
335
+ Please be aware that the Linux Foundation uses Sessionize for CFP
336
+ submissions. Sessionize is a cloud-based event content management
337
+ software designed to be intuitive and user-friendly. If you need
338
+ guidance, please review{ " " }
339
+ < a
340
+ target = "_blank"
341
+ href = "https://sessionize.com/playbook/submit-your-session-for-an-event"
342
+ className = "text-neu-800 underline hover:no-underline"
343
+ >
344
+ how to submit your session
345
+ </ a > { " " }
346
+ for an event to see step-by-step instructions and helpful
347
+ screenshots.
348
+ </ p >
349
+ < Button
350
+ disabled = { isDisabled }
351
+ variant = "primary"
352
+ href = "https://sessionize.com/graphqlconf-2025?utm_medium=website& utm_campaign = speaker_section "
353
+ className = { clsx (
354
+ "mt-6 md:mt-10" ,
355
+ isDisabled && "cursor-not-allowed" ,
356
+ ) }
357
+ >
358
+ { buttonText }
359
+ </ Button >
381
360
</ div >
382
- { /* @ts -ignore - fine code */ }
383
- < div className = "mt-6" > { tabContent [ activeTab ] } </ div >
361
+ < article className = "bg-sec-base" >
362
+ < div
363
+ role = "tablist"
364
+ className = "flex divide-sec-dark border-b border-sec-dark *:flex-1 md:divide-x"
365
+ >
366
+ { tabsInOrder . map ( ( tab , i ) => (
367
+ < button
368
+ key = { tab }
369
+ tabIndex = { i === 0 ? 0 : - 1 }
370
+ role = "tab"
371
+ aria-selected = { activeTab === tab }
372
+ className = "gql-focus-visible flex items-center justify-between px-3 py-4 typography-body-lg hover:bg-sec-light focus:outline-none aria-selected:bg-sec-light"
373
+ onFocus = { ( ) => setActiveTab ( tab ) }
374
+ onKeyDown = { event => {
375
+ if ( event . key === "ArrowLeft" ) {
376
+ const previousElement =
377
+ event . currentTarget . previousElementSibling
378
+ if ( previousElement ) {
379
+ ; ( previousElement as HTMLElement ) . focus ( )
380
+ }
381
+ } else if ( event . key === "ArrowRight" ) {
382
+ const nextElement = event . currentTarget . nextElementSibling
383
+ if ( nextElement ) {
384
+ ; ( nextElement as HTMLElement ) . focus ( )
385
+ }
386
+ }
387
+ } }
388
+ >
389
+ { tab . charAt ( 0 ) . toUpperCase ( ) + tab . slice ( 1 ) }
390
+ < ArrowDownIcon className = "ml-2 size-6 opacity-0 [[aria-selected=true]>&]:opacity-100" />
391
+ </ button >
392
+ ) ) }
393
+ </ div >
394
+ < div className = "md:p-8 lg:p-16" > { tabs [ activeTab ] } </ div >
395
+ </ article >
384
396
</ div >
385
397
</ section >
386
398
)
0 commit comments