chore(frontend-v2): polish tokens script and drop layout scope redundancy

build-tokens.ts: import the source as .js (compatible with vue-tsc
without enabling allowImportingTsExtensions), wrap top-level await
in main(), drop a leftover unused helper. Doc strings now point to
"npm run build:tokens" — the script name avoids npm's reserved
"token" subcommand. Header in the regenerated tokens.css matches.

AppLayout, AuthLayout and PairShell: drop the redundant
"r-v2 r-v2-{dark|light}" classes from their root divs. RomM.vue
already toggles those on <html>, which covers both the in-tree
shell and any teleported overlays — anchoring them again on the
layout root was harmless duplication that complicated the v1 →
v2-only cleanup. Each layout keeps its own BEM root class
(.r-v2-shell, .r-v2-auth, .r-v2-pair-shell) for its scoped styles.
useThemeClass becomes unused and is removed; when v1 is deleted,
the only thing left to clean is the toggle in RomM.vue.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
zurdi
2026-04-28 13:12:58 +00:00
parent b3180a5aca
commit 49d01f65d6
6 changed files with 19 additions and 45 deletions

View File

@@ -3,11 +3,11 @@
*
* The TypeScript module is the single source of truth. This script declares
* the JS-path → CSS-variable mapping and writes the CSS file. Run it via
* `npm run tokens` (also wired into predev / prebuild).
* `npm run build:tokens` (also wired into predev / prebuild).
*
* Adding a new token: add it to src/v2/tokens/index.ts, then add a mapping
* entry below if the default convention does not produce the desired CSS
* variable name. Re-run `npm run tokens`.
* variable name. Re-run `npm run build:tokens`.
*/
import { writeFile, readFile } from "node:fs/promises";
import { dirname, resolve } from "node:path";
@@ -27,7 +27,7 @@ import {
motion,
radius,
space,
} from "../src/v2/tokens/index.ts";
} from "../src/v2/tokens/index.js";
const __dirname = dirname(fileURLToPath(import.meta.url));
const OUTPUT = resolve(__dirname, "../src/v2/styles/tokens.css");
@@ -38,16 +38,6 @@ function camelToKebab(s: string): string {
type Entry = [cssName: string, value: string];
function map<T extends Record<string, string>>(
obj: T,
toName: (key: keyof T & string) => string,
): Entry[] {
return Object.entries(obj).map(([k, v]) => [
toName(k as keyof T & string),
v,
]);
}
const NAME_OVERRIDES = {
space: { rowPad: "--r-row-pad" },
layout: {
@@ -133,7 +123,7 @@ const HEADER = `/*
* RomM v2 Design Tokens — CSS Custom Properties
*
* GENERATED FILE — do not hand-edit. Source: src/v2/tokens/index.ts
* Regenerate with: npm run tokens
* Regenerate with: npm run build:tokens
*
* Scoped under .r-v2 so v1 styling is unaffected. Theme palettes live under
* .r-v2.r-v2-dark and .r-v2.r-v2-light. The classes are toggled on <html>
@@ -165,10 +155,17 @@ const css = [
),
].join("\n");
const existing = await readFile(OUTPUT, "utf-8").catch(() => "");
if (existing === css) {
process.stdout.write("tokens.css up-to-date\n");
} else {
async function main() {
const existing = await readFile(OUTPUT, "utf-8").catch(() => "");
if (existing === css) {
process.stdout.write("tokens.css up-to-date\n");
return;
}
await writeFile(OUTPUT, css, "utf-8");
process.stdout.write(`tokens.css regenerated (${css.length} bytes)\n`);
}
main().catch((err) => {
console.error(err);
process.exit(1);
});

View File

@@ -1,14 +0,0 @@
// useThemeClass — returns a reactive class string ("r-v2-dark" | "r-v2-light")
// derived from the active Vuetify theme. Layouts attach it to their root
// element so theme-scoped CSS (`:global(.r-v2.r-v2-light) .foo`) flips with
// the theme.
import { computed, type ComputedRef } from "vue";
import { useTheme } from "vuetify";
import { V2_THEME_DARK } from "@/v2/theme/vuetify";
export function useThemeClass(): ComputedRef<"r-v2-dark" | "r-v2-light"> {
const theme = useTheme();
return computed(() =>
theme.global.name.value === V2_THEME_DARK ? "r-v2-dark" : "r-v2-light",
);
}

View File

@@ -18,11 +18,8 @@ import { BACKGROUND_ART_KEY } from "@/v2/composables/useBackgroundArt";
import { useGamepad } from "@/v2/composables/useGamepad";
import { useGlobalHotkeys } from "@/v2/composables/useGlobalHotkeys";
import { useInputModality } from "@/v2/composables/useInputModality";
import { useThemeClass } from "@/v2/composables/useThemeClass";
import { installBackMorph } from "@/v2/composables/useViewTransition";
const themeClass = useThemeClass();
// Shared reactive background art — views paint covers via the injected setter.
const layerA = ref<string | null>(null);
const layerB = ref<string | null>(null);
@@ -64,7 +61,7 @@ onBeforeUnmount(() => {
</script>
<template>
<div class="r-v2 r-v2-shell" :class="themeClass">
<div class="r-v2-shell">
<a href="#r-v2-main" class="r-v2-skip-link">Skip to main content</a>
<BackgroundArt

View File

@@ -4,13 +4,10 @@
// corners hold the LanguageSelector (left) and VersionTag (right).
import LanguageSelector from "@/v2/components/shared/LanguageSelector.vue";
import VersionTag from "@/v2/components/shared/VersionTag.vue";
import { useThemeClass } from "@/v2/composables/useThemeClass";
const themeClass = useThemeClass();
</script>
<template>
<div class="r-v2 r-v2-auth" :class="themeClass">
<div class="r-v2-auth">
<div class="r-v2-auth__bg" />
<main class="r-v2-auth__stage">
<router-view name="v2" />

View File

@@ -2,7 +2,7 @@
* RomM v2 Design Tokens — CSS Custom Properties
*
* GENERATED FILE — do not hand-edit. Source: src/v2/tokens/index.ts
* Regenerate with: npm run tokens
* Regenerate with: npm run build:tokens
*
* Scoped under .r-v2 so v1 styling is unaffected. Theme palettes live under
* .r-v2.r-v2-dark and .r-v2.r-v2-light. The classes are toggled on <html>

View File

@@ -4,14 +4,11 @@
// nested <router-view>; the shell inlines Pair.vue instead.
import LanguageSelector from "@/v2/components/shared/LanguageSelector.vue";
import VersionTag from "@/v2/components/shared/VersionTag.vue";
import { useThemeClass } from "@/v2/composables/useThemeClass";
import Pair from "@/v2/views/Pair.vue";
const themeClass = useThemeClass();
</script>
<template>
<div class="r-v2 r-v2-pair-shell" :class="themeClass">
<div class="r-v2-pair-shell">
<div class="r-v2-pair-shell__bg" />
<main class="r-v2-pair-shell__stage">
<Pair />