// src/components/ui/Card.tsx 'use client'; import * as React from 'react'; import clsx from 'clsx'; export type CardVariant = | 'default' // normale Card, gerundet, Schatten | 'edgeToEdge' // Kante-zu-Kante auf Mobile, rounded ab sm: | 'well' // "Well" auf weißem Hintergrund | 'wellOnGray' // Well auf grauem Hintergrund | 'wellEdgeToEdge'; // Well, edge-to-edge auf Mobile export interface CardProps extends React.HTMLAttributes { variant?: CardVariant; /** Trenne Header/Body/Footer mit divide-y */ divided?: boolean; } function CardRoot({ variant = 'default', divided = false, className, ...props }: CardProps) { const base = 'overflow-hidden'; const variantClasses = (() => { switch (variant) { case 'edgeToEdge': return 'bg-white shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10'; case 'well': return 'rounded-lg bg-gray-50 dark:bg-gray-800/50'; case 'wellOnGray': return 'rounded-lg bg-gray-200 dark:bg-gray-800/50'; case 'wellEdgeToEdge': return 'bg-gray-50 sm:rounded-lg dark:bg-gray-800/50'; case 'default': default: return 'rounded-lg bg-white shadow-sm dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10'; } })(); const divideClasses = divided ? 'divide-y divide-gray-200 dark:divide-white/10' : ''; return (
); } type SectionProps = React.HTMLAttributes & { /** Grau hinterlegt (Body / Footer) wie in deinen Beispielen */ muted?: boolean; }; function CardHeader({ className, muted, ...props }: SectionProps) { return (
); } function CardBody({ className, muted, ...props }: SectionProps) { return (
); } function CardFooter({ className, muted, ...props }: SectionProps) { return (
); } // Default-Export mit statischen Subkomponenten: , etc. export const Card = Object.assign(CardRoot, { Header: CardHeader, Body: CardBody, Footer: CardFooter, }); export default Card;