Revamp CommonwealthOnline browser UI and styles

Rework the CommonwealthOnline browser UI: restructure HTML into a nav + subpanel layout, add SVG/PNG/font assets and new sprites, and overhaul styles with a new font-face and refreshed color/spacing variables. Refactor components: tabs use a left nav list; filters extraction (renderRow) and reset focus handling; direct-connect renders into a dedicated container; server-list switched to compact row layout and adds a scroll indicator; server-details now uses a preview area and simplified preview/stats rendering. Update app logic: adjust focus zone handling (nextFocusZone), limit zones per tab, update connection status/count display, and avoid rendering details for direct-connect. Overall changes improve responsiveness, visual hierarchy, and focus/navigation behavior.
This commit is contained in:
2026-06-08 14:40:00 +12:00
parent fe620020be
commit cfd1fab6b2
13 changed files with 555 additions and 506 deletions
@@ -3,50 +3,35 @@
window.CO_ServerDetails = {
render: function (root, state) {
var el = root.querySelector(".co-details");
var activePane = root.querySelector('.co-tab-pane[data-pane="' + state.activeTab + '"]');
var el = activePane && activePane.querySelector(".co-preview-area");
if (!el) return;
el.className = "co-details" + (state.focusZone === "details" ? " focused" : "");
var server = state.servers[state.selectedServerIndex];
if (!server) {
el.innerHTML = '<div class="co-details-title">Server Details</div><div class="co-empty">Select a server</div>';
if (!server || !server.previewImage) {
el.innerHTML = "";
el.classList.add("co-preview-hidden");
return;
}
var rulesHtml = "";
if (server.rules && server.rules.length) {
rulesHtml = "<ul class=\"co-detail-rules\">" + server.rules.map(function (r) {
return "<li>" + escapeHtml(r) + "</li>";
}).join("") + "</ul>";
}
el.classList.remove("co-preview-hidden");
var previewHtml = server.previewImage
? '<img src="' + escapeAttr(server.previewImage) + '" alt="Preview">'
: "Preview Unavailable";
var stats = [
server.worldspace,
server.mode,
server.players + "/" + server.maxPlayers,
server.ping + " ms"
].filter(Boolean).join(" \u00b7 ");
el.innerHTML =
'<div class="co-details-title">Server Details</div>' +
'<div class="co-preview">' + previewHtml + "</div>" +
'<div class="co-detail-name">' + escapeHtml(server.name) + "</div>" +
detailRow("Region", server.region) +
detailRow("Players", server.players + "/" + server.maxPlayers) +
detailRow("Ping", server.ping + " ms") +
detailRow("Worldspace", server.worldspace) +
detailRow("Mode", server.mode) +
detailRow("Status", server.status) +
detailRow("Modded", server.modded ? "Yes" : "No") +
detailRow("Password", server.passworded ? "Required" : "None") +
'<div class="co-detail-desc">' + escapeHtml(server.description || "") + "</div>" +
rulesHtml +
'<div class="co-detail-desc" style="margin-top:8px;color:var(--co-text-dim)">Mod list: coming soon</div>';
'<div class="co-preview"><img src="' + escapeAttr(server.previewImage) + '" alt="Preview"></div>' +
'<div class="co-preview-caption">' +
'<div class="co-preview-name">' + escapeHtml(server.name) + "</div>" +
'<div class="co-preview-stats">' + escapeHtml(stats) + "</div>" +
"</div>";
}
};
function detailRow(label, value) {
return '<div class="co-detail-row"><span>' + label + '</span><span>' + escapeHtml(String(value)) + "</span></div>";
}
function escapeHtml(value) {
return String(value)
.replace(/&/g, "&amp;")