1a3c2e08ce
- Remove clock icons and hour text from calendar month view, show only activity bars - Fix calendar week view mobile layout (2-column grid instead of vertical stack) - Update invoice form skeleton to match actual layout structure - Add client-side validation for empty invoice item descriptions with auto-scroll to error - Fix hourly rate defaulting logic with proper type guards - Update invoice details skeleton to match page structure with PageHeader - Fix hydration error in sidebar (div inside button -> span) - Improve dashboard chart color consistency (draft status now matches monthly metrics) - Fix mobile header layout to prevent text squishing (vertical stack on mobile) - Add IDs to invoice line items for scroll-into-view functionality
93 lines
2.0 KiB
TypeScript
93 lines
2.0 KiB
TypeScript
import * as React from "react";
|
|
|
|
import { cn } from "~/lib/utils";
|
|
|
|
function Card({ className, ...props }: React.ComponentProps<"div">) {
|
|
return (
|
|
<div
|
|
data-slot="card"
|
|
className={cn(
|
|
"bg-background/80 backdrop-blur-xl border-border/50 text-card-foreground flex flex-col rounded-3xl border shadow-sm overflow-hidden",
|
|
className,
|
|
)}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
|
|
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
return (
|
|
<div
|
|
data-slot="card-header"
|
|
className={cn(
|
|
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-5 pt-4 pb-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
|
className,
|
|
)}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
|
|
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
return (
|
|
<div
|
|
data-slot="card-title"
|
|
className={cn("text-lg leading-none font-semibold", className)}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
|
|
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
|
return (
|
|
<div
|
|
data-slot="card-description"
|
|
className={cn("text-muted-foreground text-sm", className)}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
|
|
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
|
return (
|
|
<div
|
|
data-slot="card-action"
|
|
className={cn(
|
|
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
|
className,
|
|
)}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
|
|
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
return (
|
|
<div
|
|
data-slot="card-content"
|
|
className={cn("px-5 pb-4", className)}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
|
|
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
return (
|
|
<div
|
|
data-slot="card-footer"
|
|
className={cn("flex items-center px-6 py-6 [.border-t]:pt-6", className)}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
|
|
export {
|
|
Card,
|
|
CardHeader,
|
|
CardFooter,
|
|
CardTitle,
|
|
CardAction,
|
|
CardDescription,
|
|
CardContent,
|
|
};
|