Skip to content

Commit de13ee3

Browse files
committed
Merge branch 'source' into new-conf-design--ogs
2 parents cf23c4c + d2452db commit de13ee3

32 files changed

+596
-451
lines changed

src/app/conf/2023/sessions/[id]/_event_title.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ScheduleSession } from "../../../_components/schedule/session-list"
1+
import { ScheduleSession } from "@/app/conf/_api/sched-types"
22

33
export function getEventTitle(
44
event: ScheduleSession,

src/app/conf/2025/components/navbar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export function Navbar({ links, year }: NavbarProps): ReactElement {
5353
<NavbarPlaceholder className="bg-pri-base before:bg-white/30 dark:bg-pri-darker dark:before:bg-blk/40" />
5454
<header
5555
className={clsx(
56-
"gql-all-anchors-focusable sticky top-0 z-10 w-full border-b border-blk/60 font-mono text-neu-900 antialiased dark:border-white/80",
56+
"gql-all-anchors-focusable sticky top-0 z-[100] w-full border-b border-blk/60 font-mono text-neu-900 antialiased dark:border-white/80",
5757
mobileDrawerOpen && "!border-neu-900 dark:!border-white",
5858
)}
5959
>

src/app/conf/2025/components/session-tags.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,17 @@ export function SessionTags({ session, className, ...rest }: SessionTagsProps) {
2121
{eventType && (
2222
<Tag color={eventsColors[session.event_type || ""]}>{eventType}</Tag>
2323
)}
24-
{session.audience && (
24+
{session.company && (
2525
<Tag
26-
color={eventsColors[session.audience] || "hsl(var(--color-neu-700))"}
26+
color={eventsColors[session.company] || "hsl(var(--color-neu-500))"}
2727
>
28-
{session.audience}
28+
{session.company}
2929
</Tag>
3030
)}
3131
{session.event_subtype && (
3232
<Tag
3333
color={
34-
eventsColors[session.event_subtype] || "hsl(var(--color-sec-base))"
34+
eventsColors[session.event_subtype] || "hsl(var(--color-sec-dark))"
3535
}
3636
>
3737
{session.event_subtype}

src/app/conf/2025/components/speaker-tags.tsx

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,17 @@ export function SpeakerTags({
1616
className?: string
1717
showEventType?: boolean
1818
}) {
19-
const eventType =
20-
showEventType && speakerSessions.get(speaker.username)?.[0]?.event_type
19+
const firstTalk = speakerSessions.get(speaker.username)?.[0]
20+
let tag = showEventType && firstTalk?.event_subtype
21+
22+
const tagColor = (tag && eventsColors[tag]) || "hsl(var(--color-sec-dark))"
23+
if (tag && tag.includes(" and ")) {
24+
tag = tag.replace(" and ", " & ")
25+
}
2126

2227
return (
2328
<div className={clsx("flex basis-0 flex-wrap gap-2", className)}>
24-
{eventType && (
25-
<Tag color={eventsColors[eventType] || "hsl(var(--color-sec-base))"}>
26-
{eventType === "Federation and Composite Schemas"
27-
? "Federation"
28-
: eventType}
29-
</Tag>
30-
)}
29+
{tag && <Tag color={tagColor}>{tag}</Tag>}
3130

3231
{speaker._years.length > 1 && (
3332
<Tag color="hsl(var(--color-neu-500))">

src/app/conf/2025/components/what-to-expect.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import clsx from "clsx"
22
import { HTMLAttributes } from "react"
33

4+
import { schedule, speakers } from "../_data"
5+
46
interface WhatToExpectSectionProps extends HTMLAttributes<HTMLElement> {}
57

68
export default function WhatToExpectSection({
@@ -14,16 +16,16 @@ export default function WhatToExpectSection({
1416
>
1517
<h3 className="typography-h2 md:flex-1">What to expect</h3>
1618
<ul className="flex flex-col gap-6 uppercase md:flex-1">
17-
<ListItem number="75+" text="talks" />
18-
<ListItem number="42" text="sessions" />
19+
<ListItem number={schedule.length} text="sessions" />
20+
<ListItem number={speakers.length} text="speakers" />
21+
<ListItem number="9" text="lightning talks" />
1922
<ListItem number="7" text="workshops" />
20-
<ListItem number="1" text="unique venue" />
2123
</ul>
2224
</section>
2325
)
2426
}
2527

26-
function ListItem({ number, text }: { number: string; text: string }) {
28+
function ListItem({ number, text }: { number: string | number; text: string }) {
2729
return (
2830
<li className="list-none bg-gradient-to-r from-[#CDF27E] p-6 dark:from-[#507501]">
2931
<span className="inline-block w-[87px] text-[72px]/none [text-box:trim-both_cap_alphabetic]">

src/app/conf/2025/schedule/[id]/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import clsx from "clsx"
66
import { metadata as layoutMetadata } from "@/app/conf/2023/layout"
77

88
import { speakers, schedule } from "../../_data"
9-
import { SchedSpeaker, ScheduleSession } from "../../../2023/types"
9+
import { ScheduleSession } from "../../../2023/types"
1010

1111
import { findVideo, SessionVideo } from "./session-video"
1212
import { NavbarPlaceholder } from "../../components/navbar"

src/app/conf/2025/schedule/_components/filters.tsx

Lines changed: 71 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,84 @@
11
import clsx from "clsx"
22
import { useState } from "react"
3-
import { Combobox } from "@headlessui/react"
3+
import {
4+
Combobox,
5+
ComboboxInput,
6+
ComboboxOption,
7+
ComboboxOptions,
8+
ComboboxButton,
9+
Label,
10+
} from "@headlessui/react"
411

512
import { Tag } from "@/app/conf/_design-system/tag"
613
import { Button } from "@/app/conf/_design-system/button"
714

815
import CloseIcon from "@/app/conf/_design-system/pixelarticons/close.svg?svgr"
916
import CaretDownIcon from "@/app/conf/_design-system/pixelarticons/caret-down.svg?svgr"
1017
import { eventsColors } from "../../utils"
18+
import { ScheduleSession } from "@/app/conf/_api/sched-types"
19+
20+
export interface FilterCategoryConfig {
21+
property: keyof ScheduleSession
22+
label: string
23+
options: string[]
24+
enabledOptions?: Set<string> | null
25+
}
26+
27+
export const FilterCategoryConfig = {
28+
fromFields: (
29+
fields: Partial<Record<keyof ScheduleSession, string /* label */>>,
30+
scheduleData: ScheduleSession[],
31+
) => {
32+
return Object.entries(fields).map(
33+
([field, label]): FilterCategoryConfig => ({
34+
property: field as keyof ScheduleSession,
35+
label,
36+
options: Array.from(
37+
new Set(
38+
scheduleData.map(
39+
session => session[field as keyof ScheduleSession],
40+
),
41+
),
42+
).filter((x): x is string => !!x && typeof x === "string"),
43+
}),
44+
)
45+
},
46+
}
47+
48+
export type CategoryName = keyof ScheduleSession
49+
50+
export interface FilterStates extends Partial<Record<CategoryName, string[]>> {}
51+
export const FilterStates = {
52+
initial: (fields: Array<keyof ScheduleSession>) =>
53+
Object.fromEntries(fields.map(field => [field, []])),
54+
}
55+
1156
type FiltersProps = {
12-
categories: { name: string; options: string[] }[]
57+
categories: FilterCategoryConfig[]
1358
filterState: Record<string, string[]>
59+
enabledOptions: Record<string, Set<string> | null>
1460
onFilterChange: (category: string, newSelectedOptions: string[]) => void
1561
}
1662

1763
export function Filters({
1864
categories,
1965
filterState,
66+
enabledOptions,
2067
onFilterChange,
2168
}: FiltersProps) {
2269
return (
2370
<div className="flex flex-wrap justify-stretch gap-x-2 gap-y-4 pb-10">
2471
{categories.map(category => (
2572
<FiltersCombobox
26-
key={category.name}
27-
label={category.name}
73+
key={category.property}
74+
label={category.label}
2875
options={category.options}
29-
value={filterState[category.name] || []}
76+
enabledOptions={enabledOptions[category.property]}
77+
value={filterState[category.property] || []}
3078
onChange={newSelectedOptions => {
31-
onFilterChange(category.name, newSelectedOptions)
79+
onFilterChange(category.property, newSelectedOptions)
3280
}}
33-
placeholder={`Any ${category.name.toLowerCase()}`}
81+
placeholder={`Any ${category.label.toLowerCase()}`}
3482
className="flex-1"
3583
/>
3684
))}
@@ -69,6 +117,7 @@ export function ResetFiltersButton({
69117
interface FiltersComboboxProps {
70118
label: string
71119
options: string[]
120+
enabledOptions: Set<string> | null
72121
value: string[]
73122
onChange: (newSelectedOptions: string[]) => void
74123
placeholder: string
@@ -77,6 +126,7 @@ interface FiltersComboboxProps {
77126
function FiltersCombobox({
78127
label,
79128
options,
129+
enabledOptions,
80130
value,
81131
onChange,
82132
placeholder,
@@ -95,12 +145,12 @@ function FiltersCombobox({
95145
<Combobox immediate multiple value={value} onChange={onChange}>
96146
<div className={clsx("flex flex-col", className)}>
97147
{label && (
98-
<Combobox.Label className="typography-menu mb-1 block font-mono font-medium uppercase text-neu-900">
148+
<Label className="typography-menu mb-1 block font-mono font-medium uppercase text-neu-900">
99149
{label}
100-
</Combobox.Label>
150+
</Label>
101151
)}
102152
<label className="relative w-full border border-neu-500 bg-neu-0 p-2 focus-within:outline-none focus-within:ring focus-within:ring-neu-300 dark:border-neu-200 dark:focus-within:ring-neu-200">
103-
<Combobox.Input
153+
<ComboboxInput
104154
value={query}
105155
onChange={e => setQuery(e.target.value)}
106156
className={clsx(
@@ -109,7 +159,7 @@ function FiltersCombobox({
109159
placeholder={placeholder}
110160
autoComplete="true"
111161
/>
112-
<Combobox.Button
162+
<ComboboxButton
113163
className={clsx(
114164
"absolute inset-y-0 right-0 flex items-center px-2 focus:outline-none",
115165
)}
@@ -118,7 +168,7 @@ function FiltersCombobox({
118168
className="ui-open:rotate-180 size-5 text-neu-400 transition-transform duration-150 group-hover:text-neu-500"
119169
aria-hidden="true"
120170
/>
121-
</Combobox.Button>
171+
</ComboboxButton>
122172
{value.length > 0 && (
123173
<div className="inset-y-0 left-0 z-[1] mt-1 flex items-center overflow-x-auto pr-8">
124174
<div className="flex flex-wrap items-center gap-1">
@@ -136,23 +186,27 @@ function FiltersCombobox({
136186
</label>
137187

138188
<div className="relative">
139-
<Combobox.Options
189+
<ComboboxOptions
140190
className={clsx(
141191
"absolute z-10 -mt-px max-h-60 w-full overflow-auto border border-neu-500 bg-neu-0 p-1 text-base",
142192
)}
143193
>
144194
{filteredOptions.map(option => (
145-
<Combobox.Option key={option} value={option}>
195+
<ComboboxOption
196+
key={option}
197+
value={option}
198+
disabled={enabledOptions ? !enabledOptions.has(option) : false}
199+
>
146200
{({ active, selected }) => (
147201
<FilterComboboxOption
148202
active={active}
149203
selected={selected}
150204
option={option}
151205
/>
152206
)}
153-
</Combobox.Option>
207+
</ComboboxOption>
154208
))}
155-
</Combobox.Options>
209+
</ComboboxOptions>
156210
</div>
157211
</div>
158212
</Combobox>
@@ -208,6 +262,7 @@ function FilterComboboxOption({
208262
className={clsx(
209263
"typography-body-sm relative flex cursor-default select-none items-center p-1 font-sans",
210264
active && "bg-neu-100 dark:bg-neu-50",
265+
"[[data-disabled]_&]:line-through [[data-disabled]_&]:opacity-40",
211266
)}
212267
>
213268
<CheckboxIcon

0 commit comments

Comments
 (0)