feat(web): make object tree collapsible and collapsed by default
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
import type { ObjectTreeNode } from '@tts/extract';
|
import type { ObjectTreeNode } from '@tts/extract';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -38,23 +39,44 @@ function TreeNode({
|
|||||||
onSelect: (guid: string) => void;
|
onSelect: (guid: string) => void;
|
||||||
}) {
|
}) {
|
||||||
const selected = node.object.GUID === selectedGuid;
|
const selected = node.object.GUID === selectedGuid;
|
||||||
|
const hasChildren = node.children.length > 0;
|
||||||
|
const [expanded, setExpanded] = useState(false);
|
||||||
return (
|
return (
|
||||||
<li>
|
<li>
|
||||||
<button
|
<div
|
||||||
onClick={() => onSelect(node.object.GUID)}
|
className={`flex items-center rounded pr-2 ${
|
||||||
style={{ paddingLeft: `${depth * 16 + 8}px` }}
|
|
||||||
className={`block w-full truncate rounded px-2 py-1 text-left text-sm ${
|
|
||||||
selected
|
selected
|
||||||
? 'bg-zinc-700 text-zinc-100'
|
? 'bg-zinc-700 text-zinc-100'
|
||||||
: 'text-zinc-300 hover:bg-zinc-800 hover: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">
|
{hasChildren ? (
|
||||||
{node.object.Name}
|
<button
|
||||||
</span>
|
onClick={() => setExpanded((e) => !e)}
|
||||||
<span className="truncate">{node.label}</span>
|
aria-label={expanded ? 'Collapse' : 'Expand'}
|
||||||
</button>
|
className="flex h-6 w-6 shrink-0 items-center justify-center rounded text-zinc-500 hover:text-zinc-200"
|
||||||
{node.children.length > 0 && (
|
>
|
||||||
|
<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>
|
<ul>
|
||||||
{node.children.map((child, index) => (
|
{node.children.map((child, index) => (
|
||||||
<TreeNode
|
<TreeNode
|
||||||
|
|||||||
Reference in New Issue
Block a user