Files
teamwallet/myteamwallet_frontend/docs/superpowers/plans/2026-07-31-design-foundation.md
Bastian Wagner 6bea4f766a first commit
2026-07-31 21:02:47 +02:00

15 KiB

Design-System-Fundament 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: Legt die technische und visuelle Basis für das TeamWallet-Redesign: Design-Tokens, ein eigenes Material-3-Theme (fintech-modern, Indigo/Grün), ein konsistentes Icon-System und ein bereinigtes Notification-System — ohne die bestehenden Bildschirme inhaltlich umzubauen (das folgt in Folge-Plänen für Public-Übersicht, Dashboard/Team-Workspace, Auth-Flows).

Architecture: Zwei neue SCSS-Partials (src/styles/_tokens.scss, src/styles/_theme.scss) werden aus src/styles.scss eingebunden. Die Angular-Material-Theming-API (mat.define-theme, installiert in node_modules/@angular/material/core/theming/_definition.scss) erzeugt das Theme aus vordefinierten M3-Paletten (mat.$blue-palette als Primary, mat.$spring-green-palette als Tertiary) statt des Stock-Themes azure-blue. Reine CSS-Custom-Properties (nicht Sass-Variablen) tragen Spacing/Radius/Elevation/Balance-Farben, damit sie direkt in Komponenten-Templates/-Styles nutzbar sind, auch außerhalb von Sass-Kontext.

Tech Stack: Angular 18.1, Angular Material 18.1 (M3-Theming-API), SCSS, Angular CLI Builder (@angular-devkit/build-angular:browser), Karma/Jasmine.

Global Constraints

  • Kein Dark Mode in diesem Plan — Tokens müssen aber so benannt/strukturiert sein, dass ein späteres Dark-Theme sie überschreiben kann (semantische Namen, keine rohen Paletten-Referenzen in Komponenten).
  • Keine neuen Abhängigkeiten hinzufügen; stattdessen wird die ungenutzte Abhängigkeit @ngxpert/hot-toast entfernt.
  • Bestehende deutsche UI-Texte bleiben unverändert (i18n-Audit ist ein separater Folge-Plan).
  • Nach jedem Task muss npm run build (aus myteamwallet_frontend/) fehlerfrei durchlaufen.
  • Angular Material 18 M3-Theming bietet keine Funktion, aus einem beliebigen Hex-Wert eine Palette zu generieren (verifiziert: _palettes.scss enthält nur die zwölf vordefinierten Paletten red/green/blue/yellow/cyan/magenta/orange/chartreuse/spring-green/azure/violet/rose). Primary/Tertiary werden daher aus diesen vordefinierten Paletten gewählt, nicht aus Wunsch-Hexcodes.

Task 1: Design-Tokens (Spacing, Radius, Elevation, Balance-Farben)

Files:

  • Create: myteamwallet_frontend/src/styles/_tokens.scss
  • Modify: myteamwallet_frontend/src/styles.scss

Interfaces:

  • Produces: CSS-Custom-Properties auf :root--tw-space-{1,2,3,4,6,8}, --tw-radius-{sm,md,lg}, --tw-elevation-{1,2}, --tw-balance-positive, --tw-balance-negative, --tw-balance-neutral, --tw-surface-bg, --tw-surface-card. Alle Folge-Tasks/-Pläne referenzieren ausschließlich diese Namen, nie rohe Hex-Werte.

  • Step 1: _tokens.scss anlegen

// myteamwallet_frontend/src/styles/_tokens.scss
:root {
  // Spacing (8px-Grid)
  --tw-space-1: 4px;
  --tw-space-2: 8px;
  --tw-space-3: 12px;
  --tw-space-4: 16px;
  --tw-space-6: 24px;
  --tw-space-8: 32px;

  // Radius
  --tw-radius-sm: 8px;
  --tw-radius-md: 12px;
  --tw-radius-lg: 16px;

  // Elevation (ersetzt die bisher wiederholte box-shadow-Deklaration)
  --tw-elevation-1: 0 1px 2px rgba(15, 23, 42, 0.06), 0 1px 3px rgba(15, 23, 42, 0.1);
  --tw-elevation-2: 0 2px 4px rgba(15, 23, 42, 0.06), 0 4px 8px rgba(15, 23, 42, 0.1);

  // Semantische Saldo-Farben (fintech-modern: gedämpftes Grün/Rot statt Signalfarben)
  --tw-balance-positive: #1b8a5a;
  --tw-balance-negative: #c4351c;
  --tw-balance-neutral: #64748b;

  // Flächen
  --tw-surface-bg: #f7f8fa;
  --tw-surface-card: #ffffff;
}
  • Step 2: In styles.scss einbinden und bestehende Hardcodes ersetzen

In myteamwallet_frontend/src/styles.scss ganz oben ergänzen:

@use './styles/tokens';

Danach folgende bestehende Stellen in derselben Datei ersetzen:

// vorher: body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; background-color: #fafafa;}
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; background-color: var(--tw-surface-bg); }
// vorher in .card:
// box-shadow: 0 2px 1px -1px #0003, 0 1px 1px #00000024, 0 1px 3px #0000001f;
.card {
  padding: var(--tw-space-3);
  box-shadow: var(--tw-elevation-1);
  margin: var(--tw-space-1);
  background-color: var(--tw-surface-card);
  border-radius: var(--tw-radius-md);

  &.flat {
    background-color: transparent;
    box-shadow: none;
    outline: #ddd solid 1px;
  }
}
// vorher: background-color: rgb(148, 16, 16) !important;
.snackbar_error > .mdc-snackbar__surface {
  background-color: var(--tw-balance-negative) !important;

  .mat-mdc-snack-bar-label {
    color: white !important;
  }
}
  • Step 3: Build verifizieren

Run: cd myteamwallet_frontend && npm run build Expected: Build erfolgreich, keine Sass-/Compile-Fehler.

  • Step 4: Commit
git add myteamwallet_frontend/src/styles/_tokens.scss myteamwallet_frontend/src/styles.scss
git commit -m "feat(design): add design tokens and wire into global styles"

Task 2: Eigenes Material-3-Theme statt Stock-Theme

Files:

  • Create: myteamwallet_frontend/src/styles/_theme.scss
  • Modify: myteamwallet_frontend/src/styles.scss
  • Modify: myteamwallet_frontend/angular.json:35 (build-Styles), myteamwallet_frontend/angular.json:125 (test-Styles)
  • Modify: myteamwallet_frontend/src/index.html

Interfaces:

  • Consumes: nichts aus Task 1 direkt (unabhängiges Partial), wird aber in derselben styles.scss eingebunden.

  • Produces: Sass-Variable theme.$teamwallet-theme, die alle Material-Komponentenstyles erzeugt. Spätere Pläne fügen hier bei Bedarf mat.theme-overrides() hinzu, ändern aber nicht den Namen $teamwallet-theme.

  • Step 1: _theme.scss anlegen

// myteamwallet_frontend/src/styles/_theme.scss
@use '@angular/material' as mat;

$teamwallet-theme: mat.define-theme((
  color: (
    theme-type: light,
    primary: mat.$blue-palette,
    tertiary: mat.$spring-green-palette,
  ),
  typography: (
    brand-family: 'Inter, Roboto, "Helvetica Neue", sans-serif',
    plain-family: 'Inter, Roboto, "Helvetica Neue", sans-serif',
  ),
  density: (
    scale: 0,
  ),
));
  • Step 2: Theme in styles.scss einbinden (ersetzt Stock-Theme-Import)

Am Anfang von myteamwallet_frontend/src/styles.scss ergänzen (vor den bestehenden Regeln):

@use '@angular/material' as mat;
@use './styles/theme';

@include mat.core();
@include mat.all-component-themes(theme.$teamwallet-theme);
  • Step 3: Stock-Theme aus angular.json entfernen

In myteamwallet_frontend/angular.json im build-Target die Zeile entfernen:

"@angular/material/prebuilt-themes/azure-blue.css",

Im test-Target die Zeile entfernen:

"@angular/material/prebuilt-themes/cyan-orange.css",

In beiden Targets bleibt "src/styles.scss" als einziger globaler Stylesheet-Eintrag stehen.

  • Step 4: Google-Font auf Inter umstellen

In myteamwallet_frontend/src/index.html die bestehende Roboto-Zeile ersetzen:

<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
  • Step 5: Build und Tests verifizieren

Run: cd myteamwallet_frontend && npm run build Expected: Build erfolgreich, Material-Komponenten (Buttons, Toolbar, Cards) werden aus dem neuen Theme gestylt statt aus azure-blue.css.

Run: cd myteamwallet_frontend && npm test -- --watch=false Expected: Bestehende Karma-Suite läuft weiterhin durch (keine Test-Regression durch den Theme-Wechsel).

  • Step 6: Commit
git add myteamwallet_frontend/src/styles/_theme.scss myteamwallet_frontend/src/styles.scss myteamwallet_frontend/angular.json myteamwallet_frontend/src/index.html
git commit -m "feat(design): replace stock Material azure-blue theme with custom M3 theme"

Task 3: Icon-System auf Material Symbols umstellen, PNG-Icon-Klassen entfernen

Files:

  • Modify: myteamwallet_frontend/src/index.html
  • Modify: myteamwallet_frontend/src/app/app.component.ts
  • Modify: myteamwallet_frontend/src/app/modules/home/dashboard/dashboard.component.ts
  • Modify: myteamwallet_frontend/src/app/modules/home/dashboard/dashboard.component.html
  • Modify: myteamwallet_frontend/src/styles.scss
  • Delete: myteamwallet_frontend/src/assets/edit.png, myteamwallet_frontend/src/assets/dashboard.png, myteamwallet_frontend/src/assets/tacho.png

Interfaces:

  • Consumes: nichts.

  • Produces: <mat-icon>-basierte Icons überall; keine PNG-Icon-Klassen (icon, icon_edit, icon_dashboard, icon_tacho) mehr im Code. Verifiziert: diese Klassen werden ausschließlich in dashboard.component.html verwendet (icon_tacho, icon_edit; icon_dashboard ist bereits toter Code).

  • Step 1: Material Symbols statt Material Icons laden

In myteamwallet_frontend/src/index.html die Material-Icons-Zeile ersetzen:

<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap" rel="stylesheet">
  • Step 2: Default-Fontset der App auf Material Symbols umstellen

In myteamwallet_frontend/src/app/app.component.ts:

import { Component } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { environment } from './../environments/environment';
import { SwUpdate } from '@angular/service-worker';
import { MatIconRegistry } from '@angular/material/icon';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  version = environment.appVersion;

  constructor(translate: TranslateService, updates: SwUpdate, iconRegistry: MatIconRegistry) {
    iconRegistry.setDefaultFontSetClass('material-symbols-outlined');
    translate.setDefaultLang('de');
    translate.use('de');
    this.update(updates);
  }
  // ... rest unverändert

(Restlichen Methodenkörper update() unverändert lassen.)

  • Step 3: Dashboard-Icons auf mat-icon umstellen

In myteamwallet_frontend/src/app/modules/home/dashboard/dashboard.component.ts MatIconModule importieren:

import { MatIconModule } from '@angular/material/icon';
// ...
@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.scss'],
  standalone: true,
  imports: [ CommonModule, TranslateModule, MatButtonModule, MatIconModule ]
})

In myteamwallet_frontend/src/app/modules/home/dashboard/dashboard.component.html ersetzen:

<!-- vorher -->
<div class="icons">
  <div class="icon icon_tacho" matRipple (click)="onTeamClick(p.team)"></div>
  <div class="icon icon_edit" matRipple (click)="onTeamClick(p.team)"></div>
</div>
<!-- nachher -->
<div class="icons">
  <button mat-icon-button (click)="onTeamClick(p.team)" aria-label="Team-Details öffnen">
    <mat-icon>speed</mat-icon>
  </button>
  <button mat-icon-button (click)="onTeamClick(p.team)" aria-label="Team bearbeiten">
    <mat-icon>edit</mat-icon>
  </button>
</div>
  • Step 4: Tote Icon-Klassen aus styles.scss entfernen

In myteamwallet_frontend/src/styles.scss den gesamten Block entfernen:

.icon { ... }
.icon_edit { ... }
.icon_dashboard { ... }
.icon_tacho { ... }

(Alle vier Regeln inkl. der .icon:hover-Verschachtelung löschen — keine andere Datei referenziert diese Klassen mehr.)

  • Step 5: Ungenutzte PNG-Assets löschen
git rm myteamwallet_frontend/src/assets/edit.png myteamwallet_frontend/src/assets/dashboard.png myteamwallet_frontend/src/assets/tacho.png
  • Step 6: Build verifizieren und visuell prüfen

Run: cd myteamwallet_frontend && npm run build Expected: Build erfolgreich, keine fehlenden Asset-Referenzen.

Run: cd myteamwallet_frontend && npm start, Dashboard im Browser öffnen (http://localhost:4200/dashboard, eingeloggt). Expected: Statt der beiden PNG-Icons erscheinen die Material-Symbols-Icons „speed“ und „edit“, klickbar wie zuvor.

  • Step 7: Commit
git add myteamwallet_frontend/src/index.html myteamwallet_frontend/src/app/app.component.ts myteamwallet_frontend/src/app/modules/home/dashboard/dashboard.component.ts myteamwallet_frontend/src/app/modules/home/dashboard/dashboard.component.html myteamwallet_frontend/src/styles.scss
git commit -m "feat(design): migrate to Material Symbols, remove PNG icon classes"

Task 4: Notification-System bereinigen

Files:

  • Modify: myteamwallet_frontend/package.json

Interfaces:

  • Consumes: --tw-balance-negative-Token aus Task 1 (bereits in .snackbar_error verdrahtet).
  • Produces: keine neuen Symbole — reine Bereinigung.

Verifiziert: @ngxpert/hot-toast ist in package.json als Abhängigkeit deklariert, wird aber im gesamten src/-Verzeichnis nirgends importiert (HotToastService/@ngxpert/hot-toast liefert null Treffer). Es gibt also kein zweites, konkurrierendes Toast-System im Code — nur eine tote Abhängigkeit. Die tatsächliche Benachrichtigung läuft ausschließlich über MatSnackBar (3 Aufrufstellen, alle in team-details.component.ts), deren Fehler-Variante bereits in Task 1 auf den neuen Token umgestellt wurde.

  • Step 1: Ungenutzte Abhängigkeit entfernen

In myteamwallet_frontend/package.json die Zeile aus dependencies entfernen:

"@ngxpert/hot-toast": "3.0.0",
  • Step 2: Lockfile aktualisieren

Run: cd myteamwallet_frontend && npm install Expected: package-lock.json aktualisiert sich, @ngxpert/hot-toast verschwindet aus dem Dependency-Baum, keine anderen Pakete werden unerwartet verändert.

  • Step 3: Build verifizieren

Run: cd myteamwallet_frontend && npm run build Expected: Build weiterhin erfolgreich (bestätigt, dass das Paket wirklich ungenutzt war).

  • Step 4: Commit
git add myteamwallet_frontend/package.json myteamwallet_frontend/package-lock.json
git commit -m "chore(deps): remove unused @ngxpert/hot-toast dependency"

Hinweis für Folge-Pläne

Die Wrapper-Komponenten-Bibliothek (BalanceDisplay, PageHeader, SectionCard, EmptyState, StatTile aus dem Gesamtplan) wird bewusst nicht in diesem Fundament-Plan gebaut, sondern erst in dem Folge-Plan, der ihren ersten echten Verwendungsort umbaut (Public-Team-Übersicht bzw. Dashboard/Team-Workspace) — YAGNI: eine Komponenten-Bibliothek ohne Konsumenten lässt sich nicht sinnvoll gegen echte Anforderungen entwerfen. Dieser Fundament-Plan liefert die Basis (Tokens, Theme, Icons, saubere Notifications), auf der diese Komponenten aufbauen.