fix(webapp): align tree mouse and keyboard interactions (#4701)
## Summary Move tree selection onto semantic tree items and use native expansion buttons. Dashboard and story tree rows now share mouse and keyboard selection through `getNodeProps`. Expand and collapse affordances are named buttons instead of clickable layout elements. Base: [#4700](https://github.com/triggerdotdev/trigger.dev/pull/4700)
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
area: webapp
|
||||
type: fix
|
||||
---
|
||||
|
||||
Run trace rows now respond consistently to mouse and keyboard selection, including Alt-click expansion controls.
|
||||
+22
-8
@@ -968,6 +968,11 @@ function TasksTreeView({
|
||||
},
|
||||
});
|
||||
|
||||
const getInteractiveNodeProps = (id: string) => ({
|
||||
...getNodeProps(id),
|
||||
onClick: () => selectNode(id),
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="grid h-full grid-rows-[2.5rem_1fr_3.25rem] overflow-hidden">
|
||||
<div className="flex items-center justify-between gap-2 border-b border-grid-dimmed px-1.5">
|
||||
@@ -1047,7 +1052,7 @@ function TasksTreeView({
|
||||
autoFocus
|
||||
tree={events}
|
||||
nodes={nodes}
|
||||
getNodeProps={getNodeProps}
|
||||
getNodeProps={getInteractiveNodeProps}
|
||||
getTreeProps={getTreeProps}
|
||||
parentClassName="pl-3"
|
||||
renderNode={({ node, state, index }) => (
|
||||
@@ -1058,9 +1063,6 @@ function TasksTreeView({
|
||||
? "bg-grid-dimmed hover:bg-grid-bright"
|
||||
: "bg-transparent hover:bg-grid-dimmed"
|
||||
)}
|
||||
onClick={() => {
|
||||
selectNode(node.id);
|
||||
}}
|
||||
>
|
||||
<div className="flex h-8 items-center">
|
||||
{Array.from({ length: node.level }).map((_, index) => (
|
||||
@@ -1070,9 +1072,18 @@ function TasksTreeView({
|
||||
isSelected={state.selected}
|
||||
/>
|
||||
))}
|
||||
<div
|
||||
<button
|
||||
type="button"
|
||||
tabIndex={-1}
|
||||
aria-label={
|
||||
node.hasChildren
|
||||
? state.expanded
|
||||
? "Collapse task"
|
||||
: "Expand task"
|
||||
: "Select task"
|
||||
}
|
||||
className={cn(
|
||||
"flex h-8 w-4 items-center",
|
||||
"flex h-8 w-4 items-center focus-custom",
|
||||
node.hasChildren && "hover:bg-surface-control"
|
||||
)}
|
||||
onClick={(e) => {
|
||||
@@ -1083,10 +1094,13 @@ function TasksTreeView({
|
||||
} else {
|
||||
expandAllBelowDepth(node.level);
|
||||
}
|
||||
} else {
|
||||
} else if (node.hasChildren) {
|
||||
toggleExpandNode(node.id);
|
||||
} else {
|
||||
selectNode(node.id, false);
|
||||
}
|
||||
scrollToNode(node.id);
|
||||
parentRef.current?.focus({ preventScroll: true });
|
||||
}}
|
||||
>
|
||||
{node.hasChildren ? (
|
||||
@@ -1098,7 +1112,7 @@ function TasksTreeView({
|
||||
) : (
|
||||
<div className="h-8 w-4" />
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="flex w-full items-center justify-between gap-2 pl-1">
|
||||
|
||||
@@ -177,6 +177,11 @@ function TreeViewParent({
|
||||
},
|
||||
});
|
||||
|
||||
const getInteractiveNodeProps = (id: string) => ({
|
||||
...getNodeProps(id),
|
||||
onClick: () => toggleNodeSelection(id),
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="flex w-72 flex-col items-start gap-y-4 p-4">
|
||||
<div className="flex items-center gap-2">
|
||||
@@ -203,7 +208,7 @@ function TreeViewParent({
|
||||
autoFocus
|
||||
tree={tree}
|
||||
nodes={nodes}
|
||||
getNodeProps={getNodeProps}
|
||||
getNodeProps={getInteractiveNodeProps}
|
||||
getTreeProps={getTreeProps}
|
||||
parentClassName="h-96 bg-background-deep"
|
||||
renderNode={({ node, state, index, virtualizer, virtualItem }) => (
|
||||
@@ -215,19 +220,23 @@ function TreeViewParent({
|
||||
"flex cursor-pointer items-center gap-2 py-1 hover:bg-blue-500/10",
|
||||
state.selected && "bg-blue-500/20 hover:bg-blue-500/30"
|
||||
)}
|
||||
onClick={() => {
|
||||
toggleNodeSelection(node.id);
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="h-4 w-4"
|
||||
<button
|
||||
type="button"
|
||||
tabIndex={-1}
|
||||
aria-label={
|
||||
node.hasChildren
|
||||
? state.expanded
|
||||
? "Collapse node"
|
||||
: "Expand node"
|
||||
: "Select node"
|
||||
}
|
||||
className="h-4 w-4 focus-custom"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
toggleExpandNode(node.id);
|
||||
selectNode(node.id, true);
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
console.log(e.key);
|
||||
parentRef.current?.focus();
|
||||
}}
|
||||
>
|
||||
{node.hasChildren ? (
|
||||
@@ -239,7 +248,7 @@ function TreeViewParent({
|
||||
) : (
|
||||
<DocumentIcon className="h-4 w-4" />
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
<div>{node.data.title}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user