134 lines
7.0 KiB
JavaScript
134 lines
7.0 KiB
JavaScript
// Steam spoof — static-but-believable game library UI.
|
|
|
|
const GAMES = [
|
|
{ id: 'elden', title: 'Elden Ring', desc: 'Explore the Lands Between in this open-world action RPG from FromSoftware. Face legendary bosses, forge your build, and uncover the mystery of the shattered Elden Ring. Every step is a descent into the unknown.' },
|
|
{ id: 'cod', title: 'Call of Duty: MW2', desc: 'Relive the global conflict in this first-person shooter campaign. From Operation Deadbolt to the final push, the stakes have never been higher. Multiplayer is included, if you can find it in the files.' },
|
|
{ id: 'fifa', title: 'FIFA 24', desc: 'The world\'s game, rendered in full hyper-realistic detail. Play Career Mode, Ultimate Team, or just stare at the menu screen for three hours. Your choice, really.' },
|
|
{ id: 'hades', title: 'Hades II', desc: 'Return to the Underworld as Melinoch, sister of Zagreus. Wield witchcraft, summon gods, and break out of the cycle of death and rebirth. Again. This time with more style.' },
|
|
{ id: 'factorio', title: 'Factorio', desc: 'Build factories, then build bigger factories, then automate your entire existence into a sprawling industrial complex that will consume all your spare time. There is no escape.' },
|
|
{ id: 'stardew', title: 'Stardew Valley', desc: 'Leave the city. Take over your grandfather\'s old farm plot. Grow crops, raise animals, befriend the locals. It\'s a quiet life, and you\'ll never leave.' },
|
|
{ id: 'bg3', title: "Baldur's Gate 3", desc: 'Gather your party. Roll the dice. Make the worst possible choice. Larian Studios has crafted a deep RPG experience with consequences that actually matter. Mostly.' },
|
|
];
|
|
|
|
export default {
|
|
id: 'steam',
|
|
title: 'Steam',
|
|
render(container, api) {
|
|
let selectedGame = null;
|
|
let installing = null;
|
|
|
|
const root = document.createElement('div');
|
|
root.style.cssText = 'height:100%;display:flex;flex-direction:column;background:var(--bg-1);';
|
|
|
|
// Top bar
|
|
const topBar = document.createElement('div');
|
|
topBar.style.cssText = 'background:var(--bg-2);padding:8px 16px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;';
|
|
const topTitle = document.createElement('span');
|
|
topTitle.style.cssText = 'font-size:14px;font-weight:600;color:var(--text);';
|
|
topTitle.textContent = 'Steam';
|
|
topBar.appendChild(topTitle);
|
|
root.appendChild(topBar);
|
|
|
|
// Body: sidebar + main
|
|
const body = document.createElement('div');
|
|
body.style.cssText = 'flex:1;display:flex;overflow:hidden;';
|
|
|
|
// Sidebar
|
|
const sidebar = document.createElement('div');
|
|
sidebar.style.cssText = 'width:220px;background:var(--bg-2);border-right:1px solid var(--border);display:flex;flex-direction:column;overflow-y:auto;flex-shrink:0;';
|
|
const sidebarLabel = document.createElement('div');
|
|
sidebarLabel.style.cssText = 'padding:12px 14px 6px;font-size:11px;font-weight:600;color:var(--text-dim);text-transform:uppercase;letter-spacing:0.05em;';
|
|
sidebarLabel.textContent = 'Library';
|
|
sidebar.appendChild(sidebarLabel);
|
|
|
|
GAMES.forEach((game) => {
|
|
const item = document.createElement('div');
|
|
item.style.cssText = 'padding:8px 14px;cursor:pointer;font-size:13px;color:var(--text);transition:background 150ms ease-out;border-left:2px solid transparent;';
|
|
item.textContent = game.title;
|
|
item.addEventListener('click', () => { selectGame(game); });
|
|
item.dataset.gameId = game.id;
|
|
sidebar.appendChild(item);
|
|
});
|
|
|
|
// Main area
|
|
const mainArea = document.createElement('div');
|
|
mainArea.style.cssText = 'flex:1;display:flex;flex-direction:column;overflow-y:auto;padding:24px;';
|
|
|
|
// Initial state: "Select a game"
|
|
const placeholder = document.createElement('div');
|
|
placeholder.style.cssText = 'flex:1;display:flex;align-items:center;justify-content:center;color:var(--text-dim);font-size:14px;';
|
|
placeholder.textContent = 'Select a game from your library';
|
|
mainArea.appendChild(placeholder);
|
|
|
|
body.appendChild(sidebar);
|
|
body.appendChild(mainArea);
|
|
root.appendChild(body);
|
|
|
|
// Status bar
|
|
const status = document.createElement('div');
|
|
status.style.cssText = 'background:var(--bg-2);border-top:1px solid var(--border);padding:6px 14px;font-size:11px;color:var(--text-dim);flex-shrink:0;';
|
|
status.textContent = 'Online \u{B7} 142 friends online \u{B7} 4.7 TB free';
|
|
root.appendChild(status);
|
|
|
|
container.appendChild(root);
|
|
|
|
function selectGame(game) {
|
|
selectedGame = game;
|
|
installing = null;
|
|
|
|
// Clear main area and add game details
|
|
while (mainArea.firstChild) mainArea.removeChild(mainArea.firstChild);
|
|
|
|
// Hero image (gradient block with title overlay)
|
|
const hero = document.createElement('div');
|
|
hero.style.cssText = 'width:100%;height:200px;background:linear-gradient(135deg, rgba(37,42,49,0.9), rgba(212,162,76,0.2));border:1px solid var(--border);display:flex;align-items:flex-end;padding:20px;margin-bottom:20px;position:relative;overflow:hidden;border-radius:4px;';
|
|
const heroOverlay = document.createElement('div');
|
|
heroOverlay.style.cssText = 'font-size:32px;font-weight:700;color:var(--text);text-shadow:0 2px 8px rgba(0,0,0,0.6);';
|
|
heroOverlay.textContent = game.title;
|
|
hero.appendChild(heroOverlay);
|
|
mainArea.appendChild(hero);
|
|
|
|
// Description
|
|
const desc = document.createElement('p');
|
|
desc.style.cssText = 'font-size:13px;color:var(--text);line-height:1.7;margin-bottom:20px;max-width:600px;';
|
|
desc.textContent = game.desc;
|
|
mainArea.appendChild(desc);
|
|
|
|
// Install button
|
|
const installBtn = document.createElement('button');
|
|
installBtn.style.cssText = 'padding:10px 28px;background:var(--accent);color:#0f1114;border:none;border-radius:4px;font-size:14px;font-weight:600;cursor:pointer;transition:opacity 150ms ease-out;width:fit-content;';
|
|
installBtn.textContent = 'Install';
|
|
installBtn.addEventListener('click', () => startInstall(game, installBtn));
|
|
mainArea.appendChild(installBtn);
|
|
}
|
|
|
|
function startInstall(game, btn) {
|
|
installing = game.id;
|
|
btn.textContent = 'Downloading...';
|
|
btn.disabled = true;
|
|
|
|
const progressWrap = document.createElement('div');
|
|
progressWrap.style.cssText = 'width:280px;height:6px;background:var(--bg-3);border-radius:3px;margin-top:12px;overflow:hidden;';
|
|
const progressFill = document.createElement('div');
|
|
progressFill.style.cssText = 'width:0%;height:100%;background:var(--accent);border-radius:3px;transition:width 2s linear;';
|
|
progressWrap.appendChild(progressFill);
|
|
mainArea.appendChild(progressWrap);
|
|
|
|
// Animate progress over 2s
|
|
requestAnimationFrame(() => {
|
|
progressFill.style.width = '100%';
|
|
});
|
|
|
|
setTimeout(() => {
|
|
btn.textContent = 'Installed (in your imagination)';
|
|
btn.style.background = 'var(--bg-3)';
|
|
btn.style.color = 'var(--text-dim)';
|
|
btn.style.border = '1px solid var(--border)';
|
|
btn.disabled = false;
|
|
installing = null;
|
|
progressWrap.remove();
|
|
}, 2100);
|
|
}
|
|
},
|
|
};
|