From 0c2380d21d838dfbb4fbfe204bed4f6d1ff7ed37 Mon Sep 17 00:00:00 2001
From: Kalle <38327916+Sendouc@users.noreply.github.com>
Date: Thu, 13 Aug 2026 19:05:02 +0300
Subject: [PATCH] Tournament cards tweaks
Closes #2356
---
.../badges/components/BadgeDisplay.module.css | 8 +++
.../badges/components/BadgeDisplay.tsx | 4 ++
.../calendar/components/Tags.module.css | 5 ++
app/features/calendar/components/Tags.tsx | 11 +++-
.../components/TournamentCard.module.css | 51 +++--------------
.../calendar/components/TournamentCard.tsx | 57 ++++++-------------
6 files changed, 53 insertions(+), 83 deletions(-)
diff --git a/app/features/badges/components/BadgeDisplay.module.css b/app/features/badges/components/BadgeDisplay.module.css
index 733c40b7c..dd4b95e82 100644
--- a/app/features/badges/components/BadgeDisplay.module.css
+++ b/app/features/badges/components/BadgeDisplay.module.css
@@ -10,6 +10,14 @@
margin-inline: auto;
}
+.badgesCompact {
+ min-width: 0;
+ max-width: 100%;
+ min-height: 0;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
.smallBadges {
display: grid;
place-items: center;
diff --git a/app/features/badges/components/BadgeDisplay.tsx b/app/features/badges/components/BadgeDisplay.tsx
index 73852d11b..0d6547bea 100644
--- a/app/features/badges/components/BadgeDisplay.tsx
+++ b/app/features/badges/components/BadgeDisplay.tsx
@@ -17,6 +17,8 @@ export interface BadgeDisplayProps {
onChange?: (badgeIds: number[]) => void;
children?: React.ReactNode;
showText?: boolean;
+ /** Fit inside tight containers (e.g. a popover) instead of the fixed 20rem box */
+ compact?: boolean;
className?: string;
}
@@ -25,6 +27,7 @@ export function BadgeDisplay({
onChange,
children,
showText = true,
+ compact = false,
className,
}: BadgeDisplayProps) {
const { t } = useTranslation("badges");
@@ -69,6 +72,7 @@ export function BadgeDisplay({
) : null}
diff --git a/app/features/calendar/components/Tags.module.css b/app/features/calendar/components/Tags.module.css
index 8fb88b8f2..7f441a77f 100644
--- a/app/features/calendar/components/Tags.module.css
+++ b/app/features/calendar/components/Tags.module.css
@@ -32,6 +32,11 @@
color: var(--color-text-inverse);
}
+.overflowTag {
+ background-color: var(--color-bg-higher);
+ color: var(--color-text-high);
+}
+
:global(html.light) .tag {
color: var(--color-text);
}
diff --git a/app/features/calendar/components/Tags.tsx b/app/features/calendar/components/Tags.tsx
index 934e0b2f6..cc212f345 100644
--- a/app/features/calendar/components/Tags.tsx
+++ b/app/features/calendar/components/Tags.tsx
@@ -12,10 +12,13 @@ export function Tags({
onDelete,
small = false,
centered = false,
+ maxVisible,
}: {
tags: Array
;
small?: boolean;
centered?: boolean;
+ /** How many tags to show at most, rest are collapsed into a "+N" indicator. If undefined all tags are shown. */
+ maxVisible?: number;
/** Called when tag delete button clicked. If undefined delete buttons won't be shown. */
onDelete?: (tag: CalendarEventTag) => void;
@@ -24,6 +27,9 @@ export function Tags({
if (tags.length === 0) return null;
+ const visibleTags = maxVisible ? tags.slice(0, maxVisible) : tags;
+ const hiddenCount = tags.length - visibleTags.length;
+
return (
- {tags.map((tag) => (
+ {visibleTags.map((tag) => (
-
))}
+ {hiddenCount > 0 ? (
+ - +{hiddenCount}
+ ) : null}
);
}
diff --git a/app/features/calendar/components/TournamentCard.module.css b/app/features/calendar/components/TournamentCard.module.css
index da83b8317..a953530e2 100644
--- a/app/features/calendar/components/TournamentCard.module.css
+++ b/app/features/calendar/components/TournamentCard.module.css
@@ -30,6 +30,10 @@
}
}
+.cardRanked {
+ box-shadow: inset 0 -3px 0 var(--color-accent);
+}
+
.imgContainer {
background-color: var(--color-bg);
padding: var(--s-1-5);
@@ -105,19 +109,12 @@
font-weight: var(--weight-semi);
}
-.modesPillContainer {
- padding-inline-start: 12px;
-}
-
-.modesPill {
- background-color: var(--color-bg-higher);
- border-radius: var(--radius-selector);
- width: max-content;
- padding: 0 var(--s-1-5);
+.modesRow {
display: flex;
+ flex: none;
gap: var(--s-1);
- height: var(--selector-size);
align-items: center;
+ padding-inline-start: 12px;
}
.pillsContainer {
@@ -126,31 +123,6 @@
justify-content: end;
padding-inline-end: 12px;
width: 100%;
-
- &.lonely {
- padding-inline-end: 0px;
- padding-inline-start: 12px;
- }
-}
-
-.pill {
- font-size: var(--font-2xs);
- font-weight: var(--weight-bold);
- border-radius: var(--radius-selector);
- height: var(--selector-size);
- padding: 0 var(--s-1-5);
- display: grid;
- place-items: center;
-}
-
-.pillRanked {
- background-color: var(--color-info-low);
- color: var(--color-text-accent);
-
- & svg {
- width: var(--tournament-card-icon-size);
- height: var(--tournament-card-icon-size);
- }
}
.firstPlacers {
@@ -172,11 +144,6 @@
min-width: 16px;
}
-.badgeDisplay {
- min-width: initial;
- min-height: initial;
-}
-
.vodIndicator {
font-size: var(--font-2xs);
font-weight: var(--weight-bold);
@@ -196,9 +163,7 @@
}
.badgePill {
- background-color: var(--color-bg-higher);
- border-radius: var(--radius-selector);
- padding: 0 var(--s-1-5);
+ padding: 0 var(--s-1);
height: var(--selector-size);
}
diff --git a/app/features/calendar/components/TournamentCard.tsx b/app/features/calendar/components/TournamentCard.tsx
index ad2d219a0..3428066eb 100644
--- a/app/features/calendar/components/TournamentCard.tsx
+++ b/app/features/calendar/components/TournamentCard.tsx
@@ -1,5 +1,5 @@
import clsx from "clsx";
-import { ShieldMinus, Trophy as TrophyIcon, Users } from "lucide-react";
+import { ShieldMinus, Users } from "lucide-react";
import { useTranslation } from "react-i18next";
import { Link } from "react-router";
import { SendouButton } from "~/components/elements/Button";
@@ -13,7 +13,6 @@ import { Trophy } from "~/features/trophies/components/Trophy";
import { useFormatDistanceToNow } from "~/hooks/intl/useFormatDistanceToNow";
import { useHydrated } from "~/hooks/useHydrated";
import { useSpoilerFree } from "~/hooks/useSpoilerFree";
-import { rankedModesShort } from "~/modules/in-game-lists/modes";
import { databaseTimestampToDate } from "~/utils/dates";
import { navIconUrl } from "~/utils/urls";
import type { CalendarEvent, ShowcaseCalendarEvent } from "../calendar-types";
@@ -37,7 +36,7 @@ export function TournamentCard({
const isCalendar = tournament.type === "calendar";
const isHostedOnSendouInk = typeof tournament.isRanked === "boolean";
const modes =
- tournament.modes && !isDefaultModes(tournament.modes)
+ isCalendar && tournament.modes && tournament.modes.length > 0
? tournament.modes
: null;
@@ -53,7 +52,12 @@ export function TournamentCard({
})}
data-testid="tournament-card"
>
-
+
{tournament.logoUrl ? (
@@ -121,7 +125,7 @@ export function TournamentCard({
) : null}
{isCalendar ? (
-
+
) : null}
{isShowcase && tournament.firstPlacers.length > 0 ? (
@@ -140,17 +144,8 @@ export function TournamentCard({
{isShowcase && "hasVods" in tournament && tournament.hasVods ? (
📺 VODs
) : null}
- {modes ?
: null}
-
- {tournament.isRanked ? (
-
-
-
- ) : null}
+ {modes ?
: null}
+
{isCalendar &&
(tournament.trophy ||
(tournament.badges && tournament.badges.length > 0)) ? (
@@ -315,16 +310,12 @@ function ParticipantsPill({
);
}
-function ModesPill({ modes }: { modes: NonNullable
}) {
- const size = 16;
-
+function ModesRow({ modes }: { modes: NonNullable }) {
return (
-
-
- {modes.map((mode) => (
-
- ))}
-
+
+ {modes.map((mode) => (
+
+ ))}
);
}
@@ -345,7 +336,7 @@ function PrizesPill({
className={styles.badgePill}
>
) : badges ? (
-
+
) : null}
);
}
-
-/** Modes pill is only interesting when the tournament deviates from the standard ranked modes */
-function isDefaultModes(modes: NonNullable
) {
- return (
- modes.length === rankedModesShort.length &&
- rankedModesShort.every((mode) => modes.includes(mode))
- );
-}