docs(design): specify download progress treatment
Document and mock the redesigned downloading state for the launcher. The reference now replaces the action button slot with a dedicated progress primitive, covers both card and detail-modal layouts, and records the sizing, number formatting, container-query fallback, and sample-data expectations that implementation work should follow. This commit keeps the design package separate from application code so the next UI/backend changes can be reviewed against a stable reference. Test Plan: - git diff --cached --check Refs: local design reference update
This commit is contained in:
@@ -18,7 +18,7 @@ const GAMES = [
|
||||
{
|
||||
id: 'avp', title: 'Aliens vs. Predator', size: 35.0, version: '2019.10.01',
|
||||
desc: "Three campaigns, three nightmares. Be the alien stalking the dark, the predator hunting both, or the marine just trying to make it home with a working flashlight.",
|
||||
state: 'none', players: '2–16', tags: ['FPS', 'Horror', 'Multiplayer'],
|
||||
state: 'downloading', progress: 0.32, speed: 49.4, players: '2–16', tags: ['FPS', 'Horror', 'Multiplayer'],
|
||||
cover: { c1: '#064e3b', c2: '#020617', accent: '#34d399', mood: 'dark' },
|
||||
},
|
||||
{
|
||||
@@ -120,7 +120,7 @@ const GAMES = [
|
||||
{
|
||||
id: 'quake3', title: 'Quake III Arena', size: 0.5, version: '2010.08.15',
|
||||
desc: "Arena FPS in its most distilled form. Rocket jumps, rail-gun duels, and a netcode that's still the benchmark.",
|
||||
state: 'none', players: '2–16', tags: ['FPS', 'Arena', 'LAN'],
|
||||
state: 'downloading', progress: 0.71, speed: 12.8, players: '2–16', tags: ['FPS', 'Arena', 'LAN'],
|
||||
cover: { c1: '#7f1d1d', c2: '#0a0a0a', accent: '#fbbf24', mood: 'dark' },
|
||||
},
|
||||
{
|
||||
@@ -152,25 +152,45 @@ const GAMES = [
|
||||
// Helpers
|
||||
const fmtSize = (gb) => gb < 1 ? `${Math.round(gb * 1024)} MB` : `${gb.toFixed(1)} GB`;
|
||||
const STATE_META = {
|
||||
installed: { label: 'Installed', dot: '#22c55e' },
|
||||
local: { label: 'Local', dot: '#f59e0b' },
|
||||
none: { label: '', dot: 'transparent' },
|
||||
installed: { label: 'Installed', dot: '#22c55e' },
|
||||
local: { label: 'Local', dot: '#f59e0b' },
|
||||
downloading: { label: 'Downloading', dot: 'var(--accent)' },
|
||||
none: { label: '', dot: 'transparent' },
|
||||
};
|
||||
const ACTION_FOR_STATE = {
|
||||
installed: { label: 'Play', kind: 'play' },
|
||||
local: { label: 'Install', kind: 'install' },
|
||||
none: { label: 'Download', kind: 'download' },
|
||||
installed: { label: 'Play', kind: 'play' },
|
||||
local: { label: 'Install', kind: 'install' },
|
||||
downloading: { label: 'Downloading', kind: 'downloading' },
|
||||
none: { label: 'Download', kind: 'download' },
|
||||
};
|
||||
|
||||
// Format helpers for download UI
|
||||
const fmtSpeed = (mbps) => mbps >= 100 ? `${Math.round(mbps)} MB/s` : `${mbps.toFixed(1)} MB/s`;
|
||||
const fmtSpeedShort = (mbps) => `${Math.round(mbps)} MB/s`;
|
||||
const fmtBytes = (gb) => {
|
||||
if (gb < 1) return `${Math.round(gb * 1024)} MB`;
|
||||
// No trailing zeros: 35 GB, 11.4 GB, 2.35 GB
|
||||
if (gb >= 10) return `${gb.toFixed(1).replace(/\.0$/,'')} GB`;
|
||||
return `${gb.toFixed(2).replace(/0$/,'').replace(/\.$/,'')} GB`;
|
||||
};
|
||||
const fmtEta = (sec) => {
|
||||
if (!isFinite(sec) || sec <= 0) return '—';
|
||||
if (sec < 60) return `${Math.round(sec)} s`;
|
||||
const m = Math.round(sec / 60);
|
||||
if (m < 60) return `${m} min`;
|
||||
return `${Math.floor(m/60)} h ${m%60} min`;
|
||||
};
|
||||
|
||||
const isLocalish = (s) => s === 'installed' || s === 'local' || s === 'downloading';
|
||||
const countByFilter = (games) => ({
|
||||
all: games.length,
|
||||
local: games.filter(g => g.state === 'installed' || g.state === 'local').length,
|
||||
local: games.filter(g => isLocalish(g.state)).length,
|
||||
installed: games.filter(g => g.state === 'installed').length,
|
||||
});
|
||||
|
||||
const filterGames = (games, key) => {
|
||||
if (key === 'all') return games;
|
||||
if (key === 'local') return games.filter(g => g.state === 'installed' || g.state === 'local');
|
||||
if (key === 'local') return games.filter(g => isLocalish(g.state));
|
||||
if (key === 'installed') return games.filter(g => g.state === 'installed');
|
||||
return games;
|
||||
};
|
||||
@@ -189,4 +209,8 @@ window.ACTION_FOR_STATE = ACTION_FOR_STATE;
|
||||
window.countByFilter = countByFilter;
|
||||
window.filterGames = filterGames;
|
||||
window.fmtSize = fmtSize;
|
||||
window.fmtSpeed = fmtSpeed;
|
||||
window.fmtSpeedShort = fmtSpeedShort;
|
||||
window.fmtBytes = fmtBytes;
|
||||
window.fmtEta = fmtEta;
|
||||
window.STORAGE = STORAGE;
|
||||
|
||||
Reference in New Issue
Block a user