feat(quick-260907-fgv-02): sechs Marken-Stellen auf TesseraLogo umgestellt, Gelbwert zusammengefuehrt
- header.tsx, sidebar.tsx (Schublade), login/page.tsx (breit + schmal), reset-password/page.tsx, reset-password/[token]/page.tsx ziehen jetzt alle TesseraLogo statt eines von Hand gesetzten Schriftzugs - login/page.tsx: handgezeichneter Vier-Quadrate-Platzhalter entfernt, gelbes Panel nutzt BRAND_YELLOW per Inline-Style statt eigener Tailwind-Klasse, Kopfkommentar ohne Farbwert neu formuliert - account-settings-form.tsx: DEFAULT_ACCENT liest jetzt BRAND_YELLOW statt eines eigenen Literals - tessera-logo.tsx: Schriftzug setzt keine eigene Textfarbe mehr, sondern erbt sie vom umgebenden Container (Rule 1 -- ohne diese Korrektur waere der Schriftzug auf dem immer gelben Anmelde-Panel im dunklen Erscheinungsbild unlesbar hell auf hell gewesen) - sidebar.tsx: nicht mehr benoetigtes tCommon entfernt; sidebar.test.tsx um common.brand.logoAlt in der Uebersetzungs-Attrappe ergaenzt - vollstaendige Web-Testsuite (221 Tests) und Typpruefung gruen Docker-Neubau und Browser-Abnahme (curl-Health-Check gegen den lokalen Container) bewusst ausgelassen -- der Orchestrator uebernimmt beides in Task 3. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K5jtbGzC5Sf9npJ3JCjKhq
This commit is contained in:
@@ -5,10 +5,12 @@ import { useTranslations } from 'next-intl';
|
|||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { login } from '@/lib/auth-actions';
|
import { login } from '@/lib/auth-actions';
|
||||||
|
import { BRAND_YELLOW } from '@/components/brand/brand';
|
||||||
|
import { TesseraLogo } from '@/components/brand/tessera-logo';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Split-screen login page (D-01).
|
* Split-screen login page (D-01).
|
||||||
* Left: Tessera branding with primary yellow (#ffed00) background.
|
* Left: Tessera branding on the brand yellow background (BRAND_YELLOW).
|
||||||
* Right: Login form on neutral background.
|
* Right: Login form on neutral background.
|
||||||
* No sidebar or header (D-04, handled by (auth) layout).
|
* No sidebar or header (D-04, handled by (auth) layout).
|
||||||
*/
|
*/
|
||||||
@@ -37,35 +39,15 @@ export default function LoginPage() {
|
|||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen">
|
<div className="flex min-h-screen">
|
||||||
{/* Left: Branding panel (hidden on mobile, visible on md+) */}
|
{/* Left: Branding panel (hidden on mobile, visible on md+) */}
|
||||||
<div className="hidden md:flex md:flex-1 items-center justify-center bg-[#ffed00]">
|
<div
|
||||||
<div className="flex flex-col items-center gap-6 px-8 text-center">
|
className="hidden md:flex md:flex-1 items-center justify-center"
|
||||||
{/* Tessera logo / text */}
|
style={{ backgroundColor: BRAND_YELLOW }}
|
||||||
<h1 className="text-6xl font-extrabold text-gray-900 tracking-tight">
|
>
|
||||||
Tessera
|
<div className="flex flex-col items-center gap-6 px-8 text-center text-gray-900">
|
||||||
</h1>
|
<TesseraLogo variant="stacked" size={112} plateOutline={false} />
|
||||||
<p className="text-xl text-gray-800 max-w-md leading-relaxed">
|
<p className="text-xl text-gray-800 max-w-md leading-relaxed">
|
||||||
{t('branding.tagline')}
|
{t('branding.tagline')}
|
||||||
</p>
|
</p>
|
||||||
{/* Abstract grid icon representing modules */}
|
|
||||||
<div className="mt-4">
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="80"
|
|
||||||
height="80"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.5"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
className="text-gray-800 opacity-50"
|
|
||||||
>
|
|
||||||
<rect x="3" y="3" width="7" height="7" rx="1" />
|
|
||||||
<rect x="14" y="3" width="7" height="7" rx="1" />
|
|
||||||
<rect x="14" y="14" width="7" height="7" rx="1" />
|
|
||||||
<rect x="3" y="14" width="7" height="7" rx="1" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -74,9 +56,7 @@ export default function LoginPage() {
|
|||||||
<div className="w-full max-w-sm space-y-8">
|
<div className="w-full max-w-sm space-y-8">
|
||||||
{/* Mobile-only branding */}
|
{/* Mobile-only branding */}
|
||||||
<div className="text-center md:hidden">
|
<div className="text-center md:hidden">
|
||||||
<h1 className="text-3xl font-extrabold text-primary tracking-tight">
|
<TesseraLogo variant="horizontal" size={32} />
|
||||||
Tessera
|
|
||||||
</h1>
|
|
||||||
<p className="mt-2 text-sm text-muted-foreground">
|
<p className="mt-2 text-sm text-muted-foreground">
|
||||||
{t('branding.tagline')}
|
{t('branding.tagline')}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useState, useTransition, useEffect } from 'react';
|
|||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
import { TesseraLogo } from '@/components/brand/tessera-logo';
|
||||||
|
|
||||||
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001';
|
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001';
|
||||||
|
|
||||||
@@ -81,9 +82,7 @@ export default function ResetPasswordTokenPage() {
|
|||||||
<div className="w-full max-w-sm space-y-8">
|
<div className="w-full max-w-sm space-y-8">
|
||||||
{/* Heading */}
|
{/* Heading */}
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<h1 className="text-3xl font-extrabold text-primary tracking-tight">
|
<TesseraLogo variant="horizontal" size={32} />
|
||||||
Tessera
|
|
||||||
</h1>
|
|
||||||
<h2 className="mt-4 text-2xl font-bold text-foreground">
|
<h2 className="mt-4 text-2xl font-bold text-foreground">
|
||||||
{t('resetPassword.newPasswordTitle')}
|
{t('resetPassword.newPasswordTitle')}
|
||||||
</h2>
|
</h2>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import { useState, useTransition } from 'react';
|
import { useState, useTransition } from 'react';
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
import { TesseraLogo } from '@/components/brand/tessera-logo';
|
||||||
|
|
||||||
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001';
|
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001';
|
||||||
|
|
||||||
@@ -52,9 +53,7 @@ export default function ResetPasswordPage() {
|
|||||||
<div className="w-full max-w-sm space-y-8">
|
<div className="w-full max-w-sm space-y-8">
|
||||||
{/* Heading */}
|
{/* Heading */}
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<h1 className="text-3xl font-extrabold text-primary tracking-tight">
|
<TesseraLogo variant="horizontal" size={32} />
|
||||||
Tessera
|
|
||||||
</h1>
|
|
||||||
<h2 className="mt-4 text-2xl font-bold text-foreground">
|
<h2 className="mt-4 text-2xl font-bold text-foreground">
|
||||||
{t('resetPassword.title')}
|
{t('resetPassword.title')}
|
||||||
</h2>
|
</h2>
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ export function TesseraLogo({
|
|||||||
<span className={`inline-flex flex-col items-center gap-2 ${className ?? ''}`}>
|
<span className={`inline-flex flex-col items-center gap-2 ${className ?? ''}`}>
|
||||||
<LogoMark size={size} plateOutline={plateOutline} ariaLabel={ariaLabel} />
|
<LogoMark size={size} plateOutline={plateOutline} ariaLabel={ariaLabel} />
|
||||||
<span
|
<span
|
||||||
className={`text-2xl font-bold tracking-tight text-foreground ${wordmarkClassName ?? ''}`}
|
className={`text-2xl font-bold tracking-tight ${wordmarkClassName ?? ''}`}
|
||||||
>
|
>
|
||||||
{t('appName')}
|
{t('appName')}
|
||||||
</span>
|
</span>
|
||||||
@@ -121,7 +121,7 @@ export function TesseraLogo({
|
|||||||
<span className={`inline-flex items-center gap-2 ${className ?? ''}`}>
|
<span className={`inline-flex items-center gap-2 ${className ?? ''}`}>
|
||||||
<LogoMark size={size} plateOutline={plateOutline} ariaLabel={ariaLabel} />
|
<LogoMark size={size} plateOutline={plateOutline} ariaLabel={ariaLabel} />
|
||||||
<span
|
<span
|
||||||
className={`font-bold tracking-tight text-foreground ${wordmarkClassName ?? ''}`}
|
className={`font-bold tracking-tight ${wordmarkClassName ?? ''}`}
|
||||||
>
|
>
|
||||||
{t('appName')}
|
{t('appName')}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
|
import { TesseraLogo } from '@/components/brand/tessera-logo';
|
||||||
import { useSidebarStore } from '@/lib/stores/sidebar-store';
|
import { useSidebarStore } from '@/lib/stores/sidebar-store';
|
||||||
import { useAuthStore } from '@/lib/stores/auth-store';
|
import { useAuthStore } from '@/lib/stores/auth-store';
|
||||||
import { fetchCurrentUser, logout } from '@/lib/auth-actions';
|
import { fetchCurrentUser, logout } from '@/lib/auth-actions';
|
||||||
@@ -88,9 +89,7 @@ export function Header() {
|
|||||||
<line x1="3" y1="18" x2="21" y2="18" />
|
<line x1="3" y1="18" x2="21" y2="18" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<span className="text-lg font-bold text-primary">
|
<TesseraLogo variant="horizontal" size={28} />
|
||||||
{t('common.appName')}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Center: Breadcrumb / page title */}
|
{/* Center: Breadcrumb / page title */}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ vi.mock('next-intl', () => ({
|
|||||||
},
|
},
|
||||||
common: {
|
common: {
|
||||||
appName: 'Tessera',
|
appName: 'Tessera',
|
||||||
|
'brand.logoAlt': 'Tessera Logo',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return map[ns]?.[key] ?? key;
|
return map[ns]?.[key] ?? key;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { usePathname } from 'next/navigation';
|
import { usePathname } from 'next/navigation';
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
|
import { TesseraLogo } from '@/components/brand/tessera-logo';
|
||||||
import { useSidebarStore } from '@/lib/stores/sidebar-store';
|
import { useSidebarStore } from '@/lib/stores/sidebar-store';
|
||||||
import { useMarketplaceStore } from '@/lib/stores/marketplace-store';
|
import { useMarketplaceStore } from '@/lib/stores/marketplace-store';
|
||||||
import { SidebarSearch } from '@/components/layout/sidebar-search';
|
import { SidebarSearch } from '@/components/layout/sidebar-search';
|
||||||
@@ -19,7 +20,6 @@ interface SidebarModule {
|
|||||||
|
|
||||||
export function Sidebar() {
|
export function Sidebar() {
|
||||||
const t = useTranslations('sidebar');
|
const t = useTranslations('sidebar');
|
||||||
const tCommon = useTranslations('common');
|
|
||||||
const { isCollapsed, isMobileOpen, toggle, setMobileOpen } = useSidebarStore();
|
const { isCollapsed, isMobileOpen, toggle, setMobileOpen } = useSidebarStore();
|
||||||
const [activeModules, setActiveModules] = useState<SidebarModule[]>([]);
|
const [activeModules, setActiveModules] = useState<SidebarModule[]>([]);
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
const [searchQuery, setSearchQuery] = useState('');
|
||||||
@@ -223,9 +223,7 @@ export function Sidebar() {
|
|||||||
/>
|
/>
|
||||||
<aside className="fixed left-0 top-0 z-50 h-full w-[var(--sidebar-width)] bg-sidebar shadow-lg">
|
<aside className="fixed left-0 top-0 z-50 h-full w-[var(--sidebar-width)] bg-sidebar shadow-lg">
|
||||||
<div className="flex h-[var(--header-height)] items-center justify-between border-b border-sidebar-border px-4">
|
<div className="flex h-[var(--header-height)] items-center justify-between border-b border-sidebar-border px-4">
|
||||||
<span className="text-lg font-bold text-primary">
|
<TesseraLogo variant="horizontal" size={28} />
|
||||||
{tCommon('appName')}
|
|
||||||
</span>
|
|
||||||
<button
|
<button
|
||||||
onClick={() => setMobileOpen(false)}
|
onClick={() => setMobileOpen(false)}
|
||||||
className="rounded-md p-2 text-muted-foreground hover:bg-muted hover:text-foreground transition-colors"
|
className="rounded-md p-2 text-muted-foreground hover:bg-muted hover:text-foreground transition-colors"
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ import {
|
|||||||
updateAccentColorAction,
|
updateAccentColorAction,
|
||||||
} from '@/lib/auth-actions';
|
} from '@/lib/auth-actions';
|
||||||
import { useAuthStore } from '@/lib/stores/auth-store';
|
import { useAuthStore } from '@/lib/stores/auth-store';
|
||||||
|
import { BRAND_YELLOW } from '@/components/brand/brand';
|
||||||
|
|
||||||
const DEFAULT_ACCENT = '#ffed00';
|
const DEFAULT_ACCENT = BRAND_YELLOW;
|
||||||
|
|
||||||
export function AccountSettingsForm() {
|
export function AccountSettingsForm() {
|
||||||
const t = useTranslations('settings');
|
const t = useTranslations('settings');
|
||||||
|
|||||||
Reference in New Issue
Block a user