feat(ui): add onNodeSelect and selectedId to ObjectGraph#40
Conversation
Make ObjectGraph labels actionable: an optional onNodeSelect callback turns each node label into a click target (drilling its path) without toggling expansion, and selectedId highlights the active node. Both props are optional so existing static trees are unaffected.
WalkthroughAdds optional node selection support to ChangesObjectGraph Node Selection
Sequence Diagram(s)sequenceDiagram
participant User
participant DefaultObjectLabel
participant ObjectGraph
User->>DefaultObjectLabel: click node label (button)
DefaultObjectLabel->>DefaultObjectLabel: stop row click propagation
DefaultObjectLabel->>ObjectGraph: onSelect(node)
ObjectGraph->>ObjectGraph: invoke onNodeSelect(node)
Note over ObjectGraph: expand/collapse and loadChildren not triggered
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Gavel summary
Totals: 1904 passed · 0 failed · 1 skipped · 4m4s |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/ui/src/data/ObjectGraph.tsx`:
- Around line 101-133: The selected label styling in DefaultObjectLabel is
currently tied to the onSelect button branch, so selectedId does not highlight
anything when onNodeSelect is omitted. Update DefaultObjectLabel in
ObjectGraph.tsx so the selected state affects both render paths, not just the
<button> case, and keep the selection styling independent of onSelect. Make sure
the selected prop is applied consistently whether the label renders as a button
or a plain span, and verify the ObjectGraph selectedId behavior still matches
the documented contract.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: eb1418dc-de2a-406d-bcde-4405650db926
📒 Files selected for processing (2)
packages/ui/src/data/ObjectGraph.test.tsxpackages/ui/src/data/ObjectGraph.tsx
| function DefaultObjectLabel<T extends ObjectGraphNode>({ | ||
| node, | ||
| onSelect, | ||
| selected = false, | ||
| }: { | ||
| node: T; | ||
| onSelect?: (node: T) => void; | ||
| selected?: boolean; | ||
| }) { | ||
| const label = onSelect ? ( | ||
| // A button so the label is a first-class click target; stopPropagation keeps | ||
| // the row's onClick (which toggles the node) from firing, so selecting a node | ||
| // never expands or collapses it. | ||
| <button | ||
| type="button" | ||
| onClick={(e) => { | ||
| e.stopPropagation(); | ||
| onSelect(node); | ||
| }} | ||
| title="Select this path" | ||
| className={cn( | ||
| "rounded px-0.5 text-left text-muted-foreground hover:text-foreground hover:underline", | ||
| selected && "bg-primary/15 text-foreground", | ||
| )} | ||
| > | ||
| {node.label} | ||
| </button> | ||
| ) : ( | ||
| <span className="text-muted-foreground">{node.label}</span> | ||
| ); | ||
| return ( | ||
| <> | ||
| <span className="text-muted-foreground">{node.label}</span> | ||
| {label} |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
selectedId highlighting silently no-ops when onNodeSelect is omitted.
selected is computed unconditionally from selectedId (Line 85) and passed into DefaultObjectLabel, but the selected styling is only applied inside the onSelect-driven <button> branch (Lines 121-124). When onSelect is undefined, the label falls back to the plain <span> (Line 129), which never reads selected at all — so passing selectedId alone (without onNodeSelect) never highlights anything, contradicting the documented contract at Line 54 ("its label is highlighted").
The existing test suite doesn't catch this because the "highlights the label" test always pairs selectedId with a no-op onNodeSelect (ObjectGraph.test.tsx Lines 63-72).
🎨 Proposed fix to decouple selected styling from onSelect
const label = onSelect ? (
<button
type="button"
onClick={(e) => {
e.stopPropagation();
onSelect(node);
}}
title="Select this path"
className={cn(
"rounded px-0.5 text-left text-muted-foreground hover:text-foreground hover:underline",
selected && "bg-primary/15 text-foreground",
)}
>
{node.label}
</button>
) : (
- <span className="text-muted-foreground">{node.label}</span>
+ <span className={cn("text-muted-foreground", selected && "bg-primary/15 text-foreground")}>
+ {node.label}
+ </span>
);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| function DefaultObjectLabel<T extends ObjectGraphNode>({ | |
| node, | |
| onSelect, | |
| selected = false, | |
| }: { | |
| node: T; | |
| onSelect?: (node: T) => void; | |
| selected?: boolean; | |
| }) { | |
| const label = onSelect ? ( | |
| // A button so the label is a first-class click target; stopPropagation keeps | |
| // the row's onClick (which toggles the node) from firing, so selecting a node | |
| // never expands or collapses it. | |
| <button | |
| type="button" | |
| onClick={(e) => { | |
| e.stopPropagation(); | |
| onSelect(node); | |
| }} | |
| title="Select this path" | |
| className={cn( | |
| "rounded px-0.5 text-left text-muted-foreground hover:text-foreground hover:underline", | |
| selected && "bg-primary/15 text-foreground", | |
| )} | |
| > | |
| {node.label} | |
| </button> | |
| ) : ( | |
| <span className="text-muted-foreground">{node.label}</span> | |
| ); | |
| return ( | |
| <> | |
| <span className="text-muted-foreground">{node.label}</span> | |
| {label} | |
| function DefaultObjectLabel<T extends ObjectGraphNode>({ | |
| node, | |
| onSelect, | |
| selected = false, | |
| }: { | |
| node: T; | |
| onSelect?: (node: T) => void; | |
| selected?: boolean; | |
| }) { | |
| const label = onSelect ? ( | |
| // A button so the label is a first-class click target; stopPropagation keeps | |
| // the row's onClick (which toggles the node) from firing, so selecting a node | |
| // never expands or collapses it. | |
| <button | |
| type="button" | |
| onClick={(e) => { | |
| e.stopPropagation(); | |
| onSelect(node); | |
| }} | |
| title="Select this path" | |
| className={cn( | |
| "rounded px-0.5 text-left text-muted-foreground hover:text-foreground hover:underline", | |
| selected && "bg-primary/15 text-foreground", | |
| )} | |
| > | |
| {node.label} | |
| </button> | |
| ) : ( | |
| <span className={cn("text-muted-foreground", selected && "bg-primary/15 text-foreground")}> | |
| {node.label} | |
| </span> | |
| ); | |
| return ( | |
| <> | |
| {label} |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/ui/src/data/ObjectGraph.tsx` around lines 101 - 133, The selected
label styling in DefaultObjectLabel is currently tied to the onSelect button
branch, so selectedId does not highlight anything when onNodeSelect is omitted.
Update DefaultObjectLabel in ObjectGraph.tsx so the selected state affects both
render paths, not just the <button> case, and keep the selection styling
independent of onSelect. Make sure the selected prop is applied consistently
whether the label renders as a button or a plain span, and verify the
ObjectGraph selectedId behavior still matches the documented contract.
Adds optional
onNodeSelectandselectedIdprops toObjectGraph.onNodeSelect(node)makes a node label an actionable click target (drills its path) without toggling expansion — the chevron stays the only expand/collapse control.selectedIdhighlights the currently-selected node's label.Both props are optional; existing static trees render unchanged.
Consumed by oipa-cli's Arthas OGNL/Spring inspector (
OgnlResultPanel→ArthasOgnlTab/ArthasSpringTab), whose docker build currently fails against published clicky-ui because these props are missing.Tests: 3 new cases in
ObjectGraph.test.tsx; all 6 ObjectGraph tests pass.Summary by CodeRabbit
New Features
Bug Fixes