Files
med-plan-assistant/src/components/ui/collapsible-card-header.tsx

60 lines
2.0 KiB
TypeScript

/**
* CollapsibleCardHeader
*
* Shared header row with a title + chevron toggle, optional children after title/chevron,
* and an optional right section for action buttons.
*/
import React from 'react';
import { ChevronDown, ChevronUp } from 'lucide-react';
import { CardHeader, CardTitle } from './card';
import { cn } from '../../lib/utils';
interface CollapsibleCardHeaderProps {
title: React.ReactNode;
isCollapsed: boolean;
onToggle: () => void;
children?: React.ReactNode;
rightSection?: React.ReactNode;
className?: string;
titleClassName?: string;
toggleLabel?: string;
}
const CollapsibleCardHeader: React.FC<CollapsibleCardHeaderProps> = ({
title,
isCollapsed,
onToggle,
children,
rightSection,
className,
titleClassName,
toggleLabel
}) => {
const accessibilityProps = toggleLabel ? { title: toggleLabel, 'aria-label': toggleLabel } : {};
return (
<CardHeader className={cn('pb-3', className)}>
<div className="flex items-start justify-between gap-3">
<div className="flex items-center gap-2 flex-wrap flex-1">
<button
type="button"
onClick={onToggle}
className="inline-flex items-center gap-2 rounded-md px-1 py-1 -ml-1 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 hover:bg-muted/60 cursor-pointer"
aria-expanded={!isCollapsed}
{...accessibilityProps}
>
<CardTitle className={cn('text-lg', titleClassName)}>
{title}
</CardTitle>
{isCollapsed ? <ChevronDown className="h-5 w-5 flex-shrink-0" /> : <ChevronUp className="h-5 w-5 flex-shrink-0" />}
</button>
{children && <div className="flex items-center gap-2 flex-nowrap">{children}</div>}
</div>
{rightSection && <div className="flex items-center gap-2">{rightSection}</div>}
</div>
</CardHeader>
);
};
export default CollapsibleCardHeader;