Section card
Card with an eyebrow header and body.
npx shadcn@latest add https://ui.thjsecurity.tech/r/section-card.jsonPulls the component into components/ui/section-card.tsx and its token dependencies. The app owns the copy from then on.
(registry) card
import * as React from "react"
import { cn } from "@/lib/utils"
import { Card } from "@/components/ui/card"
interface SectionCardProps
extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
title: React.ReactNode
/** Muted one-liner under the title (PD-style). */
description?: React.ReactNode
/** Small leading icon next to the title. */
icon?: React.ReactNode
/** Right-aligned controls (toggles, export, links). */
actions?: React.ReactNode
/** Drop the inner content padding (e.g. for full-bleed tables). */
flush?: boolean
}
/**
* Standard section container: a Card with a consistent header
* (bold title + muted description + optional icon/actions).
* Replaces ad-hoc <Card><CardHeader>… blocks for visual consistency.
*/
function SectionCard({
title,
description,
icon,
actions,
flush,
className,
children,
...props
}: SectionCardProps) {
return (
<Card className={cn("flex flex-col", className)} {...props}>
<div className="flex items-start justify-between gap-4 p-5 pb-3">
<div className="min-w-0 space-y-0.5">
<div className="flex items-center gap-2">
{icon && (
<span className="text-muted-foreground [&_svg]:size-[19px]">
{icon}
</span>
)}
<h3 className="text-base font-semibold leading-none tracking-tight">
{title}
</h3>
</div>
{description && (
<p className="text-sm text-muted-foreground">{description}</p>
)}
</div>
{actions && <div className="shrink-0">{actions}</div>}
</div>
<div className={cn(flush ? "" : "px-5 pb-5", "flex-1")}>{children}</div>
</Card>
)
}
export { SectionCard }