feat: vollständiges HeroUI v3 Redesign — Types, Utils, Layout, Sections, Dark SaaS Design
Some checks failed
Deploy Discord Bot / deploy (push) Has been cancelled

This commit is contained in:
Pepe44DEV
2026-07-01 04:46:56 +02:00
parent e9b0f25d71
commit dd6ae54306
14 changed files with 925 additions and 974 deletions

View File

@@ -0,0 +1,26 @@
import { Card, CardContent } from '@heroui/react';
import type { ReactNode } from 'react';
type Props = {
icon: ReactNode;
label: string;
value: number;
};
export function ActivityTile({ icon, label, value }: Props) {
return (
<Card className="border border-default-100 bg-default-50/20">
<CardContent className="flex flex-row items-center justify-between gap-4 p-4">
<div className="flex items-center gap-3">
<div className="flex size-10 items-center justify-center rounded-xl bg-primary-500/10 text-primary-400">
{icon}
</div>
<div>
<div className="text-tiny uppercase tracking-widest text-default-500">{label}</div>
<div className="text-2xl font-black">{value}</div>
</div>
</div>
</CardContent>
</Card>
);
}

View File

@@ -0,0 +1,18 @@
import { Card, CardHeader, CardContent } from '@heroui/react';
import type { ReactNode } from 'react';
type Props = {
title: string;
children: ReactNode;
};
export function FormPanel({ title, children }: Props) {
return (
<Card className="border border-default-100 bg-default-50/20">
<CardHeader className="px-5 pt-5 pb-0">
<h3 className="text-base font-semibold">{title}</h3>
</CardHeader>
<CardContent className="flex flex-col gap-4 px-5 py-5">{children}</CardContent>
</Card>
);
}

View File

@@ -0,0 +1,21 @@
import { Card, CardHeader, CardContent } from '@heroui/react';
import type { ReactNode } from 'react';
type Props = {
title: string;
children: ReactNode;
className?: string;
};
export function ListPanel({ title, children, className }: Props) {
return (
<Card className={`border border-default-100 bg-default-50/20 ${className ?? ''}`}>
<CardHeader className="px-5 pt-5 pb-0">
<h3 className="text-base font-semibold">{title}</h3>
</CardHeader>
<CardContent className="px-5 py-5">
{children}
</CardContent>
</Card>
);
}

View File

@@ -0,0 +1,34 @@
import { Card, CardContent } from '@heroui/react';
import type { ReactNode } from 'react';
type Props = {
lines?: number;
children?: ReactNode;
};
export function LoadingSkeleton({ lines = 3, children }: Props) {
if (children) {
return (
<div className="flex flex-col gap-3">
{Array.from({ length: lines }).map((_, i) => (
<Card key={i} className="animate-pulse border border-default-100 bg-default-50/30">
<CardContent className="p-4">{children}</CardContent>
</Card>
))}
</div>
);
}
return (
<div className="flex flex-col gap-3">
{Array.from({ length: lines }).map((_, i) => (
<Card key={i} className="animate-pulse border border-default-100 bg-default-50/30">
<CardContent className="p-5">
<div className="h-4 w-3/4 rounded-lg bg-default-200/50" />
{i < 2 && <div className="mt-3 h-3 w-1/2 rounded-lg bg-default-200/30" />}
</CardContent>
</Card>
))}
</div>
);
}

View File

@@ -0,0 +1,24 @@
import { Card, CardHeader, CardContent } from '@heroui/react';
import type { ReactNode } from 'react';
type Props = {
title: string;
subtitle?: string;
children: ReactNode;
action?: ReactNode;
};
export function SectionCard({ title, subtitle, children, action }: Props) {
return (
<Card className="border border-default-100 bg-gradient-to-b from-default-50/40 to-background">
<CardHeader className="flex items-start justify-between gap-4 px-6 pt-6 pb-0">
<div className="min-w-0">
<h2 className="text-xl font-bold tracking-tight">{title}</h2>
{subtitle && <p className="mt-1 text-small text-default-500">{subtitle}</p>}
</div>
{action && <div className="shrink-0">{action}</div>}
</CardHeader>
<CardContent className="px-6 py-5">{children}</CardContent>
</Card>
);
}

View File

@@ -0,0 +1,22 @@
import { Card, CardContent } from '@heroui/react';
import type { ReactNode } from 'react';
type Props = {
icon: ReactNode;
label: string;
value: string;
};
export function StatCard({ icon, label, value }: Props) {
return (
<Card className="border border-default-100 bg-default-50/20">
<CardContent className="flex flex-col gap-2 p-4">
<div className="flex items-center gap-2 text-tiny uppercase tracking-widest text-default-500">
<span className="text-primary-400">{icon}</span>
{label}
</div>
<div className="text-2xl font-bold tracking-tight">{value}</div>
</CardContent>
</Card>
);
}