feat(frontend): Oberfläche mit RRULE-Editor und Logo-Auswahl
- Vite, React 18, TypeScript und Tailwind mit dunklem Standard-Theme über CSS-Variablen, heller Modus umschaltbar und in localStorage gemerkt - Anmeldung, erzwungener Passwortwechsel, Layout mit Seitenleiste - API-Client mit stiller Token-Erneuerung, TanStack Query mit Fehler-Toasts - Seiten Recurrences (inkl. Detail-Drawer), Transactions, Merchants, Settings - Geführter RRULE-Editor mit Vorlagen, Expertenmodus, deutschem Klartext und Live-Vorschau der nächsten Termine vom preview-Endpunkt - Firmen-Kachelgrid mit Logo, Markenfarbe und Logo-Auswahldialog samt Upload - Beträge durchgängig in de-DE, Eingabe in beiden Schreibweisen - 49 Tests, tsc --noEmit und eslint sauber, Produktionsbundle baut Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014e7t8UpmoVNMtWivY5LiSH
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: ["./index.html", "./src/**/*.{ts,tsx}"],
|
||||
// Umschaltbar über die Klasse `dark` am <html>-Element; Vorgabe ist dunkel.
|
||||
darkMode: "class",
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
// Die Palette wird über CSS-Variablen gespeist, damit der Wechsel
|
||||
// zwischen hell und dunkel ohne doppelte Klassen auskommt.
|
||||
ground: "rgb(var(--color-ground) / <alpha-value>)",
|
||||
surface: "rgb(var(--color-surface) / <alpha-value>)",
|
||||
raised: "rgb(var(--color-raised) / <alpha-value>)",
|
||||
line: "rgb(var(--color-line) / <alpha-value>)",
|
||||
ink: "rgb(var(--color-ink) / <alpha-value>)",
|
||||
muted: "rgb(var(--color-muted) / <alpha-value>)",
|
||||
faint: "rgb(var(--color-faint) / <alpha-value>)",
|
||||
accent: "rgb(var(--color-accent) / <alpha-value>)",
|
||||
"accent-ink": "rgb(var(--color-accent-ink) / <alpha-value>)",
|
||||
positive: "rgb(var(--color-positive) / <alpha-value>)",
|
||||
negative: "rgb(var(--color-negative) / <alpha-value>)",
|
||||
warning: "rgb(var(--color-warning) / <alpha-value>)",
|
||||
},
|
||||
fontFamily: {
|
||||
sans: [
|
||||
"Inter",
|
||||
"system-ui",
|
||||
"-apple-system",
|
||||
"Segoe UI",
|
||||
"Roboto",
|
||||
"Helvetica Neue",
|
||||
"sans-serif",
|
||||
],
|
||||
mono: ["ui-monospace", "SFMono-Regular", "Menlo", "Consolas", "monospace"],
|
||||
},
|
||||
borderRadius: {
|
||||
card: "0.875rem",
|
||||
},
|
||||
keyframes: {
|
||||
"fade-in": { from: { opacity: "0" }, to: { opacity: "1" } },
|
||||
"slide-up": {
|
||||
from: { opacity: "0", transform: "translateY(0.5rem)" },
|
||||
to: { opacity: "1", transform: "translateY(0)" },
|
||||
},
|
||||
"slide-in-right": {
|
||||
from: { transform: "translateX(100%)" },
|
||||
to: { transform: "translateX(0)" },
|
||||
},
|
||||
},
|
||||
animation: {
|
||||
"fade-in": "fade-in 150ms ease-out",
|
||||
"slide-up": "slide-up 180ms ease-out",
|
||||
"slide-in-right": "slide-in-right 220ms cubic-bezier(0.22, 1, 0.36, 1)",
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
Reference in New Issue
Block a user