@@ -6,23 +6,9 @@ import Link from "next/link"
6
6
import { Button } from "../../_design-system/button"
7
7
import ArrowDownIcon from "../pixelarticons/arrow-down.svg?svgr"
8
8
9
- function TabHeading ( {
10
- children,
11
- className,
12
- } : {
13
- children : ReactNode
14
- className ?: string
15
- } ) {
16
- return (
17
- < h2 className = { clsx ( "mb-4 text-2xl font-semibold" , className ) } >
18
- { children }
19
- </ h2 >
20
- )
21
- }
22
-
23
9
function DatesTab ( ) {
24
10
return (
25
- < dl className = "divide-y divide-sec-dark border-neu-300 md:divide-neu-300 md:border" >
11
+ < DefinitionListBox >
26
12
< DefinitionListItem term = "CFP Opens" definition = "Tuesday, 4 February" />
27
13
< DefinitionListItem
28
14
term = "CFP Close"
@@ -44,7 +30,7 @@ function DatesTab() {
44
30
term = "Event Dates"
45
31
definition = "Monday, 8 September - Wednesday, 10 September, 2024"
46
32
/>
47
- </ dl >
33
+ </ DefinitionListBox >
48
34
)
49
35
}
50
36
@@ -58,21 +44,21 @@ function DefinitionListItem({
58
44
definition : string
59
45
} ) {
60
46
return (
61
- < div className = { clsx ( className , "flex typography-body-md max-md :flex-col" ) } >
62
- < dt className = "flex w-[184.5px] shrink-0 items-center whitespace-pre border-neu-300 bg-white/[0.79] px-3 py-2 max-md :w-full md :border-r md :p-4" >
47
+ < div className = { clsx ( className , "flex typography-body-md max-sm :flex-col" ) } >
48
+ < dt className = "flex w-[184.5px] shrink-0 items-center whitespace-pre border-neu-300 bg-white/[0.79] px-3 py-2 max-sm :w-full sm :border-r sm :p-4" >
63
49
{ term }
64
50
</ dt >
65
- < dd className = "flex flex-1 items-center bg-white/[0.48] px-3 py-2 backdrop-blur-[3px] md :p-4" >
51
+ < dd className = "flex flex-1 items-center bg-white/[0.48] px-3 py-2 backdrop-blur-[3px] sm :p-4" >
66
52
{ definition }
67
53
</ dd >
68
54
</ div >
69
55
)
70
56
}
71
57
function TopicsTab ( ) {
72
58
return (
73
- < div >
74
- < TabHeading className = "mt-6 " > Suggested Topics</ TabHeading >
75
- < ul className = "list-disc space-y-2 pl-6" >
59
+ < div className = "bg-sec-light p-4" >
60
+ < h3 className = "typography-h3 " > Suggested Topics</ h3 >
61
+ < ul className = "mt-2 list-disc space-y-2 pl-6" >
76
62
< li > GraphQL Working Group</ li >
77
63
< ul className = "list-disc space-y-2 pl-6" >
78
64
< li >
@@ -110,20 +96,20 @@ function TopicsTab() {
110
96
111
97
function NotesTab ( ) {
112
98
return (
113
- < div >
114
- < TabHeading className = "mt-6 " > Important Notes</ TabHeading >
115
- < ul className = "list-disc space-y-2 pl-6" >
99
+ < div className = "bg-sec-light p-4" >
100
+ < h3 className = "typography-h3 " > Important Notes</ h3 >
101
+ < ul className = "mt-2 list-disc space-y-2 pl-6" >
116
102
< li >
117
103
All speakers are required to adhere to our{ " " }
118
104
< Link
119
- className = "underline hover:text-primary "
105
+ className = "text-neu-800 underline hover:no-underline dark: text-neu-50 "
120
106
href = "/conf/2025/resources/#code-of-conduct"
121
107
>
122
108
Code of Conduct
123
109
</ Link >
124
110
. We also highly recommend that speakers take our online{ " " }
125
111
< a
126
- className = "underline hover:text-primary "
112
+ className = "text-neu-800 underline hover:no-underline dark: text-neu-50 "
127
113
target = "_blank"
128
114
href = "https://training.linuxfoundation.org/linux-courses/open-source-compliance-courses/inclusive-speaker-orientation"
129
115
>
@@ -153,10 +139,8 @@ function NotesTab() {
153
139
event.
154
140
</ li >
155
141
</ ul >
156
- < TabHeading className = "mt-6" >
157
- Preparing to Submit Your Proposal
158
- </ TabHeading >
159
- < p className = "mb-4" >
142
+ < h3 className = "mt-6 typography-h3" > Preparing to Submit Your Proposal</ h3 >
143
+ < p className = "mt-2" >
160
144
While it is not our intention to provide you with strict instructions on
161
145
how to prepare your proposal, we hope you will take a moment to review
162
146
the following guidelines that we have put together to help you prepare
@@ -176,22 +160,25 @@ function NotesTab() {
176
160
letting you share your experiences, educate the community about an
177
161
issue, or generate interest in a project.
178
162
</ p >
179
- < TabHeading className = "mt-6" > How to Give a Great Talk</ TabHeading >
180
- < p >
163
+ < h3 className = "mt-6 typography-h3 " > How to Give a Great Talk</ h3 >
164
+ < p className = "mt-2" >
181
165
We want to make sure submitters receive resources to help put together a
182
166
great submission and if accepted, give the best presentation possible.
183
167
To help with this, we recommend viewing seasoned speaker Dawn Foster's
184
168
in-depth talk:{ " " }
185
- < a href = "https://youtu.be/2I5fYBLCfUA" target = "_blank" >
186
- Getting Over Your Imposter Syndrome to Become a Conference Speaker –
187
- Dawn Foster, VMware
169
+ < a
170
+ href = "https://youtu.be/2I5fYBLCfUA"
171
+ target = "_blank"
172
+ className = "text-neu-800 underline hover:no-underline dark:text-neu-50"
173
+ >
174
+ Getting Over Your Imposter Syndrome to Become a Conference Speaker
188
175
</ a >
189
176
.
190
177
</ p >
191
- < TabHeading className = "mt-6" >
178
+ < h3 className = "mt-6 typography-h3 " >
192
179
Have More Questions? First Time Submitting? Don't Feel Intimidated
193
- </ TabHeading >
194
- < p >
180
+ </ h3 >
181
+ < p className = "mt-2" >
195
182
Linux Foundation events are an excellent way to get to know the
196
183
community and share your ideas and the work that you are doing and we
197
184
strongly encourage first-time speakers to submit talks for our events.
@@ -205,30 +192,38 @@ function NotesTab() {
205
192
206
193
function TypesTab ( ) {
207
194
return (
208
- < div >
209
- < TabHeading className = "mt-6" > Submission Types</ TabHeading >
210
- < ul className = "list-disc space-y-2 pl-6" >
211
- < li >
212
- Session Presentation: Typically 30 minutes in length, 1-2 speakers
213
- presenting on a topic
214
- </ li >
215
- < li >
216
- Panel Discussion: Typically 30 minutes in length, 3-4 speakers
217
- presenting on a topic
218
- </ li >
219
- < li > Birds of a Feather: Typically 45 minutes to 1 hour in length</ li >
220
- < li > Lightning Talk: Typically 5-10 minutes in length</ li >
221
- < li > Workshop: Typically 1-2 hours in length</ li >
222
- </ ul >
195
+ < div className = "md:p-8 lg:p-16" >
196
+ < dl className = "divide-y divide-sec-dark border-neu-300 md:divide-neu-300 md:border md:shadow-[0px_0px_20px_0px_rgba(133,185,19,0.20)]" >
197
+ < DefinitionListItem
198
+ term = "Session Presentation"
199
+ definition = "Typically 30 minutes in length, 1-2 speakers presenting on a topic"
200
+ />
201
+ < DefinitionListItem
202
+ term = "Panel Discussion"
203
+ definition = "Typically 30 minutes in length, 3-4 speakers presenting on a topic"
204
+ />
205
+ < DefinitionListItem
206
+ term = "Birds of a Feather"
207
+ definition = "Typically 45 minutes to 1 hour in length"
208
+ />
209
+ < DefinitionListItem
210
+ term = "Lightning Talk"
211
+ definition = "Typically 5-10 minutes in length"
212
+ />
213
+ < DefinitionListItem
214
+ term = "Workshop"
215
+ definition = "Typically 1-2 hours in length"
216
+ />
217
+ </ dl >
223
218
</ div >
224
219
)
225
220
}
226
221
227
222
function ProcessTab ( ) {
228
223
return (
229
- < div >
230
- < TabHeading className = "mt-6 " > The Talk Selection Process</ TabHeading >
231
- < p className = "mb-4 " >
224
+ < div className = "bg-sec-light p-4" >
225
+ < h3 className = "typography-h3 " > The Talk Selection Process</ h3 >
226
+ < p className = "mt-2 " >
232
227
The GraphQL Foundation strives to select conference talks based on fair
233
228
criteria in a transparent manner. There are three groups involved in the
234
229
selection process, each with their own focus to help create an engaging
@@ -239,36 +234,36 @@ function ProcessTab() {
239
234
< li > The new Subject Matter Experts initiative (SMEs)</ li >
240
235
< li > The Program Committee</ li >
241
236
</ ul >
242
- < TabHeading className = "mt-6" > The Technical Steering Committee</ TabHeading >
243
- < p className = "mb-4 " >
237
+ < h3 className = "mt-6 typography-h3 " > The Technical Steering Committee</ h3 >
238
+ < p className = "mt-2 " >
244
239
The TSC are a group of 11 individuals who are elected to serve a two
245
240
year term to provide technical oversight of all GraphQL development
246
241
efforts. When evaluating conference talks they{ " " }
247
242
< strong > focus on quality</ strong > and use the following criteria:
248
243
</ p >
249
- < ul className = "list-disc space-y-2 pl-6" >
244
+ < ul className = "mt-2 list-disc space-y-2 pl-6" >
250
245
< li > Relevance</ li >
251
246
< li > Originality</ li >
252
247
< li > Soundness</ li >
253
248
< li > Quality of Presentation</ li >
254
249
< li > Importance</ li >
255
250
</ ul >
256
- < TabHeading className = "mt-6" > Subject Matter Experts</ TabHeading >
257
- < p className = "mb-4 " >
251
+ < h3 className = "mt-6 typography-h3 " > Subject Matter Experts</ h3 >
252
+ < p className = "mt-2 " >
258
253
The SME initiative is new for 2025. This will be a panel of volunteers
259
254
drawn from industry experts, working group members, security and
260
255
observability experts, and maintainers and contributors to open source
261
256
GraphQL projects. When evaluating the talks, they will{ " " }
262
257
< strong > focus on how exciting and engaging the talks are</ strong > and
263
258
use the following criteria:
264
259
</ p >
265
- < ul className = "list-disc space-y-2 pl-6" >
260
+ < ul className = "mt-2 list-disc space-y-2 pl-6" >
266
261
< li > Subject Content</ li >
267
262
< li > Originality</ li >
268
263
< li > Audience Engagement</ li >
269
264
</ ul >
270
- < TabHeading className = "mt-6" > The Program Committee</ TabHeading >
271
- < p >
265
+ < h3 className = "mt-6 typography-h3 " > The Program Committee</ h3 >
266
+ < p className = "mt-2" >
272
267
The Program Committee is made up of representatives from the GraphQL
273
268
Foundation board and interested members of the GraphQL community who
274
269
have had experience organizing conferences. They shape the schedule from
@@ -277,10 +272,10 @@ function ProcessTab() {
277
272
demographics, to ensure a varied and well-rounded representation of the
278
273
GraphQL ecosystem.
279
274
</ p >
280
- < TabHeading className = "mt-6" >
275
+ < h3 className = "mt-6 typography-h3 " >
281
276
Have More Questions? First Time Submitting? Don't Feel Intimidated
282
- </ TabHeading >
283
- < p >
277
+ </ h3 >
278
+ < p className = "mt-2" >
284
279
Linux Foundation events are an excellent way to get to know the
285
280
community and share your ideas and the work that you are doing and we
286
281
strongly encourage first-time speakers to submit talks for our events.
@@ -325,7 +320,11 @@ export function CallForProposals() {
325
320
} , [ ] )
326
321
327
322
return (
328
- < section id = "speakers" className = "gql-conf-section gql-conf-container" >
323
+ < section
324
+ id = "speakers"
325
+ // todo: the part with `dark:` here is temporary until we have a dark mode version of this section
326
+ className = "gql-conf-section gql-conf-container dark:text-neu-0"
327
+ >
329
328
< div className = "flex *:basis-1/2 max-md:flex-col" >
330
329
< div className = "border-sec-dark bg-sec-light p-4 dark:border-sec-lighter md:border-r md:p-8 lg:p-16" >
331
330
< h1 className = "typography-h2" > Call for Proposals</ h1 >
@@ -340,7 +339,7 @@ export function CallForProposals() {
340
339
For any questions regarding the CFP process, please email{ " " }
341
340
< a
342
341
343
- className = "text-neu-800 underline hover:no-underline"
342
+ className = "text-neu-800 underline hover:no-underline dark:text-neu-50 "
344
343
>
345
344
346
345
</ a >
@@ -354,7 +353,7 @@ export function CallForProposals() {
354
353
< a
355
354
target = "_blank"
356
355
href = "https://sessionize.com/playbook/submit-your-session-for-an-event"
357
- className = "text-neu-800 underline hover:no-underline"
356
+ className = "text-neu-800 underline hover:no-underline dark:text-neu-50 "
358
357
>
359
358
how to submit your session
360
359
</ a > { " " }
@@ -377,32 +376,81 @@ export function CallForProposals() {
377
376
< article className = "flex h-auto flex-col bg-[#C6F267]" >
378
377
< div
379
378
role = "tablist"
380
- className = "flex divide-sec-dark border-b border-sec-dark *:flex-1 md:divide-x"
379
+ className = "flex divide-sec-dark border-b border-sec-dark *:flex-1 max-md:sr-only md:divide-x"
381
380
>
382
381
{ tabsInOrder . map ( ( tab , i ) => (
383
- < button
384
- key = { tab }
382
+ < TabButton
383
+ tab = { tab }
385
384
tabIndex = { i === 0 ? 0 : - 1 }
386
- role = "tab"
387
- aria-selected = { activeTab === tab }
388
- 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"
389
- onFocus = { ( ) => setActiveTab ( tab ) }
390
- onKeyDown = { arrowsMoveSideways }
391
- >
392
- { tab . charAt ( 0 ) . toUpperCase ( ) + tab . slice ( 1 ) }
393
- < ArrowDownIcon className = "ml-2 size-6 text-sec-darker opacity-0 [[aria-selected=true]>&]:opacity-100" />
394
- </ button >
385
+ activeTab = { activeTab }
386
+ setActiveTab = { setActiveTab }
387
+ />
395
388
) ) }
396
389
</ div >
397
- < div className = "flex flex-1 items-center justify-center md:p-8 lg:p-16" >
398
- { tabs [ activeTab ] }
390
+ < div className = "flex flex-1 justify-center max-md:flex-col md:items-center" >
391
+ { tabsInOrder . map ( tab => (
392
+ < >
393
+ < TabButton
394
+ tab = { tab }
395
+ activeTab = { activeTab }
396
+ setActiveTab = { setActiveTab }
397
+ className = "md:hidden"
398
+ aria-hidden
399
+ />
400
+ < div
401
+ role = "tabpanel"
402
+ key = { tab }
403
+ id = { `tabpanel-${ tab } ` }
404
+ className = "flex-1"
405
+ style = { {
406
+ display : activeTab === tab ? "block" : "none" ,
407
+ } }
408
+ >
409
+ { tabs [ tab ] }
410
+ </ div >
411
+ </ >
412
+ ) ) }
399
413
</ div >
400
414
</ article >
401
415
</ div >
402
416
</ section >
403
417
)
404
418
}
405
419
420
+ interface TabButtonProps
421
+ extends Omit < React . HTMLAttributes < HTMLButtonElement > , "onFocus" > {
422
+ tab : Tab
423
+ tabIndex ?: number
424
+ activeTab : Tab
425
+ setActiveTab : ( tab : Tab ) => void
426
+ }
427
+
428
+ function TabButton ( {
429
+ tab,
430
+ tabIndex,
431
+ activeTab,
432
+ setActiveTab,
433
+ ...props
434
+ } : TabButtonProps ) {
435
+ return (
436
+ < button
437
+ key = { tab }
438
+ tabIndex = { tabIndex }
439
+ aria-selected = { activeTab === tab }
440
+ className = "gql-focus-visible flex items-center justify-between px-3 py-4 typography-body-lg hover:bg-sec-light focus:outline-none max-md:border-b max-md:border-sec-dark max-md:first:border-t md:[--collapsible:1] md:aria-selected:bg-sec-light"
441
+ onFocus = { event => {
442
+ console . log ( "focus" )
443
+ setActiveTab ( tab )
444
+ } }
445
+ onKeyDown = { arrowsMoveSideways }
446
+ { ...props }
447
+ >
448
+ { tab . charAt ( 0 ) . toUpperCase ( ) + tab . slice ( 1 ) }
449
+ < ArrowDownIcon className = "ml-2 size-6 text-sec-darker opacity-0 [[aria-selected=true]>&]:opacity-100" />
450
+ </ button >
451
+ )
452
+ }
453
+
406
454
function arrowsMoveSideways ( event : React . KeyboardEvent < HTMLButtonElement > ) {
407
455
if ( event . key === "ArrowLeft" ) {
408
456
const previousElement = event . currentTarget . previousElementSibling
@@ -416,3 +464,13 @@ function arrowsMoveSideways(event: React.KeyboardEvent<HTMLButtonElement>) {
416
464
}
417
465
}
418
466
}
467
+
468
+ function DefinitionListBox ( { children } : { children : React . ReactNode } ) {
469
+ return (
470
+ < div className = "md:p-8 lg:p-16" >
471
+ < dl className = "divide-y divide-sec-dark border-neu-300 md:divide-neu-300 md:border md:shadow-[0px_0px_20px_0px_rgba(133,185,19,0.20)]" >
472
+ { children }
473
+ </ dl >
474
+ </ div >
475
+ )
476
+ }
0 commit comments