feat(t5): Bereiche mit eigenem Symbol und Ton, BrandMark, Verläufe raus (T5a A3)

AREAS (37 Bereiche, je Symbol genau einmal; neu compliance, medicines,
voice, hive-systems, system) als einzige Quelle für Kopfzeilen, Menü
und Schnellanlage; PageHeader, DetailHeader und EntityCard nehmen
area statt icon/gradient (Codemod über 72 Dateien). Doppelte Symbole
aufgelöst. BrandMark (Wabe) ersetzt das Verlaufs-Sechseck;
Honig-Banner auf der Startseite durch Überschrift mit Datum ersetzt;
Verläufe aus 33 Verbrauchern entfernt (Token folgen in A4).

Refs #26

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Nick.RosenloecherandClaude Opus 5.5 committed 2026-10-16 16:47:56 +02:00
1 parent cf53cf35ac
commit 258e90828f
97 files changed
+732 -395

No files matched your search

@@ -0,0 +1,70 @@
import { readdirSync, readFileSync, statSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
const SRC = join(__dirname, "..");
function sourceFiles(dir: string): string[] {
return readdirSync(dir).flatMap((name) => {
const path = join(dir, name);
if (statSync(path).isDirectory()) {
return sourceFiles(path);
}
return /\.(tsx?|css)$/.test(name) && !/\.spec\./.test(name) ? [path] : [];
});
}
function read(relative: string): string {
return readFileSync(join(SRC, relative), "utf8");
}
describe("area migration", () => {
it("no file passes a gradient prop any more", () => {
const offenders = sourceFiles(SRC).filter((file) => {
const text = readFileSync(file, "utf8");
return /gradient=|var\(--gradient-|\[background-image:var\(--gradient/.test(text);
});
expect(offenders).toEqual([]);
});
it("no source other than globals.css uses the --gradient tokens", () => {
const offenders = sourceFiles(SRC)
.filter((file) => !file.endsWith("globals.css"))
.filter((file) => /--gradient-(honey|sage|sky)/.test(readFileSync(file, "utf8")));
expect(offenders).toEqual([]);
});
it("harvest detail uses Scissors, extraction create FlaskConical and storage only Warehouse", () => {
expect(read("app/(app)/harvests/[id]/page.tsx")).toContain('area="harvests"');
expect(read("app/(app)/extractions/new/page.tsx")).toContain('area="extractions"');
const storage = read("app/(app)/storage/page.tsx");
expect(storage).toContain('area="storage"');
expect(storage).not.toMatch(/icon=\{Package\}/);
});
it("medicine packs, hive systems and voice settings use their own area icon", () => {
expect(read("app/(app)/medicines/[id]/page.tsx")).not.toMatch(/icon=\{Package\}/);
expect(read("app/(app)/medicines/lots/[id]/page.tsx")).toContain('area="medicines"');
expect(read("app/(app)/settings/hive-systems/page.tsx")).toContain('area="hive-systems"');
expect(read("app/(app)/settings/voice/page.tsx")).toContain('area="voice"');
});
it("no component passes a raw icon to the headers any more", () => {
const offenders = sourceFiles(SRC).filter((file) => {
const text = readFileSync(file, "utf8");
return /<(PageHeader|DetailHeader|EntityCard)\b[^>]*\bicon=/.test(text);
});
expect(offenders).toEqual([]);
});
it("no white text outside the hive stage", () => {
const offenders = sourceFiles(SRC)
.filter((file) => !file.replaceAll("\\", "/").includes("/components/hive/"))
.filter((file) => /\btext-white\b/.test(readFileSync(file, "utf8")));
expect(offenders).toEqual([]);
});
it("the stage overlay on the hive stage uses the holo label colour instead of white", () => {
expect(read("components/hive/editor/editor-stage-overlay.tsx")).not.toMatch(/\btext-white\b/);
});
});