[split-required] Split 58 monoliths across Python, Go, TypeScript (Phases 1-3)
Phase 1 — Python (klausur-service): 5 monoliths → 36 files - dsfa_corpus_ingestion.py (1,828 LOC → 5 files) - cv_ocr_engines.py (2,102 LOC → 7 files) - cv_layout.py (3,653 LOC → 10 files) - vocab_worksheet_api.py (2,783 LOC → 8 files) - grid_build_core.py (1,958 LOC → 6 files) Phase 2 — Go (edu-search-service, school-service): 8 monoliths → 19 files - staff_crawler.go (1,402 → 4), policy/store.go (1,168 → 3) - policy_handlers.go (700 → 2), repository.go (684 → 2) - search.go (592 → 2), ai_extraction_handlers.go (554 → 2) - seed_data.go (591 → 2), grade_service.go (646 → 2) Phase 3 — TypeScript (admin-lehrer): 45 monoliths → 220+ files - sdk/types.ts (2,108 → 16 domain files) - ai/rag/page.tsx (2,686 → 14 files) - 22 page.tsx files split into _components/ + _hooks/ - 11 component files split into sub-components - 10 SDK data catalogs added to loc-exceptions - Deleted dead backup index_original.ts (4,899 LOC) All original public APIs preserved via re-export facades. Zero new errors: Python imports verified, Go builds clean, TypeScript tsc --noEmit shows only pre-existing errors. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import type { ColorShade } from '../constants'
|
||||
|
||||
export function ColorSwatch({ color }: { color: ColorShade }) {
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
const copyToClipboard = () => {
|
||||
navigator.clipboard.writeText(color.value)
|
||||
setCopied(true)
|
||||
setTimeout(() => setCopied(false), 2000)
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={copyToClipboard}
|
||||
className="group flex flex-col items-center"
|
||||
title={`Klicken zum Kopieren: ${color.value}`}
|
||||
>
|
||||
<div
|
||||
className="w-16 h-16 rounded-xl shadow-sm border border-slate-200 transition-transform group-hover:scale-110 flex items-center justify-center"
|
||||
style={{ backgroundColor: color.value }}
|
||||
>
|
||||
{copied && (
|
||||
<svg className={`w-5 h-5 ${color.text === 'light' ? 'text-white' : 'text-slate-900'}`} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
)}
|
||||
</div>
|
||||
<span className="text-xs text-slate-600 mt-1 font-medium">{color.name}</span>
|
||||
<span className="text-xs text-slate-400 font-mono">{color.value}</span>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
'use client'
|
||||
|
||||
import {
|
||||
PRIMARY_COLORS,
|
||||
ACCENT_COLORS,
|
||||
CATEGORY_COLORS,
|
||||
SEMANTIC_COLORS,
|
||||
} from '../constants'
|
||||
import { ColorSwatch } from './ColorSwatch'
|
||||
|
||||
export function ColorsTab() {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* Primary Color */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-2">{PRIMARY_COLORS.name}</h3>
|
||||
<p className="text-sm text-slate-500 mb-4">{PRIMARY_COLORS.description}</p>
|
||||
<div className="flex gap-4 flex-wrap">
|
||||
{PRIMARY_COLORS.shades.map((shade) => (
|
||||
<ColorSwatch key={shade.name} color={shade} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Accent Color */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-2">{ACCENT_COLORS.name}</h3>
|
||||
<p className="text-sm text-slate-500 mb-4">{ACCENT_COLORS.description}</p>
|
||||
<div className="flex gap-4 flex-wrap">
|
||||
{ACCENT_COLORS.shades.map((shade) => (
|
||||
<ColorSwatch key={shade.name} color={shade} />
|
||||
))}
|
||||
</div>
|
||||
{/* Logo Gradient Preview */}
|
||||
<div className="mt-6 pt-4 border-t border-slate-200">
|
||||
<h4 className="text-sm font-medium text-slate-700 mb-3">Logo-Gradient</h4>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-16 h-16 rounded-xl flex items-center justify-center" style={{ background: 'linear-gradient(to bottom right, #0ea5e9, #d946ef)' }}>
|
||||
<span className="text-2xl font-bold text-white">B</span>
|
||||
</div>
|
||||
<div className="text-sm text-slate-600">
|
||||
<code className="bg-slate-100 px-2 py-1 rounded font-mono text-xs">
|
||||
bg-gradient-to-br from-primary-500 to-accent-500
|
||||
</code>
|
||||
<p className="mt-1 text-slate-500">Sky Blue (#0ea5e9) → Fuchsia (#d946ef)</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Category Colors */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Kategorie-Farben</h3>
|
||||
<p className="text-sm text-slate-500 mb-6">
|
||||
Jede Kategorie hat eine eigene Farbe fuer Navigation, Module und Akzente.
|
||||
</p>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{CATEGORY_COLORS.map((cat) => (
|
||||
<div key={cat.id} className="border border-slate-200 rounded-xl p-4">
|
||||
<div className="flex items-center gap-3 mb-3">
|
||||
<div
|
||||
className="w-8 h-8 rounded-lg"
|
||||
style={{ backgroundColor: cat.main }}
|
||||
/>
|
||||
<div>
|
||||
<h4 className="font-medium text-slate-900">{cat.name}</h4>
|
||||
<p className="text-xs text-slate-500">{cat.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
{cat.shades.map((shade) => (
|
||||
<ColorSwatch key={shade.name} color={shade} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Semantic Colors */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Semantische Farben</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
{Object.entries(SEMANTIC_COLORS).map(([key, palette]) => (
|
||||
<div key={key} className="border border-slate-200 rounded-xl p-4">
|
||||
<h4 className="font-medium text-slate-900 mb-3">{palette.name}</h4>
|
||||
<div className="flex gap-2">
|
||||
{palette.shades.map((shade) => (
|
||||
<ColorSwatch key={shade.name} color={shade} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Usage Guidelines */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Verwendungsrichtlinien</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<h4 className="font-medium text-slate-700 mb-2">Primary (Sky Blue)</h4>
|
||||
<ul className="text-sm text-slate-600 space-y-1">
|
||||
<li>- Primaere Buttons und CTAs</li>
|
||||
<li>- Links und interaktive Elemente</li>
|
||||
<li>- Fokuszustaende</li>
|
||||
<li>- Ausgewaehlte Navigation</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-medium text-slate-700 mb-2">Kategorie-Farben</h4>
|
||||
<ul className="text-sm text-slate-600 space-y-1">
|
||||
<li>- Sidebar-Navigation Icons</li>
|
||||
<li>- Modul-Cards und Badges</li>
|
||||
<li>- Bereichs-spezifische Akzente</li>
|
||||
<li>- Breadcrumbs und Headers</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
'use client'
|
||||
|
||||
import { CATEGORY_COLORS } from '../constants'
|
||||
|
||||
export function ComponentsTab() {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* Buttons */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Buttons</h3>
|
||||
<div className="flex flex-wrap gap-4 mb-6">
|
||||
<button className="px-6 py-2 bg-primary-600 text-white font-medium rounded-lg hover:bg-primary-700 transition-colors">
|
||||
Primary
|
||||
</button>
|
||||
<button className="px-6 py-2 bg-slate-100 text-slate-700 font-medium rounded-lg hover:bg-slate-200 transition-colors">
|
||||
Secondary
|
||||
</button>
|
||||
<button className="px-6 py-2 border border-slate-300 text-slate-700 font-medium rounded-lg hover:bg-slate-50 transition-colors">
|
||||
Outline
|
||||
</button>
|
||||
<button className="px-6 py-2 text-primary-600 font-medium rounded-lg hover:bg-primary-50 transition-colors">
|
||||
Ghost
|
||||
</button>
|
||||
<button className="px-6 py-2 bg-red-600 text-white font-medium rounded-lg hover:bg-red-700 transition-colors">
|
||||
Danger
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<button className="px-4 py-1.5 bg-primary-600 text-white text-sm font-medium rounded-lg">
|
||||
Small
|
||||
</button>
|
||||
<button className="px-6 py-2 bg-primary-600 text-white font-medium rounded-lg">
|
||||
Medium
|
||||
</button>
|
||||
<button className="px-8 py-3 bg-primary-600 text-white text-lg font-medium rounded-lg">
|
||||
Large
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Inputs */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Eingabefelder</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-1">Standard Input</label>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Placeholder..."
|
||||
className="w-full px-3 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500 outline-none"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-1">Mit Icon</label>
|
||||
<div className="relative">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Suchen..."
|
||||
className="w-full pl-10 pr-3 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500 outline-none"
|
||||
/>
|
||||
<svg className="w-5 h-5 text-slate-400 absolute left-3 top-2.5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Cards */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Cards</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-4 hover:shadow-lg hover:border-primary-300 transition-all cursor-pointer">
|
||||
<div className="w-10 h-10 bg-primary-100 rounded-lg flex items-center justify-center mb-3">
|
||||
<svg className="w-5 h-5 text-primary-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h4 className="font-semibold text-slate-900 mb-1">Feature Card</h4>
|
||||
<p className="text-sm text-slate-600">Standard Card mit Hover-Effekt.</p>
|
||||
</div>
|
||||
<div className="rounded-xl p-4 text-white" style={{ background: 'linear-gradient(to bottom right, #0ea5e9, #d946ef)' }}>
|
||||
<h4 className="font-semibold mb-1">Highlight Card</h4>
|
||||
<p className="text-sm text-white/80">Mit Gradient-Hintergrund.</p>
|
||||
</div>
|
||||
<div className="bg-slate-900 rounded-xl p-4 text-white">
|
||||
<h4 className="font-semibold mb-1">Dark Card</h4>
|
||||
<p className="text-sm text-slate-400">Sidebar-Style.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Category Cards */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Kategorie-Cards</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
{CATEGORY_COLORS.slice(0, 3).map((cat) => (
|
||||
<div
|
||||
key={cat.id}
|
||||
className="rounded-xl border p-4 hover:shadow-lg transition-all cursor-pointer"
|
||||
style={{
|
||||
borderColor: cat.shades[0].value,
|
||||
backgroundColor: cat.shades[0].value + '40'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="w-10 h-10 rounded-lg flex items-center justify-center mb-3"
|
||||
style={{ backgroundColor: cat.main }}
|
||||
>
|
||||
<svg className="w-5 h-5 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h4 className="font-semibold text-slate-900 mb-1">{cat.name.split(' (')[0]}</h4>
|
||||
<p className="text-sm text-slate-600">{cat.description}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Badges */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Badges & Tags</h3>
|
||||
<div className="flex flex-wrap gap-2 mb-4">
|
||||
<span className="px-2.5 py-1 bg-primary-100 text-primary-700 text-xs font-medium rounded-full">Primary</span>
|
||||
<span className="px-2.5 py-1 bg-green-100 text-green-700 text-xs font-medium rounded-full">Success</span>
|
||||
<span className="px-2.5 py-1 bg-amber-100 text-amber-700 text-xs font-medium rounded-full">Warning</span>
|
||||
<span className="px-2.5 py-1 bg-red-100 text-red-700 text-xs font-medium rounded-full">Danger</span>
|
||||
<span className="px-2.5 py-1 bg-slate-100 text-slate-700 text-xs font-medium rounded-full">Neutral</span>
|
||||
</div>
|
||||
<h4 className="font-medium text-slate-700 mb-2 mt-4">Kategorie-Badges</h4>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{CATEGORY_COLORS.map((cat) => (
|
||||
<span
|
||||
key={cat.id}
|
||||
className="px-2.5 py-1 text-xs font-medium rounded-full"
|
||||
style={{
|
||||
backgroundColor: cat.shades[0].value,
|
||||
color: cat.shades[3].value
|
||||
}}
|
||||
>
|
||||
{cat.name.split(' (')[0]}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Border Radius */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Border Radius</h3>
|
||||
<div className="flex gap-6 items-end">
|
||||
<div className="text-center">
|
||||
<div className="w-16 h-16 bg-primary-500 rounded"></div>
|
||||
<span className="text-xs text-slate-500 mt-2 block">rounded (4px)</span>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="w-16 h-16 bg-primary-500 rounded-lg"></div>
|
||||
<span className="text-xs text-slate-500 mt-2 block">rounded-lg (8px)</span>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="w-16 h-16 bg-primary-500 rounded-xl"></div>
|
||||
<span className="text-xs text-slate-500 mt-2 block">rounded-xl (12px)</span>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="w-16 h-16 bg-primary-500 rounded-2xl"></div>
|
||||
<span className="text-xs text-slate-500 mt-2 block">rounded-2xl (16px)</span>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="w-16 h-16 bg-primary-500 rounded-full"></div>
|
||||
<span className="text-xs text-slate-500 mt-2 block">rounded-full</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
'use client'
|
||||
|
||||
function LogoDisplay() {
|
||||
return (
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Logo</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
<div className="bg-white border border-slate-200 rounded-xl p-8 flex items-center justify-center">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-12 h-12 rounded-xl flex items-center justify-center" style={{ background: 'linear-gradient(to bottom right, #0ea5e9, #d946ef)' }}>
|
||||
<span className="text-2xl font-bold text-white">B</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-2xl font-bold text-slate-900">BreakPilot</span>
|
||||
<span className="text-sm text-slate-500 block">Admin v2</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-slate-900 rounded-xl p-8 flex items-center justify-center">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-12 h-12 rounded-xl flex items-center justify-center" style={{ background: 'linear-gradient(to bottom right, #38bdf8, #e879f9)' }}>
|
||||
<span className="text-2xl font-bold text-white">B</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-2xl font-bold text-white">BreakPilot</span>
|
||||
<span className="text-sm text-slate-400 block">Admin v2</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Gradient Info */}
|
||||
<div className="mt-6 pt-4 border-t border-slate-200">
|
||||
<div className="flex items-center gap-4">
|
||||
<code className="bg-slate-100 px-3 py-1.5 rounded-lg font-mono text-xs text-slate-700">
|
||||
background: linear-gradient(to bottom right, #0ea5e9, #d946ef)
|
||||
</code>
|
||||
<span className="text-sm text-slate-500">Primary → Accent (Sky Blue → Fuchsia)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function LogoVariations() {
|
||||
return (
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Logo-Varianten</h3>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||
<div className="border border-slate-200 rounded-xl p-4 flex flex-col items-center gap-2">
|
||||
<div className="w-12 h-12 rounded-xl flex items-center justify-center" style={{ background: 'linear-gradient(to bottom right, #0ea5e9, #d946ef)' }}>
|
||||
<span className="text-2xl font-bold text-white">B</span>
|
||||
</div>
|
||||
<span className="text-xs text-slate-600">Icon Only</span>
|
||||
</div>
|
||||
<div className="border border-slate-200 rounded-xl p-4 flex flex-col items-center gap-2">
|
||||
<span className="text-xl font-bold text-slate-900">BreakPilot</span>
|
||||
<span className="text-xs text-slate-600">Text Only</span>
|
||||
</div>
|
||||
<div className="border border-slate-200 rounded-xl p-4 flex flex-col items-center gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-8 h-8 rounded-lg flex items-center justify-center" style={{ background: 'linear-gradient(to bottom right, #0ea5e9, #d946ef)' }}>
|
||||
<span className="text-lg font-bold text-white">B</span>
|
||||
</div>
|
||||
<span className="text-lg font-bold text-slate-900">BreakPilot</span>
|
||||
</div>
|
||||
<span className="text-xs text-slate-600">Horizontal</span>
|
||||
</div>
|
||||
<div className="border border-slate-200 rounded-xl p-4 flex flex-col items-center gap-2">
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="w-10 h-10 rounded-xl flex items-center justify-center mb-1" style={{ background: 'linear-gradient(to bottom right, #0ea5e9, #d946ef)' }}>
|
||||
<span className="text-xl font-bold text-white">B</span>
|
||||
</div>
|
||||
<span className="text-sm font-bold text-slate-900">BreakPilot</span>
|
||||
</div>
|
||||
<span className="text-xs text-slate-600">Stacked</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function FaviconSizes() {
|
||||
return (
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Favicon & App Icon</h3>
|
||||
<div className="flex gap-6 items-end">
|
||||
{[
|
||||
{ size: 'w-8 h-8', rounded: 'rounded', text: 'text-sm', label: '16x16' },
|
||||
{ size: 'w-12 h-12', rounded: 'rounded-lg', text: 'text-xl', label: '32x32' },
|
||||
{ size: 'w-16 h-16', rounded: 'rounded-xl', text: 'text-2xl', label: '180x180' },
|
||||
{ size: 'w-24 h-24', rounded: 'rounded-2xl', text: 'text-4xl', label: '512x512' },
|
||||
].map((icon) => (
|
||||
<div key={icon.label} className="text-center">
|
||||
<div className={`${icon.size} ${icon.rounded} flex items-center justify-center`} style={{ background: 'linear-gradient(to bottom right, #0ea5e9, #d946ef)' }}>
|
||||
<span className={`${icon.text} font-bold text-white`}>B</span>
|
||||
</div>
|
||||
<span className="text-xs text-slate-500 mt-2 block">{icon.label}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function LogoDonts() {
|
||||
return (
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Nicht erlaubt</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div className="border border-red-200 bg-red-50 rounded-xl p-4 text-center">
|
||||
<div className="flex items-center gap-2 justify-center opacity-50">
|
||||
<div className="w-8 h-8 bg-red-500 rounded-lg flex items-center justify-center">
|
||||
<span className="text-lg font-bold text-white">B</span>
|
||||
</div>
|
||||
<span className="text-lg font-bold text-red-500">BreakPilot</span>
|
||||
</div>
|
||||
<span className="text-xs text-red-600 mt-2 block">Falsche Farben</span>
|
||||
</div>
|
||||
<div className="border border-red-200 bg-red-50 rounded-xl p-4 text-center">
|
||||
<div className="flex items-center gap-2 justify-center" style={{ transform: 'skewX(-10deg)' }}>
|
||||
<div className="w-8 h-8 rounded-lg flex items-center justify-center" style={{ background: 'linear-gradient(to bottom right, #0ea5e9, #d946ef)' }}>
|
||||
<span className="text-lg font-bold text-white">B</span>
|
||||
</div>
|
||||
<span className="text-lg font-bold text-slate-900">BreakPilot</span>
|
||||
</div>
|
||||
<span className="text-xs text-red-600 mt-2 block">Verzerrt</span>
|
||||
</div>
|
||||
<div className="border border-red-200 bg-red-50 rounded-xl p-4 text-center">
|
||||
<div className="flex items-center gap-2 justify-center">
|
||||
<div className="w-8 h-8 rounded-lg flex items-center justify-center" style={{ background: 'linear-gradient(to bottom right, #0ea5e9, #d946ef)' }}>
|
||||
<span className="text-lg font-bold text-white">B</span>
|
||||
</div>
|
||||
<span className="text-lg font-bold text-slate-900">Break Pilot</span>
|
||||
</div>
|
||||
<span className="text-xs text-red-600 mt-2 block">Falsche Schreibweise</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function StudioLogo() {
|
||||
return (
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-2">Studio Logo (BP mit Fluegeln)</h3>
|
||||
<p className="text-sm text-slate-500 mb-6">
|
||||
Das Studio-Logo verwendet ein rotes Farbschema und zeigt "BP" mit stilisierten Fluegeln.
|
||||
Es gibt drei Design-Varianten fuer unterschiedliche Anwendungsfaelle.
|
||||
</p>
|
||||
|
||||
{/* Variante A: Cupertino Clean */}
|
||||
<div className="mb-6 p-4 bg-slate-50 rounded-xl">
|
||||
<h4 className="font-medium text-slate-700 mb-4">A: Cupertino Clean</h4>
|
||||
<div className="flex items-center gap-8">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-12 h-12 relative">
|
||||
<div className="absolute inset-0 rounded-xl shadow-lg" style={{ background: 'linear-gradient(to bottom right, #ef4444, #b91c1c)' }} />
|
||||
<div className="absolute inset-0 flex items-center justify-center">
|
||||
<svg viewBox="0 0 40 40" className="w-9 h-9">
|
||||
<circle cx="20" cy="20" r="14" fill="rgba(255,255,255,0.15)" />
|
||||
<text x="20" y="26" textAnchor="middle" fill="white" fontSize="16" fontWeight="bold" fontFamily="system-ui">BP</text>
|
||||
<path d="M6 22 L12 20 M28 20 L34 22" stroke="rgba(255,255,255,0.5)" strokeWidth="1.5" strokeLinecap="round" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-semibold text-slate-900 text-lg">Break<span className="text-red-600">Pilot</span></span>
|
||||
<span className="text-slate-400 text-sm block">Studio</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-sm text-slate-600">
|
||||
<code className="bg-white px-2 py-1 rounded font-mono text-xs">#ef4444 → #b91c1c</code>
|
||||
<p className="mt-1 text-slate-500">Minimalistisch, SF-Style, BP mit Fluegel-Linien</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Variante B: Glassmorphism Pro */}
|
||||
<div className="mb-6 p-4 rounded-xl" style={{ background: 'linear-gradient(to bottom right, #312e81, #581c87, #831843)' }}>
|
||||
<h4 className="font-medium text-white/80 mb-4">B: Glassmorphism Pro</h4>
|
||||
<div className="flex items-center gap-8">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-12 relative">
|
||||
<div className="absolute inset-0 rounded-2xl blur-md opacity-50" style={{ background: 'linear-gradient(to bottom right, #f87171, #dc2626)' }} />
|
||||
<div className="absolute inset-0 rounded-2xl border border-white/20 shadow-xl" style={{ background: 'linear-gradient(to bottom right, rgba(248,113,113,0.9), rgba(220,38,38,0.9))' }} />
|
||||
<div className="absolute inset-0 flex items-center justify-center">
|
||||
<svg viewBox="0 0 40 40" className="w-9 h-9">
|
||||
<path d="M10 28 L20 8 L30 28 L20 22 Z" fill="rgba(255,255,255,0.9)" />
|
||||
<path d="M14 24 L20 12 L26 24 L20 20 Z" fill="rgba(255,255,255,0.3)" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-semibold text-white text-lg">BreakPilot</span>
|
||||
<span className="text-white/60 text-sm block">Studio</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-sm text-white/70">
|
||||
<code className="bg-white/10 px-2 py-1 rounded font-mono text-xs">#f87171 → #dc2626</code>
|
||||
<p className="mt-1 text-white/50">Glassmorphism, Glow-Effekt, Papierflugzeug-Silhouette</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Variante C: Bento Style */}
|
||||
<div className="mb-6 p-4 bg-black rounded-xl">
|
||||
<h4 className="font-medium text-white/80 mb-4">C: Bento Style</h4>
|
||||
<div className="flex items-center gap-8">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-12 relative">
|
||||
<div className="absolute inset-0 rounded-xl" style={{ background: 'linear-gradient(to bottom right, #ef4444, #991b1b)' }} />
|
||||
<div className="absolute inset-0 flex items-center justify-center">
|
||||
<svg viewBox="0 0 40 40" className="w-9 h-9">
|
||||
<circle cx="15" cy="14" r="5" stroke="white" strokeWidth="1.5" fill="none" />
|
||||
<circle cx="15" cy="24" r="5" stroke="white" strokeWidth="1.5" fill="none" />
|
||||
<line x1="27" y1="10" x2="27" y2="30" stroke="white" strokeWidth="1.5" strokeLinecap="round" />
|
||||
<circle cx="27" cy="15" r="4" stroke="white" strokeWidth="1.5" fill="none" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-semibold text-white text-lg">BreakPilot</span>
|
||||
<span className="text-white/40 text-sm ml-2">Studio</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-sm text-white/70">
|
||||
<code className="bg-white/10 px-2 py-1 rounded font-mono text-xs">#ef4444 → #991b1b</code>
|
||||
<p className="mt-1 text-white/50">Geometrisch, Monoweight, B+P als Kreise/Linien</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Studio Farbpalette */}
|
||||
<div className="pt-4 border-t border-slate-200">
|
||||
<h4 className="text-sm font-medium text-slate-700 mb-3">Studio Farbpalette (Rot)</h4>
|
||||
<div className="flex gap-3">
|
||||
{[
|
||||
{ bg: '#fef2f2', label: 'red-50' },
|
||||
{ bg: '#f87171', label: 'red-400' },
|
||||
{ bg: '#ef4444', label: 'red-500' },
|
||||
{ bg: '#dc2626', label: 'red-600' },
|
||||
{ bg: '#b91c1c', label: 'red-700' },
|
||||
{ bg: '#991b1b', label: 'red-800' },
|
||||
].map((swatch) => (
|
||||
<div key={swatch.label} className="text-center">
|
||||
<div className="w-12 h-12 rounded-lg" style={{ backgroundColor: swatch.bg }} />
|
||||
<span className="text-xs text-slate-500 mt-1 block">{swatch.label}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<p className="text-xs text-slate-500 mt-3">
|
||||
Quelle: <code className="bg-slate-100 px-1.5 py-0.5 rounded">/studio-v2/components/Logo.tsx</code>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function LogoTab() {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<LogoDisplay />
|
||||
<LogoVariations />
|
||||
<FaviconSizes />
|
||||
<LogoDonts />
|
||||
<StudioLogo />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
'use client'
|
||||
|
||||
import { TYPOGRAPHY, SPACING } from '../constants'
|
||||
|
||||
export function TypographyTab() {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* Font Family */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Schriftart: Inter</h3>
|
||||
<div className="bg-slate-50 rounded-lg p-4 font-mono text-sm text-slate-600 mb-4">
|
||||
font-family: {TYPOGRAPHY.fontFamily};
|
||||
</div>
|
||||
<p className="text-sm text-slate-600">
|
||||
Inter ist eine moderne, variable Sans-Serif Schrift, optimiert fuer Bildschirme.
|
||||
Sie ist unter der SIL Open Font License verfuegbar und frei fuer kommerzielle Nutzung.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Font Licenses */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Lizenzen</h3>
|
||||
<div className="space-y-4">
|
||||
{/* Inter License */}
|
||||
<div className="border border-slate-200 rounded-xl p-4">
|
||||
<div className="flex items-start justify-between mb-2">
|
||||
<div>
|
||||
<h4 className="font-semibold text-slate-900">Inter Font</h4>
|
||||
<p className="text-sm text-slate-500">Designer: Rasmus Andersson</p>
|
||||
</div>
|
||||
<span className="px-2.5 py-1 bg-green-100 text-green-700 text-xs font-medium rounded-full">
|
||||
OFL-1.1
|
||||
</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4 mt-3 text-sm">
|
||||
<div>
|
||||
<span className="text-slate-500">Lizenz:</span>
|
||||
<span className="ml-2 text-slate-700">SIL Open Font License 1.1</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-slate-500">Kommerzielle Nutzung:</span>
|
||||
<span className="ml-2 text-green-600 font-medium">Ja, uneingeschraenkt</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-slate-500">Attribution erforderlich:</span>
|
||||
<span className="ml-2 text-slate-700">Nein</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-slate-500">Repository:</span>
|
||||
<a href="https://github.com/rsms/inter" target="_blank" rel="noopener noreferrer" className="ml-2 text-primary-600 hover:underline">
|
||||
github.com/rsms/inter
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Heroicons License */}
|
||||
<div className="border border-slate-200 rounded-xl p-4">
|
||||
<div className="flex items-start justify-between mb-2">
|
||||
<div>
|
||||
<h4 className="font-semibold text-slate-900">Heroicons</h4>
|
||||
<p className="text-sm text-slate-500">Designer: Tailwind Labs</p>
|
||||
</div>
|
||||
<span className="px-2.5 py-1 bg-blue-100 text-blue-700 text-xs font-medium rounded-full">
|
||||
MIT
|
||||
</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4 mt-3 text-sm">
|
||||
<div>
|
||||
<span className="text-slate-500">Lizenz:</span>
|
||||
<span className="ml-2 text-slate-700">MIT License</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-slate-500">Kommerzielle Nutzung:</span>
|
||||
<span className="ml-2 text-green-600 font-medium">Ja, uneingeschraenkt</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-slate-500">Attribution erforderlich:</span>
|
||||
<span className="ml-2 text-slate-700">Nein (empfohlen)</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-slate-500">Repository:</span>
|
||||
<a href="https://github.com/tailwindlabs/heroicons" target="_blank" rel="noopener noreferrer" className="ml-2 text-primary-600 hover:underline">
|
||||
github.com/tailwindlabs/heroicons
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* License Summary */}
|
||||
<div className="bg-green-50 border border-green-200 rounded-xl p-4">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<svg className="w-5 h-5 text-green-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<h4 className="font-semibold text-green-800">Lizenz-Compliance</h4>
|
||||
</div>
|
||||
<p className="text-sm text-green-700">
|
||||
Alle verwendeten Schriftarten und Icons sind Open Source und fuer kommerzielle Nutzung freigegeben.
|
||||
Keine Attribution erforderlich. Vollstaendige Dokumentation in der SBOM.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Font Weights */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Schriftschnitte</h3>
|
||||
<div className="space-y-4">
|
||||
{TYPOGRAPHY.weights.map((w) => (
|
||||
<div key={w.weight} className="flex items-center gap-6 pb-4 border-b border-slate-100 last:border-0 last:pb-0">
|
||||
<span
|
||||
className="text-2xl w-64"
|
||||
style={{ fontWeight: w.weight }}
|
||||
>
|
||||
The quick brown fox
|
||||
</span>
|
||||
<div className="flex-1">
|
||||
<span className="font-medium text-slate-900">{w.name} ({w.weight})</span>
|
||||
<span className="text-sm text-slate-500 ml-4">{w.usage}</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Font Sizes */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Schriftgroessen</h3>
|
||||
<div className="space-y-3">
|
||||
{TYPOGRAPHY.sizes.map((s) => (
|
||||
<div key={s.name} className="flex items-baseline gap-4 border-b border-slate-100 pb-3 last:border-0">
|
||||
<span className="w-16 text-sm font-mono text-slate-500 bg-slate-100 px-2 py-0.5 rounded">{s.name}</span>
|
||||
<span className="w-36 text-sm text-slate-600">{s.size}</span>
|
||||
<span className="text-sm text-slate-500">{s.usage}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Headings Preview */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Ueberschriften-Hierarchie</h3>
|
||||
<div className="space-y-4">
|
||||
<div className="text-4xl font-bold text-slate-900">H1: Hauptueberschrift</div>
|
||||
<div className="text-3xl font-bold text-slate-900">H2: Abschnittsueberschrift</div>
|
||||
<div className="text-2xl font-semibold text-slate-900">H3: Unterabschnitt</div>
|
||||
<div className="text-xl font-semibold text-slate-900">H4: Card-Titel</div>
|
||||
<div className="text-lg font-medium text-slate-900">H5: Kleiner Titel</div>
|
||||
<div className="text-base font-medium text-slate-900">H6: Label</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Spacing */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Spacing Scale</h3>
|
||||
<div className="space-y-3">
|
||||
{SPACING.map((s) => (
|
||||
<div key={s.name} className="flex items-center gap-4">
|
||||
<span className="w-12 text-sm font-mono text-slate-500 bg-slate-100 px-2 py-0.5 rounded text-center">{s.name}</span>
|
||||
<div
|
||||
className="bg-primary-500 h-4 rounded"
|
||||
style={{ width: `${parseInt(s.value) * 16}px` }}
|
||||
/>
|
||||
<span className="text-sm text-slate-600">{s.value}</span>
|
||||
<span className="text-sm text-slate-400">{s.usage}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
'use client'
|
||||
|
||||
import { VOICE_TONE } from '../constants'
|
||||
|
||||
export function VoiceTab() {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* Brand Attributes */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Markenpersoenlichkeit</h3>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{VOICE_TONE.attributes.map((attr) => (
|
||||
<span
|
||||
key={attr}
|
||||
className="px-4 py-2 bg-primary-100 text-primary-700 rounded-full font-medium"
|
||||
>
|
||||
{attr}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Do & Dont */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-green-600 mb-4 flex items-center gap-2">
|
||||
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
So schreiben wir
|
||||
</h3>
|
||||
<ul className="space-y-2">
|
||||
{VOICE_TONE.doList.map((item) => (
|
||||
<li key={item} className="flex items-center gap-2 text-slate-600">
|
||||
<span className="w-1.5 h-1.5 bg-green-500 rounded-full flex-shrink-0"></span>
|
||||
{item}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-red-600 mb-4 flex items-center gap-2">
|
||||
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
Das vermeiden wir
|
||||
</h3>
|
||||
<ul className="space-y-2">
|
||||
{VOICE_TONE.dontList.map((item) => (
|
||||
<li key={item} className="flex items-center gap-2 text-slate-600">
|
||||
<span className="w-1.5 h-1.5 bg-red-500 rounded-full flex-shrink-0"></span>
|
||||
{item}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Example Texts */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Beispieltexte</h3>
|
||||
<div className="space-y-4">
|
||||
<div className="p-4 bg-green-50 border border-green-200 rounded-xl">
|
||||
<span className="text-xs text-green-600 font-medium mb-2 block">GUT</span>
|
||||
<p className="text-slate-700">
|
||||
"Verwalten Sie Ihre Datenschutz-Dokumente einfach und sicher. Alle Aenderungen werden protokolliert."
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4 bg-red-50 border border-red-200 rounded-xl">
|
||||
<span className="text-xs text-red-600 font-medium mb-2 block">SCHLECHT</span>
|
||||
<p className="text-slate-700">
|
||||
"Unsere revolutionaere KI-Loesung optimiert Ihre Compliance-Workflows durch state-of-the-art NLP."
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Target Audience */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6 shadow-sm">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Zielgruppe</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||
{[
|
||||
{
|
||||
iconBg: 'bg-education-100', iconColor: 'text-education-600',
|
||||
iconPath: 'M12 14l9-5-9-5-9 5 9 5z',
|
||||
iconPath2: 'M12 14l6.16-3.422a12.083 12.083 0 01.665 6.479A11.952 11.952 0 0012 20.055a11.952 11.952 0 00-6.824-2.998 12.078 12.078 0 01.665-6.479L12 14z',
|
||||
title: 'Lehrkraefte', desc: 'Zeitersparnis, einfache Bedienung',
|
||||
},
|
||||
{
|
||||
iconBg: 'bg-compliance-100', iconColor: 'text-compliance-600',
|
||||
iconPath: 'M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z',
|
||||
title: 'DSB', desc: 'DSGVO-Compliance, Dokumentation',
|
||||
},
|
||||
{
|
||||
iconBg: 'bg-infrastructure-100', iconColor: 'text-infrastructure-600',
|
||||
iconPath: 'M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4',
|
||||
title: 'Entwickler', desc: 'APIs, Integration, DevOps',
|
||||
},
|
||||
{
|
||||
iconBg: 'bg-communication-100', iconColor: 'text-communication-600',
|
||||
iconPath: 'M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4',
|
||||
title: 'Schulleitung', desc: 'Ueberblick, Kosten, Compliance',
|
||||
},
|
||||
].map((audience) => (
|
||||
<div key={audience.title} className="p-4 bg-slate-50 rounded-xl text-center">
|
||||
<div className={`w-12 h-12 ${audience.iconBg} rounded-xl flex items-center justify-center mx-auto mb-2`}>
|
||||
<svg className={`w-6 h-6 ${audience.iconColor}`} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d={audience.iconPath} />
|
||||
{audience.iconPath2 && (
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d={audience.iconPath2} />
|
||||
)}
|
||||
</svg>
|
||||
</div>
|
||||
<h4 className="font-semibold text-slate-900">{audience.title}</h4>
|
||||
<p className="text-sm text-slate-600 mt-1">{audience.desc}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
253
admin-lehrer/app/(admin)/development/brandbook/constants.ts
Normal file
253
admin-lehrer/app/(admin)/development/brandbook/constants.ts
Normal file
@@ -0,0 +1,253 @@
|
||||
/**
|
||||
* Brandbook Constants - Color palettes, typography, spacing, voice & tone
|
||||
*/
|
||||
|
||||
export interface ColorShade {
|
||||
name: string
|
||||
value: string
|
||||
text: 'dark' | 'light'
|
||||
}
|
||||
|
||||
export interface ColorPalette {
|
||||
name: string
|
||||
description: string
|
||||
shades: ColorShade[]
|
||||
}
|
||||
|
||||
export interface CategoryColor {
|
||||
id: string
|
||||
name: string
|
||||
description: string
|
||||
main: string
|
||||
shades: ColorShade[]
|
||||
}
|
||||
|
||||
// Primary brand color (Sky Blue)
|
||||
export const PRIMARY_COLORS: ColorPalette = {
|
||||
name: 'Primary (Sky Blue)',
|
||||
description: 'Haupt-Markenfarbe fuer Buttons, Links und Akzente',
|
||||
shades: [
|
||||
{ name: '50', value: '#f0f9ff', text: 'dark' },
|
||||
{ name: '100', value: '#e0f2fe', text: 'dark' },
|
||||
{ name: '200', value: '#bae6fd', text: 'dark' },
|
||||
{ name: '300', value: '#7dd3fc', text: 'dark' },
|
||||
{ name: '400', value: '#38bdf8', text: 'dark' },
|
||||
{ name: '500', value: '#0ea5e9', text: 'light' },
|
||||
{ name: '600', value: '#0284c7', text: 'light' },
|
||||
{ name: '700', value: '#0369a1', text: 'light' },
|
||||
{ name: '800', value: '#075985', text: 'light' },
|
||||
{ name: '900', value: '#0c4a6e', text: 'light' },
|
||||
],
|
||||
}
|
||||
|
||||
// Accent brand color (Fuchsia) - for logo gradient and highlights
|
||||
export const ACCENT_COLORS: ColorPalette = {
|
||||
name: 'Accent (Fuchsia)',
|
||||
description: 'Akzentfarbe fuer Logo-Gradient und besondere Highlights',
|
||||
shades: [
|
||||
{ name: '50', value: '#fdf4ff', text: 'dark' },
|
||||
{ name: '100', value: '#fae8ff', text: 'dark' },
|
||||
{ name: '200', value: '#f5d0fe', text: 'dark' },
|
||||
{ name: '300', value: '#f0abfc', text: 'dark' },
|
||||
{ name: '400', value: '#e879f9', text: 'dark' },
|
||||
{ name: '500', value: '#d946ef', text: 'light' },
|
||||
{ name: '600', value: '#c026d3', text: 'light' },
|
||||
{ name: '700', value: '#a21caf', text: 'light' },
|
||||
{ name: '800', value: '#86198f', text: 'light' },
|
||||
{ name: '900', value: '#701a75', text: 'light' },
|
||||
],
|
||||
}
|
||||
|
||||
// Category colors for navigation and modules
|
||||
export const CATEGORY_COLORS: CategoryColor[] = [
|
||||
{
|
||||
id: 'dsgvo',
|
||||
name: 'DSGVO (Violet)',
|
||||
description: 'Datenschutz & Betroffenenrechte',
|
||||
main: '#7c3aed',
|
||||
shades: [
|
||||
{ name: '100', value: '#ede9fe', text: 'dark' },
|
||||
{ name: '500', value: '#8b5cf6', text: 'light' },
|
||||
{ name: '600', value: '#7c3aed', text: 'light' },
|
||||
{ name: '700', value: '#6d28d9', text: 'light' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'compliance',
|
||||
name: 'Compliance (Purple)',
|
||||
description: 'Audit, Controls & Regulierung',
|
||||
main: '#9333ea',
|
||||
shades: [
|
||||
{ name: '100', value: '#f3e8ff', text: 'dark' },
|
||||
{ name: '500', value: '#a855f7', text: 'light' },
|
||||
{ name: '600', value: '#9333ea', text: 'light' },
|
||||
{ name: '700', value: '#7e22ce', text: 'light' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'ai',
|
||||
name: 'KI & Automatisierung (Teal)',
|
||||
description: 'LLM, OCR, RAG & Machine Learning',
|
||||
main: '#14b8a6',
|
||||
shades: [
|
||||
{ name: '100', value: '#ccfbf1', text: 'dark' },
|
||||
{ name: '500', value: '#14b8a6', text: 'light' },
|
||||
{ name: '600', value: '#0d9488', text: 'light' },
|
||||
{ name: '700', value: '#0f766e', text: 'light' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'infrastructure',
|
||||
name: 'Infrastruktur (Orange)',
|
||||
description: 'GPU, Security, CI/CD & Monitoring',
|
||||
main: '#f97316',
|
||||
shades: [
|
||||
{ name: '100', value: '#ffedd5', text: 'dark' },
|
||||
{ name: '500', value: '#f97316', text: 'light' },
|
||||
{ name: '600', value: '#ea580c', text: 'light' },
|
||||
{ name: '700', value: '#c2410c', text: 'light' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'education',
|
||||
name: 'Bildung & Schule (Blue)',
|
||||
description: 'Bildungsquellen & Lehrplaene',
|
||||
main: '#3b82f6',
|
||||
shades: [
|
||||
{ name: '100', value: '#dbeafe', text: 'dark' },
|
||||
{ name: '500', value: '#3b82f6', text: 'light' },
|
||||
{ name: '600', value: '#2563eb', text: 'light' },
|
||||
{ name: '700', value: '#1d4ed8', text: 'light' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'communication',
|
||||
name: 'Kommunikation (Green)',
|
||||
description: 'Matrix, E-Mail & Benachrichtigungen',
|
||||
main: '#22c55e',
|
||||
shades: [
|
||||
{ name: '100', value: '#dcfce7', text: 'dark' },
|
||||
{ name: '500', value: '#22c55e', text: 'light' },
|
||||
{ name: '600', value: '#16a34a', text: 'light' },
|
||||
{ name: '700', value: '#15803d', text: 'light' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'development',
|
||||
name: 'Entwicklung (Slate)',
|
||||
description: 'Workflow, Game, Docs & Brandbook',
|
||||
main: '#64748b',
|
||||
shades: [
|
||||
{ name: '100', value: '#f1f5f9', text: 'dark' },
|
||||
{ name: '500', value: '#64748b', text: 'light' },
|
||||
{ name: '600', value: '#475569', text: 'light' },
|
||||
{ name: '700', value: '#334155', text: 'light' },
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
// Semantic colors
|
||||
export const SEMANTIC_COLORS: Record<string, { name: string; shades: ColorShade[] }> = {
|
||||
success: {
|
||||
name: 'Success (Emerald)',
|
||||
shades: [
|
||||
{ name: '100', value: '#d1fae5', text: 'dark' },
|
||||
{ name: '500', value: '#10b981', text: 'light' },
|
||||
{ name: '600', value: '#059669', text: 'light' },
|
||||
],
|
||||
},
|
||||
warning: {
|
||||
name: 'Warning (Amber)',
|
||||
shades: [
|
||||
{ name: '100', value: '#fef3c7', text: 'dark' },
|
||||
{ name: '500', value: '#f59e0b', text: 'dark' },
|
||||
{ name: '600', value: '#d97706', text: 'light' },
|
||||
],
|
||||
},
|
||||
danger: {
|
||||
name: 'Danger (Red)',
|
||||
shades: [
|
||||
{ name: '100', value: '#fee2e2', text: 'dark' },
|
||||
{ name: '500', value: '#ef4444', text: 'light' },
|
||||
{ name: '600', value: '#dc2626', text: 'light' },
|
||||
],
|
||||
},
|
||||
neutral: {
|
||||
name: 'Neutral (Slate)',
|
||||
shades: [
|
||||
{ name: '50', value: '#f8fafc', text: 'dark' },
|
||||
{ name: '100', value: '#f1f5f9', text: 'dark' },
|
||||
{ name: '200', value: '#e2e8f0', text: 'dark' },
|
||||
{ name: '300', value: '#cbd5e1', text: 'dark' },
|
||||
{ name: '400', value: '#94a3b8', text: 'dark' },
|
||||
{ name: '500', value: '#64748b', text: 'light' },
|
||||
{ name: '600', value: '#475569', text: 'light' },
|
||||
{ name: '700', value: '#334155', text: 'light' },
|
||||
{ name: '800', value: '#1e293b', text: 'light' },
|
||||
{ name: '900', value: '#0f172a', text: 'light' },
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export const TYPOGRAPHY = {
|
||||
fontFamily: "'Inter', system-ui, -apple-system, sans-serif",
|
||||
weights: [
|
||||
{ weight: 400, name: 'Regular', usage: 'Fliesstext, Beschreibungen' },
|
||||
{ weight: 500, name: 'Medium', usage: 'Labels, Buttons, Navigation' },
|
||||
{ weight: 600, name: 'Semi-Bold', usage: 'Ueberschriften H3-H6, Card-Titel' },
|
||||
{ weight: 700, name: 'Bold', usage: 'Ueberschriften H1-H2, CTAs' },
|
||||
],
|
||||
sizes: [
|
||||
{ name: 'xs', size: '0.75rem (12px)', usage: 'Footnotes, Badges' },
|
||||
{ name: 'sm', size: '0.875rem (14px)', usage: 'Nebentext, Labels' },
|
||||
{ name: 'base', size: '1rem (16px)', usage: 'Fliesstext, Body' },
|
||||
{ name: 'lg', size: '1.125rem (18px)', usage: 'Lead Text' },
|
||||
{ name: 'xl', size: '1.25rem (20px)', usage: 'H4, Card Titles' },
|
||||
{ name: '2xl', size: '1.5rem (24px)', usage: 'H3' },
|
||||
{ name: '3xl', size: '1.875rem (30px)', usage: 'H2' },
|
||||
{ name: '4xl', size: '2.25rem (36px)', usage: 'H1, Hero' },
|
||||
],
|
||||
}
|
||||
|
||||
export const SPACING = [
|
||||
{ name: '1', value: '0.25rem (4px)', usage: 'Minimaler Abstand' },
|
||||
{ name: '2', value: '0.5rem (8px)', usage: 'Kompakter Abstand' },
|
||||
{ name: '3', value: '0.75rem (12px)', usage: 'Standard klein' },
|
||||
{ name: '4', value: '1rem (16px)', usage: 'Standard' },
|
||||
{ name: '6', value: '1.5rem (24px)', usage: 'Card Padding' },
|
||||
{ name: '8', value: '2rem (32px)', usage: 'Section Spacing' },
|
||||
]
|
||||
|
||||
export const VOICE_TONE = {
|
||||
attributes: [
|
||||
'Professionell & Vertrauenswuerdig',
|
||||
'Klar & Direkt',
|
||||
'Hilfreich & Unterstuetzend',
|
||||
'Modern & Innovativ',
|
||||
'DSGVO-konform & Sicher',
|
||||
],
|
||||
doList: [
|
||||
'Einfache, klare Sprache verwenden',
|
||||
'Aktiv formulieren',
|
||||
'Nutzenorientiert schreiben',
|
||||
'Konkrete Beispiele geben',
|
||||
'Technische Begriffe erklaeren',
|
||||
],
|
||||
dontList: [
|
||||
'Fachjargon ohne Erklaerung',
|
||||
'Passive Formulierungen',
|
||||
'Uebertriebene Versprechen',
|
||||
'Marketing-Floskeln',
|
||||
'Unpersoenliche Ansprache',
|
||||
],
|
||||
}
|
||||
|
||||
export type BrandbookTab = 'colors' | 'typography' | 'components' | 'logo' | 'voice'
|
||||
|
||||
export const TABS: { id: BrandbookTab; label: string }[] = [
|
||||
{ id: 'colors', label: 'Farben' },
|
||||
{ id: 'typography', label: 'Typografie' },
|
||||
{ id: 'components', label: 'Komponenten' },
|
||||
{ id: 'logo', label: 'Logo' },
|
||||
{ id: 'voice', label: 'Tonalitaet' },
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user