Component props.
The rendered settings section shell.
export function SettingsSectionShell({
icon: Icon,
title,
description,
accent,
children,
badge,
className,
contentClassName,
delay = 0,
id,
isCollapsible = false,
isCollapsed = false,
onCollapsedChange,
}: Readonly<SettingsSectionShellProps>) {
const card = (
<Card
className={cn(
"py-0! overflow-hidden border border-slate-200 bg-white/85 shadow-[0_30px_80px_-50px_rgba(15,23,42,0.15)] backdrop-blur-xl dark:border-white/10 dark:bg-slate-950/40 dark:shadow-[0_30px_80px_-50px_rgba(15,23,42,0.9)]",
className,
)}
>
{isCollapsible ? (
<>
<CollapsibleTrigger asChild>
<button
aria-expanded={!isCollapsed}
aria-controls={id ? `content-${id}` : undefined}
className={cn(
"w-full text-left",
"hover:bg-white/40 dark:hover:bg-white/5",
"transition-colors duration-200",
)}
>
<CardHeader
className={cn(
"relative overflow-hidden border-b border-white/40 px-6 py-6 sm:px-8 dark:border-white/10",
"bg-linear-to-r",
accent,
)}
>
<div className="pointer-events-none absolute inset-0 bg-white/80 backdrop-blur-sm dark:bg-slate-950/60" />
<div className="relative flex items-start justify-between gap-4">
<div className="flex items-start gap-4">
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-white/90 text-slate-900 shadow-md ring-1 ring-black/5 dark:bg-white/10 dark:text-white dark:ring-white/10">
<Icon className="h-5 w-5" aria-hidden="true" />
</div>
<div className="space-y-1">
<CardTitle className="text-base font-semibold text-slate-900 dark:text-white">
{title}
</CardTitle>
<CardDescription className="text-sm text-slate-600 dark:text-slate-100/80">
{description}
</CardDescription>
</div>
</div>
<div className="relative flex items-center gap-3">
{badge && <div>{badge}</div>}
<CollapsibleChevron
isExpanded={!isCollapsed}
className="text-slate-600 dark:text-slate-400"
/>
</div>
</div>
</CardHeader>
</button>
</CollapsibleTrigger>
<CollapsibleContent id={id ? `content-${id}` : undefined}>
<CardContent
className={cn(
"px-6 py-6 text-slate-700 sm:px-8 dark:text-slate-200",
contentClassName,
)}
>
{children}
</CardContent>
</CollapsibleContent>
</>
) : (
<>
<CardHeader
className={cn(
"relative overflow-hidden border-b border-white/40 px-6 py-6 sm:px-8 dark:border-white/10",
"bg-linear-to-r",
accent,
)}
>
<div className="pointer-events-none absolute inset-0 bg-white/80 backdrop-blur-sm dark:bg-slate-950/60" />
<div className="relative flex items-start justify-between gap-4">
<div className="flex items-start gap-4">
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-white/90 text-slate-900 shadow-md ring-1 ring-black/5 dark:bg-white/10 dark:text-white dark:ring-white/10">
<Icon className="h-5 w-5" aria-hidden="true" />
</div>
<div className="space-y-1">
<CardTitle className="text-base font-semibold text-slate-900 dark:text-white">
{title}
</CardTitle>
<CardDescription className="text-sm text-slate-600 dark:text-slate-100/80">
{description}
</CardDescription>
</div>
</div>
{badge && <div className="relative">{badge}</div>}
</div>
</CardHeader>
<CardContent
className={cn(
"px-6 py-6 text-slate-700 sm:px-8 dark:text-slate-200",
contentClassName,
)}
>
{children}
</CardContent>
</>
)}
</Card>
);
if (isCollapsible) {
return (
<motion.div
initial={{ opacity: 0, y: 18 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.45, delay }}
>
<Collapsible
open={!isCollapsed}
onOpenChange={(open) => onCollapsedChange?.(!open)}
>
{card}
</Collapsible>
</motion.div>
);
}
return (
<motion.div
initial={{ opacity: 0, y: 18 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.45, delay }}
>
{card}
</motion.div>
);
}
Shell component for settings sections with consistent styling and animation. Wraps section content with a card, icon, title, and optional badge. Supports optional collapsible behavior when isCollapsible is true.