Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 23 additions & 21 deletions src/client/components/LobbyCard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ export function trustRequiredDialog(
* and a bottom bar naming the map and mode.
*/

/**
* One class for both of the top row's pills so they can't drift apart. Keep
* them direct flex children of the row: wrapped in a block, a pill picks up a
* line box and renders 4px short and 2px low.
*/
const CARD_PILL_CLASS =
"inline-block px-2 py-1 rounded text-xs font-bold tracking-widest bg-malibu-blue text-white";

/**
* Aspect ratios keyed by map, loaded lazily from each map's manifest. Shared
* so the second component to render a map doesn't refetch it.
Expand Down Expand Up @@ -168,9 +176,9 @@ export function lobbyCard({
lobby.gameConfig?.publicGameModifiers,
lobby.gameConfig?.doomsdayClock?.speed,
);
// Sort by length for visual consistency (shorter labels first)
// Longest first: on a short card the pills that say the most stay legible.
if (modifierLabels.length > 1) {
modifierLabels.sort((a, b) => a.length - b.length);
modifierLabels.sort((a, b) => b.length - a.length);
}

const trustedOnly = lobby.gameConfig?.trusted === true;
Expand All @@ -180,16 +188,15 @@ export function lobbyCard({
@click=${onClick}
?disabled=${disabled}
aria-disabled=${blocked}
class="group relative w-full ${heightClass} text-white uppercase rounded-2xl transition-all duration-200 hover:scale-[1.02] active:scale-[0.98] bg-surface hover:shadow-[var(--shadow-lobby-card-hover)] ${disabled
class="group relative w-full ${heightClass} text-white uppercase rounded-2xl overflow-hidden transition-all duration-200 hover:scale-[1.02] active:scale-[0.98] bg-surface hover:shadow-[var(--shadow-lobby-card-hover)] ${disabled
? "opacity-50 cursor-not-allowed pointer-events-none"
: blocked
? "opacity-50 cursor-not-allowed"
: ""}"
>
<!-- Image clipped separately so overflow-hidden doesn't block absolute children -->
<div
class="absolute inset-0 rounded-2xl overflow-hidden pointer-events-none"
>
<!-- The card is the only rounded, clipping box: a radius on this layer
and on the name bar too drew a rim along the corners. -->
<div class="absolute inset-0 pointer-events-none">
${mapImageSrc
? html`<img
src="${mapImageSrc}"
Expand All @@ -206,30 +213,25 @@ export function lobbyCard({
class="absolute inset-x-2 top-2 flex items-start justify-between gap-2"
>
${modifierLabels.length > 0
? html`<div
class="flex flex-col items-start gap-1 mt-[2px] min-w-0 max-w-[65%]"
>
? html`<div class="flex flex-col items-start gap-1 min-w-0">
${modifierLabels.map(
(label) =>
html`<span
class="px-2 py-1 rounded text-xs font-bold uppercase tracking-widest bg-malibu-blue text-white shadow-[var(--shadow-malibu-blue-pill)]"
html`<span class="${CARD_PILL_CLASS} uppercase"
>${label}</span
>`,
)}
</div>`
: html`<div></div>`}
<div class="shrink-0">
<span
class="text-xs font-bold tracking-widest ${timeDisplayUppercase
? "uppercase"
: "normal-case"} bg-malibu-blue text-white px-2 py-1 rounded"
>${timeDisplay}</span
>
</div>
<span
class="${CARD_PILL_CLASS} shrink-0 ${timeDisplayUppercase
? "uppercase"
: "normal-case"}"
>${timeDisplay}</span
>
</div>
<!-- Bottom bar: map name + mode, with player count floating above -->
<div
class="absolute bottom-0 left-0 right-0 flex flex-col px-3 py-2 bg-black/55 backdrop-blur-sm rounded-b-2xl ${trustedOnly
class="absolute bottom-0 left-0 right-0 flex flex-col px-3 py-2 bg-black/55 backdrop-blur-sm ${trustedOnly
? "pr-10"
: ""}"
style="overflow: visible;"
Expand Down
Loading