update
This commit is contained in:
540
docs/superpowers/plans/2026-05-18-minecraft-theme.md
Normal file
540
docs/superpowers/plans/2026-05-18-minecraft-theme.md
Normal file
@@ -0,0 +1,540 @@
|
||||
# Minecraft Theme Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Add a "minecraft" design theme — zero border-radius, Minecraft GUI bevel shadows, 16px pixel grid background, monospace font, dark (Stone & Cave) + light (Overworld Day) modes.
|
||||
|
||||
**Architecture:** Four small file edits following the established theme pattern. Dark mode uses `html[data-theme="dark"][data-design-theme="minecraft"]` selectors (same specificity as the generic dark override rules, but placed later in the file so they win). Light mode uses `html[data-theme="light"][data-design-theme="minecraft"]`. No font imports — system monospace only.
|
||||
|
||||
**Tech Stack:** Vanilla JS, Vite, CSS custom properties. No test suite — verification is manual via `npm start`.
|
||||
|
||||
---
|
||||
|
||||
## Files Modified
|
||||
|
||||
| File | Change |
|
||||
|---|---|
|
||||
| `theme.js:1` | Add `"minecraft"` to `DESIGN_THEMES` |
|
||||
| `index.html:48` | Add `<li role="option" data-value="minecraft">` after animal-crossing |
|
||||
| `i18n.js:136–226` | Add `minecraft` key in all 11 language objects of `DESIGN_THEME_LABELS` |
|
||||
| `style.css` | Append dark vars + light vars + body/grid/control/card overrides + reduced-motion |
|
||||
|
||||
---
|
||||
|
||||
## Task 1: Register the theme slug
|
||||
|
||||
**Files:**
|
||||
- Modify: `theme.js:1`
|
||||
- Modify: `index.html:48`
|
||||
|
||||
- [ ] **Step 1: Add slug to DESIGN_THEMES in theme.js**
|
||||
|
||||
Change line 1 from:
|
||||
```js
|
||||
const DESIGN_THEMES = ["fluent", "material-you", "terminal", "cyberpunk", "nord", "animal-crossing"]
|
||||
```
|
||||
to:
|
||||
```js
|
||||
const DESIGN_THEMES = ["fluent", "material-you", "terminal", "cyberpunk", "nord", "animal-crossing", "minecraft"]
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Add dropdown option in index.html**
|
||||
|
||||
After the animal-crossing `<li>` (currently lines 46–48):
|
||||
```html
|
||||
<li role="option" data-value="animal-crossing" aria-selected="false">
|
||||
Animal Crossing
|
||||
</li>
|
||||
```
|
||||
add immediately after:
|
||||
```html
|
||||
<li role="option" data-value="minecraft" aria-selected="false">
|
||||
Minecraft
|
||||
</li>
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add theme.js index.html
|
||||
git commit -m "feat: register minecraft theme slug"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 2: Add i18n labels
|
||||
|
||||
**Files:**
|
||||
- Modify: `i18n.js:136–226`
|
||||
|
||||
- [ ] **Step 1: Add `minecraft` key to every language object in DESIGN_THEME_LABELS**
|
||||
|
||||
Replace the entire `DESIGN_THEME_LABELS` constant with:
|
||||
|
||||
```js
|
||||
export const DESIGN_THEME_LABELS = {
|
||||
"zh-Hans": {
|
||||
fluent: "Fluent",
|
||||
"material-you": "Material You",
|
||||
terminal: "终端",
|
||||
cyberpunk: "赛博朋克",
|
||||
nord: "Nord",
|
||||
"animal-crossing": "动森",
|
||||
minecraft: "我的世界",
|
||||
},
|
||||
"zh-Hant": {
|
||||
fluent: "Fluent",
|
||||
"material-you": "Material You",
|
||||
terminal: "終端",
|
||||
cyberpunk: "賽博龐克",
|
||||
nord: "Nord",
|
||||
"animal-crossing": "動森",
|
||||
minecraft: "我的世界",
|
||||
},
|
||||
en: {
|
||||
fluent: "Fluent",
|
||||
"material-you": "Material You",
|
||||
terminal: "Terminal",
|
||||
cyberpunk: "Cyberpunk",
|
||||
nord: "Nord",
|
||||
"animal-crossing": "Animal Crossing",
|
||||
minecraft: "Minecraft",
|
||||
},
|
||||
ja: {
|
||||
fluent: "Fluent",
|
||||
"material-you": "Material You",
|
||||
terminal: "ターミナル",
|
||||
cyberpunk: "サイバーパンク",
|
||||
nord: "Nord",
|
||||
"animal-crossing": "どうぶつの森",
|
||||
minecraft: "マインクラフト",
|
||||
},
|
||||
ko: {
|
||||
fluent: "Fluent",
|
||||
"material-you": "Material You",
|
||||
terminal: "터미널",
|
||||
cyberpunk: "사이버펑크",
|
||||
nord: "Nord",
|
||||
"animal-crossing": "동물의 숲",
|
||||
minecraft: "마인크래프트",
|
||||
},
|
||||
wenyan: {
|
||||
fluent: "流光",
|
||||
"material-you": "物材",
|
||||
terminal: "终端",
|
||||
cyberpunk: "赛博",
|
||||
nord: "清寒",
|
||||
"animal-crossing": "森友",
|
||||
minecraft: "方块世界",
|
||||
},
|
||||
mars: {
|
||||
fluent: "流↗光",
|
||||
"material-you": "材↘質",
|
||||
terminal: "終↗★端",
|
||||
cyberpunk: "賽↘!博",
|
||||
nord: "清↗寒★",
|
||||
"animal-crossing": "动↗森★",
|
||||
minecraft: "我↗的★世界",
|
||||
},
|
||||
garbled: {
|
||||
fluent: "◼è▦",
|
||||
"material-you": "拷▤屯ä锟◽",
|
||||
terminal: "¥¬▤▨¿¿",
|
||||
cyberpunk: "◼çæ¥烫¥",
|
||||
nord: "æ◽屯¿",
|
||||
"animal-crossing": "ä◼▤è",
|
||||
minecraft: "▤◼▦è屯",
|
||||
},
|
||||
bin: {
|
||||
fluent: "0101",
|
||||
"material-you": "010101",
|
||||
terminal: "01010101",
|
||||
cyberpunk: "0101010101",
|
||||
nord: "0101010",
|
||||
"animal-crossing": "01010101",
|
||||
minecraft: "0101010",
|
||||
},
|
||||
meow: {
|
||||
fluent: "喵喵",
|
||||
"material-you": "喵喵喵",
|
||||
terminal: "喵喵",
|
||||
cyberpunk: "喵喵喵喵",
|
||||
nord: "喵喵喵",
|
||||
"animal-crossing": "喵喵喵喵",
|
||||
minecraft: "喵喵喵",
|
||||
},
|
||||
emoji: {
|
||||
fluent: "💧",
|
||||
"material-you": "🧱",
|
||||
terminal: "⌨️",
|
||||
cyberpunk: "⚡",
|
||||
nord: "❄️",
|
||||
"animal-crossing": "🌿",
|
||||
minecraft: "⛏️",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Commit**
|
||||
|
||||
```bash
|
||||
git add i18n.js
|
||||
git commit -m "feat: add minecraft labels for all 11 languages"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 3: Add CSS — dark mode (Stone & Cave)
|
||||
|
||||
**Files:**
|
||||
- Modify: `style.css` (append after the `prefers-reduced-motion` block at end of file)
|
||||
|
||||
- [ ] **Step 1: Append dark mode CSS block at end of style.css**
|
||||
|
||||
```css
|
||||
/* ─── Minecraft — Stone & Cave / Overworld Day ──────────────── */
|
||||
html[data-design-theme="minecraft"] {
|
||||
color-scheme: dark;
|
||||
|
||||
--accent: #5aaa3a;
|
||||
--accent-rgb: 90, 170, 58;
|
||||
--accent-2: #3d8a2a;
|
||||
--accent-3: #2a6e1a;
|
||||
--accent-secondary-rgb: 91, 191, 232;
|
||||
|
||||
--page-gradient: #1a1a1a;
|
||||
--page-texture: none;
|
||||
--title-gradient: linear-gradient(135deg, #5bbfe8 0%, #5aaa3a 100%);
|
||||
|
||||
--control-bg: rgba(62, 62, 62, 0.92);
|
||||
--control-border: #1a1a1a;
|
||||
--control-inset: rgba(255, 255, 255, 0.2);
|
||||
--control-fg: #f0f0f0;
|
||||
}
|
||||
|
||||
html[data-theme="dark"][data-design-theme="minecraft"] {
|
||||
color-scheme: dark;
|
||||
|
||||
--accent: #5aaa3a;
|
||||
--accent-rgb: 90, 170, 58;
|
||||
--accent-2: #3d8a2a;
|
||||
--accent-3: #2a6e1a;
|
||||
--accent-secondary-rgb: 91, 191, 232;
|
||||
|
||||
--page-gradient: #1a1a1a;
|
||||
--page-texture: none;
|
||||
--title-gradient: linear-gradient(135deg, #5bbfe8 0%, #5aaa3a 100%);
|
||||
|
||||
--control-bg: rgba(62, 62, 62, 0.92);
|
||||
--control-border: #1a1a1a;
|
||||
--control-inset: rgba(255, 255, 255, 0.2);
|
||||
--control-fg: #f0f0f0;
|
||||
}
|
||||
|
||||
html[data-design-theme="minecraft"] body {
|
||||
font-family: ui-monospace, "Courier New", Courier, monospace;
|
||||
letter-spacing: 0.04em;
|
||||
color: #f0f0f0;
|
||||
}
|
||||
|
||||
html[data-theme="dark"][data-design-theme="minecraft"] body {
|
||||
color: #f0f0f0;
|
||||
}
|
||||
|
||||
html[data-design-theme="minecraft"] body::before {
|
||||
background-image:
|
||||
linear-gradient(rgba(255, 255, 255, 0.025) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgba(255, 255, 255, 0.025) 1px, transparent 1px);
|
||||
background-size: 16px 16px;
|
||||
}
|
||||
|
||||
html[data-design-theme="minecraft"] .design-theme-button,
|
||||
html[data-design-theme="minecraft"] .theme-toggle {
|
||||
border-radius: 0;
|
||||
backdrop-filter: none;
|
||||
-webkit-backdrop-filter: none;
|
||||
box-shadow:
|
||||
inset 2px 2px 0 rgba(255, 255, 255, 0.25),
|
||||
inset -2px -2px 0 rgba(0, 0, 0, 0.5);
|
||||
transition: all 0.1s steps(2, end);
|
||||
}
|
||||
|
||||
html[data-design-theme="minecraft"] .design-theme-button:hover,
|
||||
html[data-design-theme="minecraft"] .theme-toggle:hover {
|
||||
background: rgba(82, 82, 82, 0.95);
|
||||
box-shadow:
|
||||
inset 2px 2px 0 rgba(255, 255, 255, 0.35),
|
||||
inset -2px -2px 0 rgba(0, 0, 0, 0.4);
|
||||
transform: none;
|
||||
border-color: rgba(var(--accent-rgb), 0.7);
|
||||
}
|
||||
|
||||
html[data-design-theme="minecraft"] .design-theme-button:active,
|
||||
html[data-design-theme="minecraft"] .theme-toggle:active {
|
||||
box-shadow:
|
||||
inset 2px 2px 0 rgba(0, 0, 0, 0.4),
|
||||
inset -2px -2px 0 rgba(255, 255, 255, 0.12);
|
||||
}
|
||||
|
||||
html[data-design-theme="minecraft"] .design-theme-list {
|
||||
border-radius: 0;
|
||||
backdrop-filter: none;
|
||||
-webkit-backdrop-filter: none;
|
||||
background: rgba(30, 30, 30, 0.96);
|
||||
border: 2px solid #111111;
|
||||
box-shadow:
|
||||
inset 2px 2px 0 rgba(255, 255, 255, 0.1),
|
||||
inset -2px -2px 0 rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
html[data-design-theme="minecraft"] .design-theme-list [role="option"] {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
html[data-design-theme="minecraft"]
|
||||
.design-theme-list
|
||||
[role="option"]:hover,
|
||||
html[data-design-theme="minecraft"]
|
||||
.design-theme-list
|
||||
[role="option"][aria-selected="true"] {
|
||||
background: rgba(var(--accent-rgb), 0.25);
|
||||
color: var(--control-fg);
|
||||
}
|
||||
|
||||
html[data-theme="dark"][data-design-theme="minecraft"] .card {
|
||||
background: #3c3c3c;
|
||||
border: 2px solid #111111;
|
||||
border-radius: 0;
|
||||
backdrop-filter: none;
|
||||
-webkit-backdrop-filter: none;
|
||||
box-shadow:
|
||||
inset 2px 2px 0 rgba(255, 255, 255, 0.2),
|
||||
inset -2px -2px 0 rgba(0, 0, 0, 0.5);
|
||||
transition: all 0.1s steps(2, end);
|
||||
transform: none;
|
||||
}
|
||||
|
||||
html[data-theme="dark"][data-design-theme="minecraft"] .card::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
html[data-theme="dark"][data-design-theme="minecraft"] .card.pin {
|
||||
background: #454545;
|
||||
}
|
||||
|
||||
html[data-theme="dark"][data-design-theme="minecraft"] .card h2 {
|
||||
color: #f0f0f0;
|
||||
}
|
||||
|
||||
html[data-theme="dark"][data-design-theme="minecraft"] .card p {
|
||||
color: #c8c8c8;
|
||||
}
|
||||
|
||||
html[data-theme="dark"][data-design-theme="minecraft"] .card:hover,
|
||||
html[data-theme="dark"][data-design-theme="minecraft"] .card:focus {
|
||||
background: #484848;
|
||||
transform: none;
|
||||
border-color: #5aaa3a;
|
||||
box-shadow:
|
||||
inset 2px 2px 0 rgba(0, 0, 0, 0.35),
|
||||
inset -2px -2px 0 rgba(255, 255, 255, 0.12);
|
||||
}
|
||||
|
||||
html[data-theme="dark"][data-design-theme="minecraft"] .card:hover h2,
|
||||
html[data-theme="dark"][data-design-theme="minecraft"] .card:focus h2 {
|
||||
color: #5aaa3a;
|
||||
}
|
||||
|
||||
html[data-theme="dark"][data-design-theme="minecraft"] .card:hover p,
|
||||
html[data-theme="dark"][data-design-theme="minecraft"] .card:focus p {
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
html[data-theme="dark"][data-design-theme="minecraft"] .beian a {
|
||||
color: #c8c8c8;
|
||||
}
|
||||
|
||||
html[data-theme="dark"][data-design-theme="minecraft"] .beian a:hover {
|
||||
color: #5aaa3a;
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Verify dark mode in browser**
|
||||
|
||||
Start dev server (`npm start`). Select "我的世界" in dark mode. Verify:
|
||||
- Background is `#1a1a1a` dark stone (not generic dark gray)
|
||||
- Title has blue-to-green gradient
|
||||
- Cards are `#3c3c3c` with visible bevel (lighter top-left, darker bottom-right inset)
|
||||
- Cards have NO rounded corners (sharp square edges)
|
||||
- Card hover inverts the bevel and border turns green
|
||||
- Controls have zero border-radius and bevel effect
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add style.css
|
||||
git commit -m "feat: add minecraft dark mode CSS"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 4: Add CSS — light mode (Overworld Day)
|
||||
|
||||
**Files:**
|
||||
- Modify: `style.css` (append after dark mode block from Task 3)
|
||||
|
||||
- [ ] **Step 1: Append light mode CSS block**
|
||||
|
||||
```css
|
||||
html[data-theme="light"][data-design-theme="minecraft"] {
|
||||
color-scheme: light;
|
||||
|
||||
--accent: #5c9e40;
|
||||
--accent-rgb: 92, 158, 64;
|
||||
--accent-2: #4a8a30;
|
||||
--accent-3: #8b6914;
|
||||
--accent-secondary-rgb: 135, 206, 235;
|
||||
|
||||
--page-gradient: linear-gradient(180deg, #87ceeb 0%, #c9e8f7 50%, #f0f8ff 100%);
|
||||
--page-texture: none;
|
||||
--title-gradient: linear-gradient(135deg, #5c9e40 0%, #8b6914 100%);
|
||||
|
||||
--control-bg: rgba(198, 198, 198, 0.92);
|
||||
--control-border: #555555;
|
||||
--control-inset: rgba(255, 255, 255, 0.5);
|
||||
--control-fg: #2a2a2a;
|
||||
}
|
||||
|
||||
html[data-theme="light"][data-design-theme="minecraft"] body {
|
||||
color: #2a2a2a;
|
||||
}
|
||||
|
||||
html[data-theme="light"][data-design-theme="minecraft"] body::before {
|
||||
background-image:
|
||||
linear-gradient(rgba(0, 0, 0, 0.04) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgba(0, 0, 0, 0.04) 1px, transparent 1px);
|
||||
background-size: 16px 16px;
|
||||
}
|
||||
|
||||
html[data-theme="light"][data-design-theme="minecraft"] .design-theme-list {
|
||||
background: rgba(210, 210, 210, 0.96);
|
||||
border: 2px solid #555555;
|
||||
box-shadow:
|
||||
inset 2px 2px 0 rgba(255, 255, 255, 0.7),
|
||||
inset -2px -2px 0 rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
html[data-theme="light"][data-design-theme="minecraft"] .card {
|
||||
background: rgba(198, 198, 198, 0.85);
|
||||
border: 2px solid #555555;
|
||||
border-radius: 0;
|
||||
backdrop-filter: none;
|
||||
-webkit-backdrop-filter: none;
|
||||
box-shadow:
|
||||
inset 2px 2px 0 rgba(255, 255, 255, 0.6),
|
||||
inset -2px -2px 0 rgba(0, 0, 0, 0.25);
|
||||
transition: all 0.1s steps(2, end);
|
||||
transform: none;
|
||||
}
|
||||
|
||||
html[data-theme="light"][data-design-theme="minecraft"] .card::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
html[data-theme="light"][data-design-theme="minecraft"] .card.pin {
|
||||
background: rgba(210, 210, 210, 0.88);
|
||||
}
|
||||
|
||||
html[data-theme="light"][data-design-theme="minecraft"] .card h2 {
|
||||
color: #2a2a2a;
|
||||
}
|
||||
|
||||
html[data-theme="light"][data-design-theme="minecraft"] .card p {
|
||||
color: #4a4a4a;
|
||||
}
|
||||
|
||||
html[data-theme="light"][data-design-theme="minecraft"] .card:hover,
|
||||
html[data-theme="light"][data-design-theme="minecraft"] .card:focus {
|
||||
background: rgba(212, 224, 198, 0.92);
|
||||
transform: none;
|
||||
border-color: #5c9e40;
|
||||
box-shadow:
|
||||
inset 2px 2px 0 rgba(0, 0, 0, 0.15),
|
||||
inset -2px -2px 0 rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
html[data-theme="light"][data-design-theme="minecraft"] .card:hover h2,
|
||||
html[data-theme="light"][data-design-theme="minecraft"] .card:focus h2 {
|
||||
color: #5c9e40;
|
||||
}
|
||||
|
||||
html[data-theme="light"][data-design-theme="minecraft"] .card:hover p,
|
||||
html[data-theme="light"][data-design-theme="minecraft"] .card:focus p {
|
||||
color: #2a2a2a;
|
||||
}
|
||||
|
||||
html[data-theme="light"][data-design-theme="minecraft"] .beian a {
|
||||
color: #4a4a4a;
|
||||
}
|
||||
|
||||
html[data-theme="light"][data-design-theme="minecraft"] .beian a:hover {
|
||||
color: #5c9e40;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
html[data-design-theme="minecraft"] .card,
|
||||
html[data-design-theme="minecraft"] .design-theme-button,
|
||||
html[data-design-theme="minecraft"] .theme-toggle {
|
||||
transition-duration: 0.01ms !important;
|
||||
transform: none !important;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Verify light mode in browser**
|
||||
|
||||
Toggle to light mode with "我的世界" theme active. Verify:
|
||||
- Background is sky blue gradient (top `#87ceeb` to near-white at bottom)
|
||||
- Cards are stone gray `rgba(198,198,198)` with bevel (light top-left, darker bottom-right)
|
||||
- Cards have NO rounded corners
|
||||
- Card hover turns slightly green-tinted and border goes grass green
|
||||
- 16px grid is faintly visible on the sky background
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add style.css
|
||||
git commit -m "feat: add minecraft light mode CSS"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 5: Final verification
|
||||
|
||||
- [ ] **Step 1: Check `minecraft` is not in FORCED_DARK_DESIGN_THEMES**
|
||||
|
||||
Read `theme.js` line 2. It must remain:
|
||||
```js
|
||||
const FORCED_DARK_DESIGN_THEMES = new Set(["terminal", "cyberpunk"])
|
||||
```
|
||||
"minecraft" must NOT appear here.
|
||||
|
||||
- [ ] **Step 2: Verify theme cycles cleanly**
|
||||
|
||||
Cycle through all 7 themes in the dropdown. No broken styles at any step.
|
||||
|
||||
- [ ] **Step 3: Verify forced-dark restore**
|
||||
|
||||
While on Minecraft (light mode), switch to Terminal (forces dark), then back to Minecraft — should restore light mode.
|
||||
|
||||
- [ ] **Step 4: Run formatter**
|
||||
|
||||
```bash
|
||||
npm run fmt
|
||||
```
|
||||
|
||||
If files changed, commit:
|
||||
```bash
|
||||
git add style.css index.html i18n.js theme.js
|
||||
git commit -m "style: run prettier after minecraft theme"
|
||||
```
|
||||
Reference in New Issue
Block a user