- 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
59 lines
2.1 KiB
JavaScript
59 lines
2.1 KiB
JavaScript
/** @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: [],
|
|
};
|