feat(web): make object tree collapsible and collapsed by default

This commit is contained in:
2026-08-08 12:27:23 +08:00
parent f126bf7993
commit 3b66e82b67
+32 -10
View File
@@ -1,3 +1,4 @@
import { useState } from 'react';
import type { ObjectTreeNode } from '@tts/extract';
interface Props {
@@ -38,23 +39,44 @@ function TreeNode({
onSelect: (guid: string) => void;
}) {
const selected = node.object.GUID === selectedGuid;
const hasChildren = node.children.length > 0;
const [expanded, setExpanded] = useState(false);
return (
<li>
<button
onClick={() => onSelect(node.object.GUID)}
style={{ paddingLeft: `${depth * 16 + 8}px` }}
className={`block w-full truncate rounded px-2 py-1 text-left text-sm ${
<div
className={`flex items-center rounded pr-2 ${
selected
? 'bg-zinc-700 text-zinc-100'
: 'text-zinc-300 hover:bg-zinc-800 hover:text-zinc-100'
}`}
style={{ paddingLeft: `${depth * 16 + 4}px` }}
>
<span className="mr-1.5 rounded bg-zinc-800 px-1 py-0.5 text-xs uppercase text-zinc-500">
{node.object.Name}
</span>
<span className="truncate">{node.label}</span>
</button>
{node.children.length > 0 && (
{hasChildren ? (
<button
onClick={() => setExpanded((e) => !e)}
aria-label={expanded ? 'Collapse' : 'Expand'}
className="flex h-6 w-6 shrink-0 items-center justify-center rounded text-zinc-500 hover:text-zinc-200"
>
<span
className={`inline-block text-xs transition-transform ${expanded ? 'rotate-90' : ''}`}
>
</span>
</button>
) : (
<span className="h-6 w-6 shrink-0" />
)}
<button
onClick={() => onSelect(node.object.GUID)}
className="block min-w-0 flex-1 truncate py-1 text-left text-sm"
>
<span className="mr-1.5 rounded bg-zinc-800 px-1 py-0.5 text-xs uppercase text-zinc-500">
{node.object.Name}
</span>
<span className="truncate">{node.label}</span>
</button>
</div>
{hasChildren && expanded && (
<ul>
{node.children.map((child, index) => (
<TreeNode