feat: First iteration, multi themes, I18N

This commit is contained in:
gauvainboiche
2026-10-08 11:58:18 +02:00
parent 9240fa3c3c
commit aa9721ac2a
53 changed files with 3363 additions and 1 deletions
+162
View File
@@ -0,0 +1,162 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<meta name="color-scheme" content="light dark">
<title>Idle Clicker</title>
<link rel="stylesheet" href="css/base.css">
<link rel="stylesheet" href="css/layout.css">
<link rel="stylesheet" href="css/components.css">
<!-- The theme stylesheet (themes/<id>/theme.css) is injected by js/services/themes.js -->
<script type="module" src="js/main.js"></script>
</head>
<body>
<header class="topbar">
<h1 class="topbar__title" id="game-title" data-i18n="theme.title">Idle Clicker</h1>
<div class="topbar__controls">
<label class="field">
<span class="field__label" data-i18n="ui.theme">Theme</span>
<select id="theme-select"></select>
</label>
<label class="field">
<span class="field__label" data-i18n="ui.language">Language</span>
<select id="locale-select"></select>
</label>
<button class="btn btn--ghost" id="open-settings" type="button" data-i18n="ui.settings">Save &amp; settings</button>
</div>
</header>
<p class="banner" id="cookie-warning" hidden data-i18n="toast.cookiesBlocked"></p>
<main class="game" id="game">
<!-- Overview -->
<section class="panel panel--stats" aria-labelledby="h-stats">
<h2 class="panel__title" id="h-stats" data-i18n="ui.overview">Overview</h2>
<div class="tiles">
<div class="tile tile--primary">
<span class="icon icon--placeholder" aria-hidden="true" data-icon="res.units"></span>
<div>
<span class="tile__label" data-i18n="theme.res.units"></span>
<strong class="tile__value" id="v-units">0</strong>
</div>
</div>
<div class="tile">
<span class="icon icon--placeholder" aria-hidden="true" data-icon="res.funds"></span>
<div>
<span class="tile__label" data-i18n="theme.res.funds"></span>
<strong class="tile__value" id="v-funds">0</strong>
</div>
</div>
<div class="tile">
<span class="icon icon--placeholder" aria-hidden="true" data-icon="res.material"></span>
<div>
<span class="tile__label" data-i18n="theme.res.material"></span>
<strong class="tile__value" id="v-material">0</strong>
</div>
</div>
</div>
<dl class="stats">
<div><dt data-i18n="ui.totalProduced"></dt><dd id="v-total">0</dd></div>
<div><dt data-i18n="ui.production"></dt><dd id="v-rate">0</dd></div>
<div><dt data-i18n="ui.demand"></dt><dd id="v-demand">0</dd></div>
<div><dt data-i18n="ui.income"></dt><dd id="v-income">0</dd></div>
</dl>
</section>
<!-- Manual production + raw material -->
<section class="panel panel--production" aria-labelledby="h-production">
<h2 class="panel__title" id="h-production" data-i18n="ui.manual">Manual work</h2>
<button class="btn btn--primary btn--big" id="make" type="button">
<span data-i18n="theme.action.make"></span>
<small id="make-yield"></small>
</button>
<button class="btn btn--wide" id="buy-material" type="button">
<span data-i18n="theme.action.buyMaterial"></span>
<small id="buy-material-info"></small>
</button>
</section>
<!-- Selling -->
<section class="panel panel--market" aria-labelledby="h-market">
<h2 class="panel__title" id="h-market" data-i18n="ui.market">Market</h2>
<div class="price">
<span class="price__label" data-i18n="ui.price"></span>
<div class="price__row">
<button class="btn btn--square" id="price-down" type="button" data-i18n-attr="aria-label:ui.priceDown">−</button>
<input class="price__input" id="price-input" type="number" inputmode="decimal" min="0.01" step="0.01">
<button class="btn btn--square" id="price-up" type="button" data-i18n-attr="aria-label:ui.priceUp">+</button>
</div>
<input class="price__slider" id="price-slider" type="range" min="0" max="1000" step="1" data-i18n-attr="aria-label:ui.price">
<p class="hint" id="price-hint"></p>
</div>
<button class="btn btn--wide" id="buy-marketing" type="button">
<span data-i18n="ui.marketing"></span>
<small id="buy-marketing-info"></small>
</button>
</section>
<!-- Automation -->
<section class="panel panel--generators" aria-labelledby="h-generators">
<div class="panel__head">
<h2 class="panel__title" id="h-generators" data-i18n="ui.automation">Automation</h2>
<fieldset class="segmented" id="buy-amount">
<legend class="sr-only" data-i18n="ui.buyAmount"></legend>
<label><input type="radio" name="buy-amount" value="1" checked><span>×1</span></label>
<label><input type="radio" name="buy-amount" value="10"><span>×10</span></label>
<label><input type="radio" name="buy-amount" value="100"><span>×100</span></label>
<label><input type="radio" name="buy-amount" value="max"><span data-i18n="ui.max"></span></label>
</fieldset>
</div>
<ul class="cards" id="generators"></ul>
</section>
<!-- Upgrades -->
<section class="panel panel--upgrades" aria-labelledby="h-upgrades">
<div class="panel__head">
<h2 class="panel__title" id="h-upgrades" data-i18n="ui.upgrades">Upgrades</h2>
<span class="badge" id="upgrade-count"></span>
</div>
<p class="hint" id="upgrades-empty" data-i18n="ui.noUpgrades"></p>
<ul class="cards" id="upgrades"></ul>
</section>
</main>
<!-- Save & settings -->
<dialog class="dialog" id="settings" aria-labelledby="h-settings">
<form method="dialog" class="dialog__body">
<div class="panel__head">
<h2 class="panel__title" id="h-settings" data-i18n="settings.title"></h2>
<button class="btn btn--ghost" value="close" data-i18n="ui.close"></button>
</div>
<h3 class="dialog__subtitle" data-i18n="settings.export"></h3>
<p class="hint" data-i18n="settings.exportHelp"></p>
<textarea class="textarea" id="export-text" rows="5" readonly spellcheck="false" data-i18n-attr="aria-label:settings.export"></textarea>
<div class="row">
<button class="btn" type="button" id="export-json" data-i18n="settings.downloadJson"></button>
<button class="btn" type="button" id="export-txt" data-i18n="settings.downloadTxt"></button>
<button class="btn" type="button" id="export-copy" data-i18n="settings.copy"></button>
</div>
<h3 class="dialog__subtitle" data-i18n="settings.import"></h3>
<p class="hint" data-i18n="settings.importHelp"></p>
<div class="row">
<label class="btn" for="import-file" data-i18n="settings.importFile"></label>
<input class="sr-only" id="import-file" type="file" accept=".json,.txt,application/json,text/plain">
</div>
<textarea class="textarea" id="import-text" rows="4" spellcheck="false" data-i18n-attr="aria-label:settings.import;placeholder:settings.pastePlaceholder"></textarea>
<div class="row">
<button class="btn" type="button" id="import-paste" data-i18n="settings.importText"></button>
</div>
<h3 class="dialog__subtitle" data-i18n="settings.danger"></h3>
<div class="row">
<button class="btn btn--danger" type="button" id="reset-game" data-i18n="settings.reset"></button>
</div>
</form>
</dialog>
<div class="toasts" id="toasts" role="status" aria-live="polite"></div>
</body>
</html>