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