From 1601d97f629568eeaf515c5f7be841c778d59c67 Mon Sep 17 00:00:00 2001 From: Schalli Date: Thu, 17 Sep 2026 12:15:33 +0200 Subject: [PATCH] =?UTF-8?q?feat(brand):=20gedrehte=20Kachel=20der=20Bildma?= =?UTF-8?q?rke=20=C3=BCbernimmt=20die=20Akzentfarbe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LogoMark: gedrehte Signalkachel per Inline-Style fill: var(--primary, BRAND_YELLOW) statt festem fill-Attribut - folgt damit der persoenlichen Akzentfarbe (applyAccentColor in auth-store.ts) in Kopfzeile, Seitenleiste und leerem Dashboard; ohne Nutzer (Anmeldeseite) gilt der CSS-Standard Markengelb - brand.ts: Kommentar zu BRAND_YELLOW als Rueckfallwert ergaenzt - tessera-logo.test.tsx: Kacheltest auf Inline-Style-Fuellung umgeschrieben (jsdom haelt var() in style.fill) Co-Authored-By: Claude Opus 5 (1M context) --- apps/web/src/components/brand/brand.ts | 7 ++++++- .../components/brand/tessera-logo.test.tsx | 20 ++++++++++++++----- .../web/src/components/brand/tessera-logo.tsx | 12 ++++++++++- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/apps/web/src/components/brand/brand.ts b/apps/web/src/components/brand/brand.ts index 3c9613f..1391a6a 100644 --- a/apps/web/src/components/brand/brand.ts +++ b/apps/web/src/components/brand/brand.ts @@ -8,7 +8,12 @@ * mandantenspezifische Gestaltung setzt an dieser Datei an. */ -/** Gelbwert der gedrehten Signalkachel. */ +/** + * Standard-Gelb der gedrehten Signalkachel und Rueckfall, wenn keine + * persoenliche Akzentfarbe (`--primary`) gesetzt ist. Die Kachel selbst wird + * in tessera-logo.tsx per `style={{ fill: var(--primary, BRAND_YELLOW) }}` + * gefuellt -- nicht mehr per festem `fill`-Praesentationsattribut. + */ export const BRAND_YELLOW = '#ffed00'; /** Olivton der vier achsenparallelen Kacheln. */ diff --git a/apps/web/src/components/brand/tessera-logo.test.tsx b/apps/web/src/components/brand/tessera-logo.test.tsx index 48e24f3..1b95753 100644 --- a/apps/web/src/components/brand/tessera-logo.test.tsx +++ b/apps/web/src/components/brand/tessera-logo.test.tsx @@ -1,6 +1,6 @@ import { cleanup, render, screen } from '@testing-library/react'; import { afterEach, describe, expect, it, vi } from 'vitest'; -import { BRAND_YELLOW } from './brand'; +import { BRAND_OLIVE, BRAND_YELLOW } from './brand'; import { TesseraLogo } from './tessera-logo'; import de from '@/messages/de.json'; import en from '@/messages/en.json'; @@ -94,18 +94,28 @@ describe('TesseraLogo', () => { expect(plate?.getAttribute('class')).not.toContain('dark:stroke-white/25'); }); - it('renders exactly five tiles, exactly one in the brand yellow and exactly one rotated', () => { + it('renders exactly five tiles; only the rotated one is filled from the accent token with the brand yellow as fallback', () => { render(); const mark = screen.getByRole('img', { name: 'Tessera Logo' }); - const tiles = Array.from(mark.querySelectorAll('g rect')); + const tiles = Array.from(mark.querySelectorAll('g rect')) as SVGRectElement[]; expect(tiles).toHaveLength(5); - const yellowTiles = tiles.filter((tile) => tile.getAttribute('fill') === BRAND_YELLOW); - expect(yellowTiles).toHaveLength(1); + const accentTiles = tiles.filter((tile) => tile.style.fill === `var(--primary, ${BRAND_YELLOW})`); + expect(accentTiles).toHaveLength(1); + expect(accentTiles[0].hasAttribute('transform')).toBe(true); const rotatedTiles = tiles.filter((tile) => tile.hasAttribute('transform')); expect(rotatedTiles).toHaveLength(1); + + const presentationYellowTiles = tiles.filter((tile) => tile.getAttribute('fill') === BRAND_YELLOW); + expect(presentationYellowTiles).toHaveLength(0); + + const oliveTiles = tiles.filter((tile) => tile.getAttribute('fill') === BRAND_OLIVE); + expect(oliveTiles).toHaveLength(4); + for (const tile of oliveTiles) { + expect(tile.getAttribute('style')).toBeNull(); + } }); }); diff --git a/apps/web/src/components/brand/tessera-logo.tsx b/apps/web/src/components/brand/tessera-logo.tsx index c497c68..89b49d5 100644 --- a/apps/web/src/components/brand/tessera-logo.tsx +++ b/apps/web/src/components/brand/tessera-logo.tsx @@ -69,6 +69,13 @@ function LogoMark({ + {/* + `var()` ist in SVG-Praesentationsattributen (fill="...") nicht + zuverlaessig, im Inline-Style schon — deshalb hier style statt fill. + `--primary` wird von applyAccentColor() in auth-store.ts gesetzt; + ohne angemeldeten Nutzer (z. B. Anmeldeseite) ist der Token nicht + definiert und der Rueckfall in var() greift: BRAND_YELLOW. + */} @@ -90,6 +97,9 @@ function LogoMark({ * Schriftzug und deren Anordnung an einer einzigen Stelle -- eine spaetere * mandantenspezifische Gestaltung setzt hier an, nicht an den einzelnen * Verwendungsstellen. + * + * Die gedrehte Signalkachel der Bildmarke folgt der persoenlichen + * Akzentfarbe (CSS-Token `--primary`, siehe LogoMark). */ export function TesseraLogo({ variant = 'horizontal',