Skip to content

Commit b69b505

Browse files
feat: update tickets and mobile schedule
1 parent 9a0c6e5 commit b69b505

7 files changed

Lines changed: 186 additions & 75 deletions

File tree

src/components/header.tsx

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { Box, Container, Flex, NavLink } from "theme-ui";
22

3+
import { genericInformation } from "~/data/generic";
4+
35
import { Logo } from "./logo";
46

57
type LinkComponent = React.FC<{ href: string; children: React.ReactNode }>;
@@ -132,8 +134,47 @@ export const Header = () => (
132134
<MenuLink href="#venue">Venue 🏰</MenuLink>
133135
<MenuLink href="#sponsors">Sponsors 💛</MenuLink>
134136
<MenuLink href="#coc">CoC 💂</MenuLink>
135-
<MenuButton href="#">Tickets coming soon 🎫</MenuButton>
137+
<MenuButton href={genericInformation.ticketsUrl}>
138+
Buy tickets 🎫
139+
</MenuButton>
136140
</Flex>
137141
</Container>
138142
</Box>
139143
);
144+
145+
export const FloatingTicketsButton = () => (
146+
<NavLink
147+
href={genericInformation.ticketsUrl}
148+
target="_blank"
149+
rel="noopener noreferrer"
150+
sx={{
151+
position: "fixed",
152+
right: ["1.2rem", "2rem"],
153+
bottom: ["1.2rem", "2rem"],
154+
zIndex: 20,
155+
display: "inline-flex",
156+
alignItems: "center",
157+
justifyContent: "center",
158+
minWidth: ["13.6rem", "16rem"],
159+
px: ["1.6rem", "2.4rem"],
160+
py: ["1rem", "1.2rem"],
161+
border: "1px solid white",
162+
borderRadius: "10rem",
163+
background: "primary",
164+
boxShadow: "0.6rem 0.4rem 2.4rem -0.8rem rgba(25, 0, 0, 0.5)",
165+
color: "white",
166+
fontSize: ["smallBody", "body"],
167+
fontWeight: "bold",
168+
textAlign: "center",
169+
transition: `transform 0.3s cubic-bezier(0.165, 0.84, 0.44, 1),
170+
box-shadow 0.3s cubic-bezier(0.165, 0.84, 0.44, 1)`,
171+
"&:hover, &:focus": {
172+
color: "white",
173+
transform: "translateY(-0.2rem)",
174+
boxShadow: "0.8rem 0.6rem 3rem -0.8rem rgba(25, 0, 0, 0.6)",
175+
},
176+
}}
177+
>
178+
Buy tickets 🎫
179+
</NavLink>
180+
);

src/components/image.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export const Image: React.FC<Props> = ({
2121
height,
2222
objectFit,
2323
layout,
24+
sx,
2425
className,
2526
}) => {
2627
let finalWidth = width;
@@ -34,7 +35,7 @@ export const Image: React.FC<Props> = ({
3435
<img
3536
src={src}
3637
alt={alt}
37-
sx={{ width: finalWidth, height: finalHeight, objectFit }}
38+
sx={{ width: finalWidth, height: finalHeight, objectFit, ...sx }}
3839
className={className}
3940
/>
4041
);

src/components/schedule-card.tsx

Lines changed: 106 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -42,60 +42,83 @@ const TalkCard: React.FC<{
4242
return (
4343
<Card
4444
sx={{
45-
minHeight: "12.8rem",
45+
minHeight: ["auto", "12.8rem"],
4646
border: schedule.isKeynote ? ".3rem solid #ed4337" : undefined,
47-
boxShadow: schedule.isKeynote
48-
? "0 8px 32px -12px #ed4337"
49-
: undefined,
47+
borderRadius: ["3.2rem", "10rem"],
48+
boxShadow: schedule.isKeynote ? "0 8px 32px -12px #ed4337" : undefined,
5049
p: photos.length
5150
? [
52-
"3.2rem 4rem 2rem",
51+
"3rem 1.5rem 1.5rem",
5352
invert ? "2rem 17rem 2rem 10rem" : "2rem 10rem 2rem 17rem",
5453
]
55-
: ["2rem 4rem", "2rem 10rem"],
54+
: ["2.4rem 1.5rem 1.5rem", "2rem 10rem"],
5655
}}
5756
>
5857
{photos.length > 0 && (
5958
<Box
6059
sx={{
6160
position: "absolute",
62-
top: [0, "50%"],
63-
left: invert ? ["50%", "auto"] : ["50%", 0],
64-
right: invert ? ["50%", 0] : "auto",
65-
transform: ["translate(-50%,-75%) scale(1)", "translateY(-50%)"],
66-
display: "flex",
61+
top: "50%",
62+
left: invert ? "auto" : 0,
63+
right: invert ? 0 : "auto",
64+
transform: "translateY(-50%)",
65+
display: ["none", "flex"],
6766
alignItems: "center",
6867
justifyContent: "center",
69-
width: photos.length > 1 ? ["10rem", "14.4rem"] : undefined,
70-
height: photos.length > 1 ? ["10rem", "14.4rem"] : undefined,
68+
width: photos.length > 1 ? "14.4rem" : undefined,
69+
height: photos.length > 1 ? "14.4rem" : undefined,
7170
}}
7271
>
7372
{photos.map((photo, index) => (
7473
<Avatar
7574
key={photo}
7675
src={photo}
7776
sx={{
78-
width: photos.length > 1 ? ["6rem", "10rem"] : undefined,
79-
height: photos.length > 1 ? ["6rem", "10rem"] : undefined,
77+
width: photos.length > 1 ? "10rem" : "14.4rem",
78+
height: photos.length > 1 ? "10rem" : "14.4rem",
8079
position: photos.length > 1 ? "absolute" : undefined,
8180
top:
82-
photos.length > 1
83-
? index === 0
84-
? ["0.4rem", "0"]
85-
: ["3.6rem", "4.4rem"]
86-
: undefined,
81+
photos.length > 1 ? (index === 0 ? 0 : "4.4rem") : undefined,
8782
left:
88-
photos.length > 1
89-
? index === 0
90-
? ["0.4rem", "0"]
91-
: ["3.6rem", "4.4rem"]
92-
: undefined,
83+
photos.length > 1 ? (index === 0 ? 0 : "4.4rem") : undefined,
9384
zIndex: photos.length - index,
9485
border: photos.length > 1 ? ".4rem solid white" : undefined,
9586
boxShadow:
96-
photos.length > 1
97-
? "2px 8px 24px -8px #ed4337"
98-
: undefined,
87+
photos.length > 1 ? "2px 8px 24px -8px #ed4337" : undefined,
88+
}}
89+
/>
90+
))}
91+
</Box>
92+
)}
93+
94+
{photos.length > 0 && (
95+
<Box
96+
sx={{
97+
display: ["flex", "none"],
98+
alignItems: "center",
99+
justifyContent: "center",
100+
width: photos.length > 1 ? "7.2rem" : undefined,
101+
height: photos.length > 1 ? "7.2rem" : undefined,
102+
mb: "1rem",
103+
position: "relative",
104+
}}
105+
>
106+
{photos.map((photo, index) => (
107+
<Avatar
108+
key={photo}
109+
src={photo}
110+
sx={{
111+
width: photos.length > 1 ? "4.8rem" : "6.4rem",
112+
height: photos.length > 1 ? "4.8rem" : "6.4rem",
113+
position: photos.length > 1 ? "absolute" : undefined,
114+
top:
115+
photos.length > 1 ? (index === 0 ? 0 : "2.4rem") : undefined,
116+
left:
117+
photos.length > 1 ? (index === 0 ? 0 : "2.4rem") : undefined,
118+
zIndex: photos.length - index,
119+
border: photos.length > 1 ? ".3rem solid white" : undefined,
120+
boxShadow:
121+
photos.length > 1 ? "2px 8px 24px -8px #ed4337" : undefined,
99122
}}
100123
/>
101124
))}
@@ -107,8 +130,10 @@ const TalkCard: React.FC<{
107130
sx={{
108131
mt: 0,
109132
mb: ["1rem", ".5rem"],
110-
fontSize: "body",
133+
fontSize: ["1.7rem", "body"],
134+
lineHeight: ["1.25", "heading"],
111135
color: "text",
136+
overflowWrap: "break-word",
112137
}}
113138
>
114139
{schedule.title}
@@ -119,8 +144,9 @@ const TalkCard: React.FC<{
119144
display: "flex",
120145
justifyContent: "center",
121146
gap: ".75rem",
147+
rowGap: ".35rem",
122148
flexWrap: "wrap",
123-
fontSize: ["smallBody", "body"],
149+
fontSize: ["1.35rem", "body"],
124150
}}
125151
>
126152
{schedule.isKeynote && (
@@ -145,6 +171,7 @@ const TalkCard: React.FC<{
145171
alignItems: "center",
146172
justifyContent: "center",
147173
gap: ".4rem",
174+
flexWrap: "wrap",
148175
}}
149176
>
150177
{speaker.name}
@@ -184,7 +211,8 @@ const TalkCard: React.FC<{
184211
const InfoCard: React.FC<{ schedule: Props["schedule"] }> = ({ schedule }) => (
185212
<Card
186213
sx={{
187-
p: "2rem 10rem",
214+
p: ["1.5rem 1.25rem", "2rem 10rem"],
215+
borderRadius: ["2.4rem", "10rem"],
188216
backgroundColor: "primary",
189217
color: "white",
190218
backgroundImage: `linear-gradient(
@@ -211,7 +239,7 @@ const InfoCard: React.FC<{ schedule: Props["schedule"] }> = ({ schedule }) => (
211239
>
212240
<Text
213241
sx={{
214-
fontSize: "body",
242+
fontSize: ["smallBody", "body"],
215243
}}
216244
>
217245
{schedule.label}
@@ -223,39 +251,50 @@ export const ScheduleCard: React.FC<Props> = ({
223251
variant = "talk",
224252
invert = false,
225253
schedule,
226-
}) => (
227-
<Box
228-
sx={{
229-
position: "relative",
230-
mt: variant === "talk" ? ["9rem", "primary"] : "primary",
231-
}}
232-
>
233-
{variant === "talk" && <TalkCard schedule={schedule} invert={invert} />}
234-
{variant === "info" && <InfoCard schedule={schedule} />}
254+
}) => {
255+
const hasPhotos = Boolean(
256+
schedule.speakerIds?.some((id) => SPEAKERS[id]?.image),
257+
);
235258

236-
{formatTimeRange(schedule) && (
237-
<Text
238-
key="when"
239-
sx={{
240-
position: "absolute",
241-
zIndex: 1,
242-
top: 0,
243-
left: "50%",
244-
transform: "translate(-50%, -50%)",
245-
px: "1rem",
246-
py: ".35rem",
247-
borderRadius: "999px",
248-
backgroundColor: variant === "info" ? "white" : "primary",
249-
boxShadow: "0 4px 16px -8px #464444",
250-
color: variant === "info" ? "primary" : "white",
251-
fontFamily: "heading",
252-
fontSize: "smallBody",
253-
lineHeight: 1,
254-
whiteSpace: "nowrap",
255-
}}
256-
>
257-
{formatTimeRange(schedule)}
258-
</Text>
259-
)}
260-
</Box>
261-
);
259+
return (
260+
<Box
261+
sx={{
262+
position: "relative",
263+
mt:
264+
variant === "talk"
265+
? hasPhotos
266+
? ["3.2rem", "primary"]
267+
: ["3rem", "primary"]
268+
: ["3rem", "primary"],
269+
}}
270+
>
271+
{variant === "talk" && <TalkCard schedule={schedule} invert={invert} />}
272+
{variant === "info" && <InfoCard schedule={schedule} />}
273+
274+
{formatTimeRange(schedule) && (
275+
<Text
276+
key="when"
277+
sx={{
278+
position: "absolute",
279+
zIndex: 1,
280+
top: 0,
281+
left: "50%",
282+
transform: "translate(-50%, -50%)",
283+
px: [".75rem", "1rem"],
284+
py: ".35rem",
285+
borderRadius: "999px",
286+
backgroundColor: variant === "info" ? "white" : "primary",
287+
boxShadow: "0 4px 16px -8px #464444",
288+
color: variant === "info" ? "primary" : "white",
289+
fontFamily: "heading",
290+
fontSize: ["1.35rem", "smallBody"],
291+
lineHeight: 1,
292+
whiteSpace: "nowrap",
293+
}}
294+
>
295+
{formatTimeRange(schedule)}
296+
</Text>
297+
)}
298+
</Box>
299+
);
300+
};

src/data/generic.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ export const genericInformation = {
55
subHeading: "PJAIT building A, Koszykowa 86, Warsaw, Poland",
66
whenDatetime: "2026/05/09 10:00 AM UTC+2",
77
whenFormat: "do MMMM y",
8+
ticketsUrl: "https://pretix.eu/europython/warsaw-python-pizza/",
89
};

src/pages/index.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Head from "next/head";
22
import { Box } from "theme-ui";
33

44
import { Footer } from "~/components/footer";
5-
import { Header } from "~/components/header";
5+
import { FloatingTicketsButton, Header } from "~/components/header";
66
import { genericInformation } from "~/data/generic";
77
import { About } from "~/sections/about";
88
import { CFP_Closed } from "~/sections/cfp_closed";
@@ -64,6 +64,13 @@ const Home = () => (
6464
url: "https://forms.gle/5pqj68ES9ENaGPBf6",
6565
availabilityEnds: "2026-04-12",
6666
},
67+
offers: {
68+
"@type": "Offer",
69+
name: "Tickets",
70+
url: genericInformation.ticketsUrl,
71+
availability: "https://schema.org/InStock",
72+
validFrom: "2026-04-27",
73+
},
6774
hasSponsorshipOffer: {
6875
"@type": "Offer",
6976
name: "Sponsor Packages",
@@ -74,6 +81,7 @@ const Home = () => (
7481
/>
7582
</Head>
7683
<Header />
84+
<FloatingTicketsButton />
7785
<Hero />
7886
<About />
7987
{/*<SpeakersSection />*/}

src/sections/cfp_closed.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ export const CFP_Closed = () => (
88
Proposals submission is now closed
99
</AnchorHeading>
1010
<Paragraph>
11-
We would like to thank everyone who submitted their proposals! We are now
12-
compiling the final version of the event schedule.
11+
We would like to thank everyone who submitted their proposals! We have
12+
already created the final version of the event schedule.
1313
</Paragraph>
1414
</Container>
1515
);

0 commit comments

Comments
 (0)