Files
resolutionflow/frontend/src/components/library/TreeListView.tsx
chihlasm f4ce1595d6 feat: implement monochrome design system across entire frontend
Migrate all 84 frontend files from the old themed/colored design to a
monochrome glass-morphism design system. Pure black backgrounds, white
text with opacity levels, glass-card components with backdrop-blur, and
functional color reserved for status indicators only.

Foundation: remap CSS variables to monochrome, simplify Tailwind config,
remove theme toggle, convert brand logo/wordmark to white. Pages: all
14 pages updated. Components: all common, library, session, step-library,
tree-editor, tree-preview, admin, and subscription components converted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 21:41:29 -05:00

124 lines
4.5 KiB
TypeScript

import { Link } from 'react-router-dom'
import { Pencil, Globe, Lock, GitBranch, FileText } from 'lucide-react'
import type { TreeListItem } from '@/types'
import { TagBadges } from '@/components/common/TagBadges'
import { AddToFolderMenu } from './AddToFolderMenu'
import { cn } from '@/lib/utils'
import { usePermissions } from '@/hooks/usePermissions'
interface TreeListViewProps {
trees: TreeListItem[]
onStartSession: (treeId: string) => void
onTagClick: (tag: string) => void
onFolderCreated: (parentId?: string | null) => void
onDeleteTree: (tree: TreeListItem) => void
onForkTree?: (treeId: string) => void
}
export function TreeListView({
trees,
onStartSession,
onTagClick,
onFolderCreated,
onForkTree,
}: TreeListViewProps) {
const { canEditTree } = usePermissions()
return (
<div className="space-y-2">
{trees.map((tree) => (
<div
key={tree.id}
className="flex items-center gap-4 glass-card rounded-2xl p-4 transition-all hover:border-white/20 hover:shadow-sm"
>
{/* Left: Name and Description */}
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2 mb-1">
<h3 className="font-semibold text-white truncate">{tree.name}</h3>
{tree.status === 'draft' && (
<span className="inline-flex items-center gap-1 rounded-full bg-yellow-400/10 px-2 py-0.5 text-xs font-medium text-yellow-400 flex-shrink-0">
<FileText className="h-3 w-3" />
Draft
</span>
)}
{tree.is_public ? (
<span title="Public tree">
<Globe className="h-3.5 w-3.5 text-white/40 flex-shrink-0" />
</span>
) : (
<span title="Private tree">
<Lock className="h-3.5 w-3.5 text-white/40 flex-shrink-0" />
</span>
)}
</div>
<p className="text-sm text-white/70 truncate">
{tree.description || 'No description available'}
</p>
</div>
{/* Center: Category and Tags */}
<div className="hidden lg:flex items-center gap-2 min-w-0" style={{ maxWidth: '300px' }}>
{tree.category_info && (
<span className="rounded-full bg-white/10 px-2 py-0.5 text-xs text-white/70 whitespace-nowrap">
{tree.category_info.name}
</span>
)}
{tree.tags && tree.tags.length > 0 && (
<div className="min-w-0">
<TagBadges tags={tree.tags} maxVisible={2} onTagClick={onTagClick} />
</div>
)}
</div>
{/* Right: Metadata and Actions */}
<div className="flex items-center gap-3 flex-shrink-0">
<div className="hidden sm:flex flex-col items-end text-xs text-white/40">
<span>v{tree.version}</span>
<span>{tree.usage_count} uses</span>
</div>
<div className="flex items-center gap-2">
<AddToFolderMenu treeId={tree.id} onFolderCreated={onFolderCreated} />
{onForkTree && (
<button
type="button"
onClick={() => onForkTree(tree.id)}
className={cn(
'rounded-md border border-white/10 p-1.5 text-white/60',
'hover:bg-white/10 hover:text-white'
)}
title="Fork tree"
>
<GitBranch className="h-4 w-4" />
</button>
)}
{canEditTree({ author_id: tree.author_id, account_id: tree.account_id }) && (
<Link
to={`/trees/${tree.id}/edit`}
className={cn(
'rounded-md border border-white/10 p-1.5 text-white/60',
'hover:bg-white/10 hover:text-white'
)}
title="Edit tree"
>
<Pencil className="h-4 w-4" />
</Link>
)}
<button
type="button"
onClick={() => onStartSession(tree.id)}
className={cn(
'rounded-md bg-white px-3 py-1.5 text-sm font-medium text-black',
'hover:bg-white/90 whitespace-nowrap'
)}
>
Start
</button>
</div>
</div>
</div>
))}
</div>
)
}