feat(frontend): moderneres visuelles Redesign (Farben, Tiefe, Dashboard-Hero)

Kartenhintergrund und Seitenhintergrund waren fast farbgleich, wodurch
alles flach wirkte trotz vorhandenem Schatten. Staerkerer Kontrast
(--background/--card/--muted/--border), neue Gradient- und
Schatten-Tokens (--gradient-honey/-sage/-sky, --shadow-soft/-elevated).

Card-Komponente: rounded-2xl, echter sichtbarer Schatten, optionaler
Hover-Lift (interactive-Prop). Sidebar: solide Gradient-Badge, kraeftiger
Active-Pill-Zustand statt blassem Tint. Header: sticky mit Blur-Schatten
statt hartem Rand. Dashboard: Gradient-Hero mit Begruessung und
Honeycomb-Muster, farbige Gradient-Icon-Badges pro KPI-Kachel,
Hinweise-Zeilen mit Icon statt rohem Enum-Badge (dabei toten
CONSPICUOUS_COLONY-Style-Key gefunden und auf COLONY_ATTENTION
korrigiert). Honeycomb-Hintergrund aus der Login-Seite in eine
gemeinsame Komponente extrahiert und dort mit dem gleichen
Gradient-Badge-Header konsistent gemacht.
This commit is contained in:
Nick Szaunig committed 2026-08-23 20:10:33 +02:00
1 parent 6ab028d1be
commit 5cacc3c60d
7 files changed
+202 -103

No files matched your search

@@ -0,0 +1,31 @@
interface HoneycombPatternProps {
className?: string;
id?: string;
}
export function HoneycombPattern({ className, id = "honeycomb" }: HoneycombPatternProps) {
return (
<svg
aria-hidden="true"
className={className ?? "pointer-events-none absolute inset-0 h-full w-full text-primary/[0.07]"}
>
<defs>
<pattern
id={id}
width="56"
height="97"
patternUnits="userSpaceOnUse"
patternTransform="scale(1)"
>
<path
fill="none"
stroke="currentColor"
strokeWidth="1.5"
d="M28 0 56 16.2 56 48.5 28 64.7 0 48.5 0 16.2Z M28 64.7 56 80.8 56 97 28 97 0 97 0 80.8Z"
/>
</pattern>
</defs>
<rect width="100%" height="100%" fill={`url(#${id})`} />
</svg>
);
}
+5 -2
View File
@@ -5,14 +5,17 @@ import { cn } from "@/lib/utils"
function Card({
className,
size = "default",
interactive = false,
...props
}: React.ComponentProps<"div"> & { size?: "default" | "sm" }) {
}: React.ComponentProps<"div"> & { size?: "default" | "sm"; interactive?: boolean }) {
return (
<div
data-slot="card"
data-size={size}
className={cn(
"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl border border-border/60 bg-card py-(--card-spacing) text-sm text-card-foreground shadow-[0_1px_2px_-1px_rgba(33,20,10,0.06),0_2px_8px_-2px_rgba(33,20,10,0.06)] transition-shadow [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-2xl border border-border/50 bg-card py-(--card-spacing) text-sm text-card-foreground shadow-[var(--shadow-soft)] transition-all duration-200 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-2xl *:[img:last-child]:rounded-b-2xl",
interactive &&
"motion-safe:hover:-translate-y-0.5 hover:shadow-[var(--shadow-elevated)] hover:border-border",
className
)}
{...props}