0 ? maxHeight : undefined, overflowY: 'auto' }}
>
{items.map((item, i) => (
))}
);
}
// Folder Tree Item
function FolderTreeItem({
node,
depth,
selectedFilter,
onSelectFolder,
onMoreClick,
isDragOver,
onDragOver,
onDragLeave,
onDrop,
}: {
node: ContactFolderTreeNode;
depth: number;
selectedFilter: ContactFilter;
onSelectFolder: (folderId: string) => void;
onMoreClick: (e: React.MouseEvent, folderId: string) => void;
isDragOver: boolean;
onDragOver: (e: React.DragEvent, folderId: string) => void;
onDragLeave: (folderId: string) => void;
onDrop: (e: React.DragEvent, folderId: string) => void;
}) {
const [expanded, setExpanded] = useState(true);
const folderKey = `folder:${node.id}` as ContactFilter;
const isActive = selectedFilter === folderKey;
return (
{
// Prevent drag when the click originated from the more-options button
const target = e.target as HTMLElement;
if (target.tagName === 'BUTTON' || target.closest('button[aria-label="Optionen"]')) {
e.preventDefault();
return;
}
e.dataTransfer.setData('text/folder-id', node.id);
e.dataTransfer.effectAllowed = 'move';
}}
onDragOver={(e) => onDragOver(e, node.id)}
onDragLeave={() => onDragLeave(node.id)}
onDrop={(e) => onDrop(e, node.id)}
className={clsx(
'group flex items-center gap-1.5 px-2 py-1.5 text-sm font-medium rounded-md cursor-pointer min-h-touch',
'transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',
isDragOver
? 'bg-primary-100 ring-2 ring-primary-400'
: isActive
? 'bg-primary-50 text-primary-700'
: 'text-secondary-700 hover:bg-secondary-100',
)}
style={{ paddingLeft: depth * 12 + 8 }}
onClick={() => {
setExpanded(!expanded);
onSelectFolder(node.id);
}}
>
{chevron(expanded)}
{icon(ICONS.folder, 'w-4 h-4 text-secondary-400')}
{node.name}
{node.contact_count > 0 && (
{node.contact_count}
)}
{expanded && node.children.map((child) => (
))}
);
}
// Main Component
export function ContactFolderTree({
selectedFilter,
onSelect,
tags,
loading,
contacts = [],
}: ContactFolderTreeProps) {
const { t } = useTranslation();
const [tagsOpen, setTagsOpen] = useState(true);
const [dropdown, setDropdown] = useState