feat(landing): slim status section, hero, and server-card icon
- Remove the stat-grid from the status section (server card only); prune the now-orphaned site.stats, MOD_COUNT_KEY, statLabels (3 locales), and .stat-grid/.tile CSS. - Empty-roster message -> "Nobody online", now localized (status.empty in en/es/eu) and wired to both ServerCard instances. - Flatten the server-card icon (drop the inset emboss bevel on .sc-icon). - Drop "Solo LAN" (hero metaLan) from the hero meta row; prune metaLan (3 locales). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
// loaded via ./data/mods.ts (resilient: missing file → empty list, build never
|
||||
// fails). Flat alphabetical grid: extracted logo (or a pixel placeholder) +
|
||||
// pretty name + version. description is exposed as a tooltip. No categories, no
|
||||
// external links. Tiles share the MC-GUI bevel treatment used by .feat/.tile.
|
||||
// external links. Tiles share the MC-GUI bevel treatment used by .feat.
|
||||
import { MODS } from "../data/mods";
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -29,7 +29,7 @@ const {
|
||||
upTo,
|
||||
onlineLabel = "Online",
|
||||
offlineLabel = "Offline",
|
||||
emptyLabel = "Nobody online — be the first.",
|
||||
emptyLabel = "Nobody online",
|
||||
} = Astro.props;
|
||||
|
||||
const { status, avatarUrl, avatarMode } = site;
|
||||
@@ -98,7 +98,6 @@ const { status, avatarUrl, avatarMode } = site;
|
||||
width: 72px; height: 72px; flex-shrink: 0;
|
||||
display: grid; place-items: center; position: relative;
|
||||
background: var(--bg-2);
|
||||
box-shadow: inset 2px 2px 0 var(--bevel-lo), inset -2px -2px 0 var(--bevel-hi);
|
||||
}
|
||||
.sc-favicon { width: 64px; height: 64px; image-rendering: pixelated; }
|
||||
.sc-creeper img { width: 56px; height: 56px; }
|
||||
@@ -207,7 +206,7 @@ const { status, avatarUrl, avatarMode } = site;
|
||||
players.hidden = false;
|
||||
if (real.length === 0) {
|
||||
if (emptyEl) {
|
||||
emptyEl.textContent = empty ?? "Nobody online.";
|
||||
emptyEl.textContent = empty ?? "Nobody online";
|
||||
emptyEl.hidden = false;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -5,15 +5,9 @@
|
||||
// @ts-ignore — node builtins (no @types/node in this Astro SSG; same reason
|
||||
// `process` below is untyped). Used only at build time to read the manifest.
|
||||
import { readFileSync } from "node:fs";
|
||||
import { MODS } from "./mods";
|
||||
|
||||
const BASE_DOMAIN = process.env.BASE_DOMAIN ?? "ulicraft.local";
|
||||
|
||||
// Installed-pack mod count, fed by tooling/build-modlist.py via mods.json (see
|
||||
// ./mods.ts). Feeds the homepage "Mods" stat tile. When the generated catalogue
|
||||
// is absent/empty (fresh checkout), fall back to the honest "50+" estimate.
|
||||
const MOD_COUNT_KEY = MODS.count > 0 ? `${MODS.count}` : "50+";
|
||||
|
||||
// NMSR render mode for avatar tiles. AVATAR_MODE is the ServerCard online row +
|
||||
// account preview (heads); ROSTER_AVATAR_MODE is the Members grid (full body by
|
||||
// default). Read at build time, same as BASE_DOMAIN. e.g. "headiso" | "head" |
|
||||
@@ -183,15 +177,6 @@ export const site = {
|
||||
rosterApi: `/api/mcstatus/players`,
|
||||
},
|
||||
|
||||
// Honest stat tiles. Keys (numbers/versions) are language-neutral; labels
|
||||
// come from ui.ts (same order).
|
||||
stats: [
|
||||
{ key: MOD_COUNT_KEY },
|
||||
{ key: MC_VERSION },
|
||||
{ key: "10" },
|
||||
{ key: "6h" },
|
||||
],
|
||||
|
||||
// Feature cards. glyph ∈ shield|diamond|orb|heart; gold = gold pixel fill.
|
||||
// Text (h/p) comes from ui.ts (same order).
|
||||
features: [
|
||||
|
||||
@@ -43,7 +43,6 @@ export interface UI {
|
||||
copyIp: string;
|
||||
howToJoin: string;
|
||||
metaModpack: string;
|
||||
metaLan: string;
|
||||
};
|
||||
status: {
|
||||
eyebrow: string;
|
||||
@@ -52,8 +51,8 @@ export interface UI {
|
||||
modded: string;
|
||||
motd: string;
|
||||
upTo: string;
|
||||
empty: string; // shown on the ServerCard when nobody is online
|
||||
};
|
||||
statLabels: [string, string, string, string];
|
||||
members: {
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
@@ -194,7 +193,6 @@ export const ui: Record<Lang, UI> = {
|
||||
copyIp: "Copy IP",
|
||||
howToJoin: "How to Join",
|
||||
metaModpack: "NeoForge modpack",
|
||||
metaLan: "LAN-only",
|
||||
},
|
||||
status: {
|
||||
eyebrow: "Server",
|
||||
@@ -203,8 +201,8 @@ export const ui: Record<Lang, UI> = {
|
||||
modded: "Modded",
|
||||
motd: "NeoForge modpack · Simple Voice Chat · LAN-only",
|
||||
upTo: "up to",
|
||||
empty: "Nobody online",
|
||||
},
|
||||
statLabels: ["Mods", "NeoForge", "Player slots", "World backups"],
|
||||
members: {
|
||||
eyebrow: "El valle",
|
||||
title: "Who's on the server.",
|
||||
@@ -376,7 +374,6 @@ export const ui: Record<Lang, UI> = {
|
||||
copyIp: "Copiar IP",
|
||||
howToJoin: "Cómo entrar",
|
||||
metaModpack: "Pack NeoForge",
|
||||
metaLan: "Solo LAN",
|
||||
},
|
||||
status: {
|
||||
eyebrow: "Servidor",
|
||||
@@ -385,8 +382,8 @@ export const ui: Record<Lang, UI> = {
|
||||
modded: "Con mods",
|
||||
motd: "Pack NeoForge · Simple Voice Chat · Solo LAN",
|
||||
upTo: "hasta",
|
||||
empty: "No hay nadie conectado",
|
||||
},
|
||||
statLabels: ["Mods", "NeoForge", "Plazas", "Copias del mundo"],
|
||||
members: {
|
||||
eyebrow: "El valle",
|
||||
title: "Quién está en el servidor.",
|
||||
@@ -558,7 +555,6 @@ export const ui: Record<Lang, UI> = {
|
||||
copyIp: "Kopiatu IPa",
|
||||
howToJoin: "Nola sartu",
|
||||
metaModpack: "NeoForge packa",
|
||||
metaLan: "LAN soilik",
|
||||
},
|
||||
status: {
|
||||
eyebrow: "Zerbitzaria",
|
||||
@@ -567,8 +563,8 @@ export const ui: Record<Lang, UI> = {
|
||||
modded: "Mod-duna",
|
||||
motd: "NeoForge packa · Simple Voice Chat · LAN soilik",
|
||||
upTo: "gehienez",
|
||||
empty: "Inor ez dago konektatuta",
|
||||
},
|
||||
statLabels: ["Modak", "NeoForge", "Plazak", "Munduaren babeskopiak"],
|
||||
members: {
|
||||
eyebrow: "El valle",
|
||||
title: "Nor dago zerbitzarian.",
|
||||
|
||||
@@ -111,8 +111,6 @@ const dustBits = Array.from({ length: 16 }, (_, i) => {
|
||||
<span>Java {site.mcVersion}</span>
|
||||
<span class="dot"></span>
|
||||
<span>{t.hero.metaModpack}</span>
|
||||
<span class="dot"></span>
|
||||
<span>{t.hero.metaLan}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hero-status">
|
||||
@@ -120,6 +118,7 @@ const dustBits = Array.from({ length: 16 }, (_, i) => {
|
||||
modded={t.status.modded}
|
||||
motd={t.status.motd}
|
||||
upTo={t.status.upTo}
|
||||
emptyLabel={t.status.empty}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -178,16 +177,9 @@ const dustBits = Array.from({ length: 16 }, (_, i) => {
|
||||
modded={t.status.modded}
|
||||
motd={t.status.motd}
|
||||
upTo={t.status.upTo}
|
||||
emptyLabel={t.status.empty}
|
||||
/>
|
||||
</div>
|
||||
<div class="stat-grid">
|
||||
{site.stats.map((s, i) => (
|
||||
<div class="tile reveal" style={`transition-delay:${i * 60}ms`}>
|
||||
<div class="k">{s.key}</div>
|
||||
<div class="l">{t.statLabels[i]}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -472,22 +472,6 @@ section { position: relative; z-index: 1; }
|
||||
.bars i:nth-child(4){height:85%}
|
||||
.bars i:nth-child(5){height:100%}
|
||||
|
||||
/* stat tiles */
|
||||
.stat-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 16px;
|
||||
margin-top: 28px;
|
||||
}
|
||||
.tile {
|
||||
background: var(--surface);
|
||||
padding: 22px;
|
||||
box-shadow: inset 2px 2px 0 var(--bevel-hi), inset -2px -2px 0 var(--bevel-lo);
|
||||
}
|
||||
.tile .k { font-family: var(--font-head); font-weight: 600; font-size: 38px; color: var(--text); line-height: 1; font-variant-numeric: tabular-nums; }
|
||||
.tile .k .u { color: var(--accent); font-size: 22px; }
|
||||
.tile .l { margin-top: 8px; color: var(--dim); font-size: 13px; letter-spacing: 0.04em; text-transform: uppercase; font-family: var(--font-pixel); font-size: 9px; line-height: 1.8; }
|
||||
|
||||
/* ============================================================
|
||||
PLAYER ROSTER (shared avatar tiles)
|
||||
Used by ServerCard.astro (online row) and PlayerRoster.astro
|
||||
@@ -650,7 +634,6 @@ section { position: relative; z-index: 1; }
|
||||
:root[data-head="8bit"] .step .num { font-size: 30px; }
|
||||
:root[data-head="8bit"] .feat h3 { font-size: 15px; line-height: 1.4; }
|
||||
:root[data-head="8bit"] .serverlist .title { font-size: 16px; }
|
||||
:root[data-head="8bit"] .tile .k { font-size: 26px; }
|
||||
:root[data-head="8bit"] .ip-chip button { font-size: 12px; }
|
||||
:root[data-head="8bit"] .live-pill { font-size: 12px; }
|
||||
|
||||
@@ -733,7 +716,6 @@ section { position: relative; z-index: 1; }
|
||||
@media (max-width: 880px) {
|
||||
:root[data-hero="split"] .hero-grid { grid-template-columns: 1fr; }
|
||||
:root[data-hero="split"] .hero-status { display: block; }
|
||||
.stat-grid { grid-template-columns: repeat(2, 1fr); }
|
||||
.feat-grid { grid-template-columns: 1fr; }
|
||||
.nav-links { display: none; }
|
||||
.serverlist { flex-wrap: wrap; }
|
||||
@@ -743,5 +725,4 @@ section { position: relative; z-index: 1; }
|
||||
.step { grid-template-columns: 1fr; gap: 18px; }
|
||||
.step .num { width: 64px; height: 64px; font-size: 32px; }
|
||||
.ip-chip .ip-val { font-size: 22px; }
|
||||
.stat-grid { grid-template-columns: 1fr 1fr; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user