65 lines
2.2 KiB
TypeScript
65 lines
2.2 KiB
TypeScript
import React from 'react';
|
|
import { CheckCircle2, Circle } from 'lucide-react';
|
|
|
|
import { Button } from '@/components/ui/button';
|
|
import { cn } from '@/lib/utils';
|
|
|
|
type ChecklistAction = {
|
|
label: string;
|
|
onClick: () => void;
|
|
disabled?: boolean;
|
|
};
|
|
|
|
type ChecklistRowProps = {
|
|
icon: React.ReactNode;
|
|
label: string;
|
|
hint?: string;
|
|
completed: boolean;
|
|
status: { complete: string; pending: string };
|
|
action?: ChecklistAction;
|
|
className?: string;
|
|
};
|
|
|
|
export function ChecklistRow({ icon, label, hint, completed, status, action, className }: ChecklistRowProps) {
|
|
return (
|
|
<div
|
|
className={cn(
|
|
'flex flex-col gap-3 rounded-2xl border border-white/20 bg-white/90 p-4 text-slate-900 transition duration-200 ease-out hover:-translate-y-0.5 hover:shadow-md hover:shadow-rose-300/20 md:flex-row md:items-center md:justify-between',
|
|
'dark:border-slate-800/70 dark:bg-slate-950/80 dark:text-slate-100',
|
|
className
|
|
)}
|
|
>
|
|
<div className="flex items-start gap-3">
|
|
<div
|
|
className={cn(
|
|
'flex h-11 w-11 items-center justify-center rounded-full text-base transition-colors duration-200',
|
|
completed ? 'bg-emerald-500/15 text-emerald-600 dark:text-emerald-300' : 'bg-slate-200/80 text-slate-500 dark:bg-slate-800/50'
|
|
)}
|
|
>
|
|
{icon}
|
|
</div>
|
|
<div className="space-y-1">
|
|
<p className="text-sm font-semibold leading-tight">{label}</p>
|
|
{hint ? <p className="text-xs text-slate-600 dark:text-slate-400">{hint}</p> : null}
|
|
</div>
|
|
</div>
|
|
<div className="flex flex-wrap items-center gap-2">
|
|
<span
|
|
className={cn(
|
|
'inline-flex items-center gap-1 text-xs font-medium',
|
|
completed ? 'text-emerald-600 dark:text-emerald-300' : 'text-slate-500 dark:text-slate-400'
|
|
)}
|
|
>
|
|
{completed ? <CheckCircle2 className="h-4 w-4" /> : <Circle className="h-4 w-4" />}
|
|
{completed ? status.complete : status.pending}
|
|
</span>
|
|
{action ? (
|
|
<Button size="sm" variant="outline" onClick={action.onClick} disabled={action.disabled}>
|
|
{action.label}
|
|
</Button>
|
|
) : null}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|