From b7318c8070b68da31aa86524ba352cef55c2d181 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sun, 22 Mar 2026 20:56:14 +0200 Subject: [PATCH] Front page styling tweaks (#2906) --- .../components/TournamentCard.module.css | 1 + app/features/front-page/routes/index.tsx | 144 +++++++++++------- app/styles/front.module.css | 102 ++++++++++++- e2e/sendouq.spec.ts | 2 + 4 files changed, 193 insertions(+), 56 deletions(-) diff --git a/app/features/calendar/components/TournamentCard.module.css b/app/features/calendar/components/TournamentCard.module.css index d51ed265f..1f3e7f1fc 100644 --- a/app/features/calendar/components/TournamentCard.module.css +++ b/app/features/calendar/components/TournamentCard.module.css @@ -150,6 +150,7 @@ .firstPlacers { margin-inline: auto; margin-top: var(--s-5); + margin-block-end: var(--s-4); width: max-content; } diff --git a/app/features/front-page/routes/index.tsx b/app/features/front-page/routes/index.tsx index 8d2e5de51..fd3e02603 100644 --- a/app/features/front-page/routes/index.tsx +++ b/app/features/front-page/routes/index.tsx @@ -49,39 +49,49 @@ export default function FrontPage() { ); } -function SeasonBanner() { - const { t } = useTranslation(["front"]); - const season = Seasons.next(new Date()) ?? Seasons.currentOrPrevious()!; - const _previousSeason = Seasons.previous(); +function useSeasonData() { + const season = Seasons.next() ?? Seasons.currentOrPrevious()!; + const previousSeason = Seasons.previous(); + + const isInFuture = new Date() < season.starts; + const isShowingPreviousSeason = previousSeason?.nth === season.nth; + + return { season, isInFuture, isShowingPreviousSeason }; +} + +function SeasonDates({ + season, + className, +}: { + season: ReturnType["season"]; + className: string; +}) { const isMounted = useIsMounted(); const { formatDate } = useTimeFormat(); - const isInFuture = new Date() < season.starts; - const isShowingPreviousSeason = _previousSeason?.nth === season.nth; + return isMounted ? ( +
+ {formatDate(season.starts, { month: "long", day: "numeric" })} -{" "} + {formatDate(season.ends, { month: "long", day: "numeric" })} +
+ ) : ( +
X
+ ); +} + +function SeasonBanner() { + const { t } = useTranslation(["front"]); + const { season, isInFuture, isShowingPreviousSeason } = useSeasonData(); if (isShowingPreviousSeason) return null; return ( -
+
{t("front:sq.season", { nth: season.nth })}
- {isMounted ? ( -
- {formatDate(season.starts, { - month: "long", - day: "numeric", - })}{" "} - -{" "} - {formatDate(season.ends, { - month: "long", - day: "numeric", - })} -
- ) : ( -
X
- )} + + +
+ {t("front:sq.season", { nth: season.nth })} +
+ + + + + + {isInFuture ? t("front:sq.prepare") : t("front:sq.participate")} + + + ); +} + function LeagueBanner() { const showBannerFor = import.meta.env.VITE_SHOW_BANNER_FOR_SEASON; if (!showBannerFor) return null; @@ -113,7 +150,7 @@ function LeagueBanner() { } function ResultHighlights() { - const { t } = useTranslation(["front"]); + const { t } = useTranslation(["front", "common"]); const data = useLoaderData(); // should not happen @@ -127,33 +164,21 @@ function ResultHighlights() { const season = Seasons.currentOrPrevious()!; - const recentResults = ( - <> -

- {t("front:showcase.results")} -

-
- {data.tournaments.results.map((tournament) => ( - - ))} -
- - ); - return ( <>
+
+

+ {t("common:pages.sendouq")} +

+ +

{t("front:leaderboards.topPlayers")} @@ -178,15 +203,26 @@ function ResultHighlights() { })} />

-
- {recentResults} -
-
-
- {recentResults} +
+
+

+ {t("front:showcase.results")} +

+
+ {data.tournaments.results.map((tournament) => ( + + ))} +
diff --git a/app/styles/front.module.css b/app/styles/front.module.css index f327f6269..5386754db 100644 --- a/app/styles/front.module.css +++ b/app/styles/front.module.css @@ -97,6 +97,30 @@ transition: all 0.2s ease-out; } +.seasonBannerMobileOnly { + display: flex; + flex-direction: column; + gap: var(--s-1); +} + +.seasonCardDesktopOnly { + display: none; + flex-direction: column; + gap: var(--s-2); + text-align: center; + align-items: center; +} + +@media screen and (min-width: 750px) { + .seasonBannerMobileOnly { + display: none; + } + + .seasonCardDesktopOnly { + display: flex; + } +} + .seasonBannerLink:hover svg { translate: 2px; } @@ -105,7 +129,8 @@ display: flex; gap: var(--s-2); height: 100%; - padding: var(--s-2); + padding: 0 var(--s-2) var(--s-2) var(--s-2); + overflow-x: auto; } .resultHighlights { @@ -114,6 +139,20 @@ padding: var(--s-2); } +.resultHighlights > div { + flex: 3 1 0; + width: 100%; +} + +.resultHighlights > .seasonCardDesktopOnly { + flex: 2 1 0; +} + +.resultHighlightsTop { + --card-width: 100%; + overflow-x: auto; +} + .resultHighlightsTitle { font-size: var(--font-xs); } @@ -123,9 +162,68 @@ margin-inline-start: 65px; } -.leaderboard { +.seasonCard { + --l: 50%; + min-width: var(--card-width); max-width: var(--card-width); + flex: 1; + background: linear-gradient( + to bottom, + var(--color-bg-higher), + var(--l), + var(--color-bg) + ); + border-radius: var(--radius-box); + border: var(--border-style-high); + display: flex; + flex-direction: column; + padding: var(--s-2); + position: relative; + color: var(--color-text); + overflow: hidden; + transition: --l 0.2s ease-out; +} + +.seasonCard:hover { + --l: 75%; +} + +.seasonCardHeader { + font-size: var(--font-lg); + font-weight: var(--weight-bold); + padding-block-start: var(--s-2); +} + +.seasonCardDates { + font-size: var(--font-xs); + font-weight: var(--weight-semi); + color: var(--color-text-lighter); +} + +.seasonCardImg { + position: absolute; + width: 140px; + bottom: 0; + right: 16px; +} + +.seasonCardButton { + font-size: var(--font-2xs); + color: var(--color-text); + background-color: var(--color-bg-higher); + border-radius: var(--radius-selector); + width: max-content; + height: var(--selector-size); + display: flex; + gap: var(--s-1); + padding: var(--s-0-5) var(--s-1-5); +} + +.leaderboard { + width: 100%; + min-width: 14rem; + max-width: var(--card-width); background-color: var(--color-bg-higher); border-radius: var(--radius-box); display: flex; diff --git a/e2e/sendouq.spec.ts b/e2e/sendouq.spec.ts index bade23e1c..c6ba44d2c 100644 --- a/e2e/sendouq.spec.ts +++ b/e2e/sendouq.spec.ts @@ -98,6 +98,8 @@ test.describe("SendouQ", () => { test("Challenge flow - send challenge, report match, seasons page, quick rejoin with replay", async ({ page, }) => { + test.slow(); + await seed(page); // DEFAULT seed includes full groups for ADMIN and NZAP await impersonate(page, ADMIN_ID);