13 KiB
Animal Crossing 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 an "animal-crossing" design theme (warm cream light / deep forest dark) to the hyyzhome IoT portal.
Architecture: Four small, independent file edits. No new files created. The theme slug is registered in theme.js, a dropdown option added in index.html, CSS variables + component overrides added in style.css, and display labels added in i18n.js. Changes are order-independent but committing theme.js + index.html first lets you visually verify the option appears before styling is complete.
Tech Stack: Vanilla JS, Vite, CSS custom properties. No framework. No test suite — verification is manual in the dev server (npm start).
Files Modified
| File | Change |
|---|---|
theme.js:1 |
Add "animal-crossing" to DESIGN_THEMES array |
index.html:45 |
Add <li role="option" data-value="animal-crossing"> after the Nord option |
i18n.js:136–213 |
Add "animal-crossing" key to every language in DESIGN_THEME_LABELS |
style.css |
Append light + dark variable blocks and component overrides at end of file |
Task 1: Register the theme slug
Files:
-
Modify:
theme.js:1 -
Modify:
index.html:45 -
Step 1: Add slug to DESIGN_THEMES
In theme.js, change line 1 from:
const DESIGN_THEMES = ["fluent", "material-you", "terminal", "cyberpunk", "nord"]
to:
const DESIGN_THEMES = ["fluent", "material-you", "terminal", "cyberpunk", "nord", "animal-crossing"]
- Step 2: Add dropdown option in index.html
In index.html, after the Nord <li> (currently line 45):
<li role="option" data-value="nord" aria-selected="false">
Nord
</li>
add immediately after:
<li role="option" data-value="animal-crossing" aria-selected="false">
动森
</li>
- Step 3: Start dev server and verify option appears
npm start
Open the app in a browser. Click the design theme dropdown — "动森" should appear as a new option. Selecting it will show unstyled (inherits Fluent variables) — that's expected at this stage.
- Step 4: Commit
git add theme.js index.html
git commit -m "feat: register animal-crossing theme slug"
Task 2: Add i18n labels
Files:
-
Modify:
i18n.js:136–213 -
Step 1: Add label to every language in DESIGN_THEME_LABELS
In i18n.js, add "animal-crossing" to each language object inside DESIGN_THEME_LABELS. The full updated constant (lines 136–214) should be:
export const DESIGN_THEME_LABELS = {
"zh-Hans": {
fluent: "Fluent",
"material-you": "Material You",
terminal: "终端",
cyberpunk: "赛博朋克",
nord: "Nord",
"animal-crossing": "动森",
},
"zh-Hant": {
fluent: "Fluent",
"material-you": "Material You",
terminal: "終端",
cyberpunk: "賽博龐克",
nord: "Nord",
"animal-crossing": "動森",
},
en: {
fluent: "Fluent",
"material-you": "Material You",
terminal: "Terminal",
cyberpunk: "Cyberpunk",
nord: "Nord",
"animal-crossing": "Animal Crossing",
},
ja: {
fluent: "Fluent",
"material-you": "Material You",
terminal: "ターミナル",
cyberpunk: "サイバーパンク",
nord: "Nord",
"animal-crossing": "どうぶつの森",
},
ko: {
fluent: "Fluent",
"material-you": "Material You",
terminal: "터미널",
cyberpunk: "사이버펑크",
nord: "Nord",
"animal-crossing": "동물의 숲",
},
wenyan: {
fluent: "流光",
"material-you": "物材",
terminal: "终端",
cyberpunk: "赛博",
nord: "清寒",
"animal-crossing": "森友",
},
mars: {
fluent: "流↗光",
"material-you": "材↘質",
terminal: "終↗★端",
cyberpunk: "賽↘!博",
nord: "清↗寒★",
"animal-crossing": "动↗森★",
},
garbled: {
fluent: "◼è▦",
"material-you": "拷▤屯ä锟◽",
terminal: "¥¬▤▨¿¿",
cyberpunk: "◼çæ¥烫¥",
nord: "æ◽屯¿",
"animal-crossing": "ä◼▤è",
},
bin: {
fluent: "0101",
"material-you": "010101",
terminal: "01010101",
cyberpunk: "0101010101",
nord: "0101010",
"animal-crossing": "01010101",
},
meow: {
fluent: "喵喵",
"material-you": "喵喵喵",
terminal: "喵喵",
cyberpunk: "喵喵喵喵",
nord: "喵喵喵",
"animal-crossing": "喵喵喵喵",
},
emoji: {
fluent: "💧",
"material-you": "🧱",
terminal: "⌨️",
cyberpunk: "⚡",
nord: "❄️",
"animal-crossing": "🌿",
},
}
- Step 2: Verify labels in browser
With the dev server still running, switch language to English — the dropdown option should now read "Animal Crossing" instead of "动森". Switch to Japanese — should read "どうぶつの森". Switch to emoji — should read "🌿".
- Step 3: Commit
git add i18n.js
git commit -m "feat: add animal-crossing labels for all 11 languages"
Task 3: Add CSS — light mode
Files:
-
Modify:
style.css(append after the Nord section, before the@media (max-width: 600px)block) -
Step 1: Append light-mode CSS block
At the end of the Nord section in style.css (before the @media (max-width: 600px) rule), append:
/* ─── Animal Crossing — Sunny Meadow ───────────────────────── */
html[data-design-theme="animal-crossing"] {
color-scheme: light;
--accent: #6dbc7e;
--accent-rgb: 109, 188, 126;
--accent-2: #5aad6d;
--accent-3: #4a9e5d;
--accent-secondary-rgb: 244, 200, 66;
--page-gradient: linear-gradient(
135deg,
#fdf6e3 0%,
#f5f0d8 25%,
#fdf6e3 50%,
#f8f2e0 75%,
#fdf6e3 100%
);
--page-texture:
radial-gradient(
circle at 20% 50%,
rgba(109, 188, 126, 0.08) 0%,
transparent 50%
),
radial-gradient(
circle at 80% 80%,
rgba(244, 200, 66, 0.06) 0%,
transparent 50%
);
--title-gradient: linear-gradient(
135deg,
#6dbc7e 0%,
#5aad6d 40%,
#f4c842 100%
);
--control-bg: rgba(255, 252, 240, 0.82);
--control-border: rgba(109, 188, 126, 0.35);
--control-inset: rgba(255, 255, 255, 0.85);
--control-fg: #5c4824;
}
html[data-design-theme="animal-crossing"] body {
color: #5c4824;
}
html[data-design-theme="animal-crossing"] .design-theme-button,
html[data-design-theme="animal-crossing"] .theme-toggle {
border-radius: 14px;
}
html[data-design-theme="animal-crossing"] .card {
background: rgba(255, 252, 240, 0.85);
border: 1px solid rgba(109, 188, 126, 0.25);
border-radius: 16px;
box-shadow:
0 2px 8px rgba(0, 0, 0, 0.06),
0 1px 2px rgba(0, 0, 0, 0.03),
inset 0 1px 0 rgba(255, 255, 255, 0.9);
}
html[data-design-theme="animal-crossing"] .card::before {
display: none;
}
html[data-design-theme="animal-crossing"] .card.pin {
background: rgba(245, 242, 228, 0.88);
}
html[data-design-theme="animal-crossing"] .card h2 {
color: #5c4824;
}
html[data-design-theme="animal-crossing"] .card p {
color: #7a6040;
}
html[data-design-theme="animal-crossing"] .card:hover,
html[data-design-theme="animal-crossing"] .card:focus {
color: var(--accent);
transform: translateY(-2px);
border-color: rgba(109, 188, 126, 0.45);
box-shadow:
0 8px 24px rgba(109, 188, 126, 0.2),
0 4px 8px rgba(0, 0, 0, 0.08),
inset 0 1px 0 rgba(255, 255, 255, 0.95);
}
html[data-design-theme="animal-crossing"] .card:hover h2,
html[data-design-theme="animal-crossing"] .card:focus h2 {
color: var(--accent);
}
html[data-design-theme="animal-crossing"] .card:hover p,
html[data-design-theme="animal-crossing"] .card:focus p {
color: #5c4824;
}
html[data-design-theme="animal-crossing"] .beian a {
color: #7a6040;
}
html[data-design-theme="animal-crossing"] .beian a:hover {
color: var(--accent);
}
- Step 2: Verify light mode in browser
Select "Animal Crossing" / "动森" in the dropdown with light mode active. Verify:
-
Background is warm cream (not white/dark)
-
Title has green-to-yellow gradient
-
Cards are creamy with rounded corners (16px)
-
Card hover shows green glow and lifts up
-
Control buttons have 14px border radius
-
Step 3: Commit
git add style.css
git commit -m "feat: add animal-crossing light mode CSS"
Task 4: Add CSS — dark mode
Files:
-
Modify:
style.css(append immediately after the light-mode block from Task 3) -
Step 1: Append dark-mode CSS block
Immediately after the light-mode block (still before @media (max-width: 600px)), append:
html[data-theme="dark"][data-design-theme="animal-crossing"] {
color-scheme: dark;
--accent: #9ed98a;
--accent-rgb: 158, 217, 138;
--accent-2: #86cb72;
--accent-3: #6dbc5e;
--accent-secondary-rgb: 245, 210, 90;
--page-gradient: #1e2d1e;
--page-texture:
radial-gradient(
circle at 20% 50%,
rgba(158, 217, 138, 0.06) 0%,
transparent 50%
),
radial-gradient(
circle at 80% 80%,
rgba(245, 210, 90, 0.04) 0%,
transparent 50%
);
--title-gradient: linear-gradient(
135deg,
#9ed98a 0%,
#86cb72 40%,
#f5d25a 100%
);
--control-bg: rgba(25, 40, 25, 0.82);
--control-border: rgba(158, 217, 138, 0.25);
--control-inset: rgba(255, 255, 255, 0.04);
--control-fg: #e8f4d8;
}
html[data-theme="dark"][data-design-theme="animal-crossing"] body {
color: #e8f4d8;
}
html[data-theme="dark"][data-design-theme="animal-crossing"] .card {
background: rgba(30, 48, 30, 0.82);
border: 1px solid rgba(158, 217, 138, 0.18);
border-radius: 16px;
box-shadow:
0 2px 8px rgba(0, 0, 0, 0.3),
0 1px 2px rgba(0, 0, 0, 0.2),
inset 0 1px 0 rgba(255, 255, 255, 0.04);
}
html[data-theme="dark"][data-design-theme="animal-crossing"] .card::before {
display: none;
}
html[data-theme="dark"][data-design-theme="animal-crossing"] .card.pin {
background: rgba(38, 58, 38, 0.88);
}
html[data-theme="dark"][data-design-theme="animal-crossing"] .card h2 {
color: #e8f4d8;
}
html[data-theme="dark"][data-design-theme="animal-crossing"] .card p {
color: #b0c8a0;
}
html[data-theme="dark"][data-design-theme="animal-crossing"] .card:hover,
html[data-theme="dark"][data-design-theme="animal-crossing"] .card:focus {
border-color: rgba(158, 217, 138, 0.45);
box-shadow:
0 8px 24px rgba(158, 217, 138, 0.2),
0 4px 8px rgba(0, 0, 0, 0.3),
inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
html[data-theme="dark"][data-design-theme="animal-crossing"] .card:hover h2,
html[data-theme="dark"][data-design-theme="animal-crossing"] .card:focus h2 {
color: var(--accent);
}
html[data-theme="dark"][data-design-theme="animal-crossing"] .card:hover p,
html[data-theme="dark"][data-design-theme="animal-crossing"] .card:focus p {
color: #c8deb8;
}
html[data-theme="dark"][data-design-theme="animal-crossing"] .design-theme-list {
background: rgba(22, 36, 22, 0.9);
box-shadow:
0 12px 30px rgba(0, 0, 0, 0.55),
0 6px 12px rgba(0, 0, 0, 0.35),
inset 0 1px 0 rgba(255, 255, 255, 0.04);
}
html[data-theme="dark"][data-design-theme="animal-crossing"] .beian a {
color: #b0c8a0;
}
html[data-theme="dark"][data-design-theme="animal-crossing"] .beian a:hover {
color: var(--accent);
}
@media (prefers-reduced-motion: reduce) {
html[data-design-theme="animal-crossing"] .card,
html[data-design-theme="animal-crossing"] .design-theme-button,
html[data-design-theme="animal-crossing"] .theme-toggle {
transition-duration: 0.01ms !important;
transform: none !important;
}
}
- Step 2: Verify dark mode in browser
Toggle to dark mode while "Animal Crossing" theme is active. Verify:
-
Background is deep forest green
#1e2d1e(not generic dark grey) -
Title has soft lime-to-yellow gradient
-
Cards are dark forest green with subtle lime border
-
Card hover shows lime glow
-
Toggling back to light mode restores the cream palette
-
Step 3: Commit
git add style.css
git commit -m "feat: add animal-crossing dark mode CSS"
Task 5: Final verification
- Step 1: Check theme persists across reload
Select "Animal Crossing" in dark mode. Reload the page. Theme and dark/light preference should both be restored from localStorage.
- Step 2: Check theme switching is clean
Cycle through all 6 themes (Fluent → Material You → Terminal → Cyberpunk → Nord → Animal Crossing → Fluent). No visual artifacts or broken styles should appear at any step.
- Step 3: Check forced-dark themes restore correctly
While on Animal Crossing (light mode), switch to Terminal (forces dark). Then switch back to Animal Crossing — it should restore the light mode you had before.
- Step 4: Run formatter
npm run fmt
Confirm no diff beyond whitespace normalisation. Commit if formatter changed anything:
git add -p
git commit -m "style: run prettier after animal-crossing theme"