diff --git a/2024/src/components/RoomLegend.tsx b/2024/src/components/RoomLegend.tsx index 66a66082..87cb480c 100644 --- a/2024/src/components/RoomLegend.tsx +++ b/2024/src/components/RoomLegend.tsx @@ -16,11 +16,25 @@ const Box = styled.div` gap: 1em; } ` + +const RoomBoxContainer = styled.div` + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 1em; + + ${({ theme }) => theme.breakpoints.mobile} { + align-items: flex-start; + gap: 0; + } +` + const RoomBox = styled(InlineLink)<{ disabled: boolean }>` flex: 1; display: flex; flex-direction: row; align-items: center; + ${({ disabled }) => disabled ? ` @@ -66,10 +80,32 @@ const SubText = styled.span` margin-top: -0.1rem; font-family: ${({ theme }) => theme.fonts.text}; ` + +const StreamLink = styled.a<{ track: Rooms }>` + display: block; + font-size: 1.6rem; + margin-top: 1rem; + text-align: left; + font-family: ${({ theme }) => theme.fonts.text}; + + color: ${({ theme }) => theme.colors.text}; + text-decoration-color: ${({ track, theme }) => + theme.colors[`room${track}Border`]}; + + &:hover { + color: ${({ track, theme }) => theme.colors[`room${track}Border`]}; + } + + @media print { + display: none; + } +` + const TextBox = styled.div` display: flex; flex-direction: column; justify-items: center; + align-items: center; ` type RoomProps = { @@ -78,22 +114,42 @@ type RoomProps = { } export const Room = ({ track, "selected-track": selectedTrack }: RoomProps) => { + function getTrackLink(track: Rooms) { + switch (track) { + case "A": + return "https://youtube.com/live/ew1zmA7y9q8" + case "B": + return "https://youtube.com/live/2BXwigWGjWQ" + case "C": + return "https://youtube.com/live/E3yTtaGr7V8" + case "D": + return "https://youtube.com/live/5Wt0r5vHOwQ" + } + } + const { t } = useTranslation() return ( - - - - {t(`room${track}`)} - {t(`room${track}Sub`)} - - + + + + + {t(`room${track}`)} + {t(`room${track}Sub`)} + + + + + + {t("viewStream")} + + ) } @@ -106,3 +162,4 @@ export const RoomLegend = (props: RoomLegendProps) => ( ))} ) + diff --git a/2024/src/components/StreamLinks.tsx b/2024/src/components/StreamLinks.tsx new file mode 100644 index 00000000..46006ee8 --- /dev/null +++ b/2024/src/components/StreamLinks.tsx @@ -0,0 +1,71 @@ +import React from "react" +import { useTranslation } from "react-i18next" + +import styled from "styled-components" + +const Container = styled.div` + width: 100%; + + display: flex; + flex-wrap: wrap; + gap: 40px 20px; + justify-content: center; +` + +const Button = styled.a` + display: block; + height: min-content; + + color: #000000; + font-weight: bold; + font-family: ${({ theme }) => theme.fonts.text}; + padding: 20px 30px 20px 30px; + text-decoration: none; + border: solid 2px; + + transition: transform 0.2s ease-in-out; + &:hover { + transform: scale(1.05); + } +` + +const ButtonA = styled(Button)` + background-color: ${({ theme }) => theme.colors.roomA}; + border-color: ${({ theme }) => theme.colors.roomABorder}; +` +const ButtonB = styled(Button)` + background-color: ${({ theme }) => theme.colors.roomB}; + border-color: ${({ theme }) => theme.colors.roomBBorder}; +` + +const ButtonC = styled(Button)` + background-color: ${({ theme }) => theme.colors.roomC}; + border-color: ${({ theme }) => theme.colors.roomCBorder}; +` + +const ButtonD = styled(Button)` + background-color: ${({ theme }) => theme.colors.roomD}; + border-color: ${({ theme }) => theme.colors.roomDBorder}; +` + +export const StreamLinks = () => { + const { t } = useTranslation() + + return ( + + + {t("streamLinks.trackA")} + + + {t("streamLinks.trackB")} + + + {t("streamLinks.trackC")} + + + {t("streamLinks.trackD")} + + + ) +} + diff --git a/2024/src/components/Title.tsx b/2024/src/components/Title.tsx index e82cb4fa..d1aca7a2 100644 --- a/2024/src/components/Title.tsx +++ b/2024/src/components/Title.tsx @@ -33,5 +33,26 @@ const H2 = styled.h2` export function Title(props: Props) { const { children, heading = "h1" } = props - return heading === "h1" ?

{children}

:

{children}

+ const processedChildren = React.Children.map(children, child => { + if (typeof child === "string") { + return child.split("
").map((text, i, array) => + i === array.length - 1 ? ( + text + ) : ( + <> + {text} +
+ + ), + ) + } + return child + }) + + return heading === "h1" ? ( +

{processedChildren}

+ ) : ( +

{processedChildren}

+ ) } + diff --git a/2024/src/i18n/en.ts b/2024/src/i18n/en.ts index 0591ede8..af0afe53 100644 --- a/2024/src/i18n/en.ts +++ b/2024/src/i18n/en.ts @@ -61,6 +61,12 @@ export const en = { callForSponsors: "Call For Sponsors", becomeASponsor: "Become a sponsor", sponsors: "Sponsors", + "streamLinks.title": "View track live streams", + "streamLinks.trackA": "Track A", + "streamLinks.trackB": "Track B", + "streamLinks.trackC": "Track C", + "streamLinks.trackD": "Track D", + "viewStream": "View stream", "sponsor.premium": "Premium Sponsor", "sponsor.sponsor": "Sponsor", openMobileMenu: "Open Navigation Menu", diff --git a/2024/src/i18n/ja.ts b/2024/src/i18n/ja.ts index 159957bf..faa44749 100644 --- a/2024/src/i18n/ja.ts +++ b/2024/src/i18n/ja.ts @@ -47,6 +47,12 @@ export const ja: { moreDetails: "詳細", "specified-commercial-transactions-act": "特定商取引法に基づく表示", "code-of-conduct": "行動規範", + "streamLinks.title": "トラックの
ライブ配信を見る", + "streamLinks.trackA": "トラックA", + "streamLinks.trackB": "トラックB", + "streamLinks.trackC": "トラックC", + "streamLinks.trackD": "トラックD", + "viewStream": "ライブ配信を見る", // @ts-expect-error It's not defined in en.ts Japanese: "日本語", English: "英語", diff --git a/2024/src/pages/index.tsx b/2024/src/pages/index.tsx index eef81a7d..1e08b754 100644 --- a/2024/src/pages/index.tsx +++ b/2024/src/pages/index.tsx @@ -7,6 +7,7 @@ import { SEO } from "../components/Seo" import { Hero } from "../components/Hero" import { Title } from "../components/Title" import { SpeakerList } from "../components/SpeakerList" +import { StreamLinks } from "../components/StreamLinks" import { SponsorList } from "../components/SponsorList" import { LinkButton } from "../components/LinkButton" import { Card as _Card } from "../components/Card" @@ -206,6 +207,18 @@ export default function IndexPage() { Date.now() > new Date(site.siteMetadata.sponsorDeadline).getTime() const parts = [ + { + subTitle: t("streamLinks.title"), + available: true, + render: () => ( + <> +
+ +
+ + ), + }, + { subTitle: t("speakers"), available: featuredSpeakers.length, diff --git a/2024/src/templates/schedule.tsx b/2024/src/templates/schedule.tsx index 8b786ad1..bfe20ee0 100644 --- a/2024/src/templates/schedule.tsx +++ b/2024/src/templates/schedule.tsx @@ -459,6 +459,7 @@ export default function SchedulePage({ +