Skip to content

Commit 02363bf

Browse files
metonymclaude
andcommitted
feat(TreeView): add selectNode method
Add imperative selectNode(id) method to programmatically select a node without changing focus or expansion state. This fills a gap where selection was previously only possible through user interaction or the more invasive showNode method. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 02acf0b commit 02363bf

File tree

7 files changed

+84
-0
lines changed

7 files changed

+84
-0
lines changed

docs/src/pages/components/TreeView.svx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ Use `TreeView.collapseNodes` to collapse specific nodes based on a condition.
9090

9191
<FileSource src="/framed/TreeView/TreeViewCollapseNodes" />
9292

93+
## Select a specific node
94+
95+
Use `TreeView.selectNode` to programmatically select a node without changing expansion state or focus.
96+
97+
<FileSource src="/framed/TreeView/TreeViewSelectNode" />
98+
9399
## Show a specific node
94100

95101
Use `TreeView.showNode` to expand, select, and focus a specific node.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<script>
2+
import { Button, ButtonSet, TreeView } from "carbon-components-svelte";
3+
4+
const nodeSpark = { id: 3, text: "Apache Spark" };
5+
const nodeBlockchain = { id: 8, text: "IBM Blockchain Platform" };
6+
7+
let treeview = null;
8+
let nodes = [
9+
{ id: 0, text: "AI / Machine learning" },
10+
{
11+
id: 1,
12+
text: "Analytics",
13+
nodes: [
14+
{
15+
id: 2,
16+
text: "IBM Analytics Engine",
17+
nodes: [nodeSpark, { id: 4, text: "Hadoop" }],
18+
},
19+
{ id: 5, text: "IBM Cloud SQL Query" },
20+
{ id: 6, text: "IBM Db2 Warehouse on Cloud" },
21+
],
22+
},
23+
{
24+
id: 7,
25+
text: "Blockchain",
26+
nodes: [{ id: 8, text: "IBM Blockchain Platform" }],
27+
},
28+
];
29+
</script>
30+
31+
<ButtonSet style="margin-bottom: var(--cds-spacing-05)">
32+
{#each [nodeSpark, nodeBlockchain] as { id, text }}
33+
<Button
34+
on:click={() => {
35+
treeview?.selectNode(id);
36+
}}
37+
>
38+
Select "{text}"
39+
</Button>
40+
{/each}
41+
</ButtonSet>
42+
43+
<TreeView bind:this={treeview} labelText="Cloud Products" {nodes} />

src/TreeView/TreeView.svelte

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,14 @@
115115
.map((node) => node.id);
116116
}
117117
118+
/**
119+
* Programmatically select a node by `id` without changing focus or expansion state
120+
* @type {(id: TreeNodeId) => void}
121+
*/
122+
export function selectNode(id) {
123+
selectedIds = [id];
124+
}
125+
118126
/**
119127
* Programmatically show a node by `id`.
120128
* The matching node will be expanded, selected, and focused

tests/TreeView/TreeView.hierarchy.test.svelte

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,4 @@
5959
>
6060
Expand some nodes
6161
</Button>
62+
<Button on:click={() => treeview.selectNode(3)}>Select Apache Spark</Button>

tests/TreeView/TreeView.test.svelte

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,4 @@
7878
>
7979
Expand some nodes
8080
</Button>
81+
<Button on:click={() => treeview.selectNode(3)}>Select Apache Spark</Button>

tests/TreeView/TreeView.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,24 @@ describe.each(testCases)("$name", ({ component }) => {
7979
screen.getByText("IBM Analytics Engine").parentNode?.parentNode,
8080
).toHaveAttribute("aria-expanded", "true");
8181
});
82+
83+
it("can programmatically select a node without affecting expansion or focus", async () => {
84+
const consoleLog = vi.spyOn(console, "log");
85+
86+
render(component);
87+
88+
noExpandedItems();
89+
90+
const selectButton = screen.getByText("Select Apache Spark");
91+
await user.click(selectButton);
92+
93+
// Should not expand any nodes
94+
noExpandedItems();
95+
96+
// Should update selectedIds
97+
expect(consoleLog).toBeCalledWith("selectedIds", [3]);
98+
99+
// Should not trigger select event (no user interaction with tree)
100+
expect(consoleLog).not.toBeCalledWith("select", expect.any(Object));
101+
});
82102
});

types/TreeView/TreeView.svelte.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ export default class TreeView extends SvelteComponentTyped<
106106
*/
107107
collapseNodes: (filterId?: (node: TreeNode) => boolean) => void;
108108

109+
/**
110+
* Programmatically select a node by `id` without changing focus or expansion state
111+
*/
112+
selectNode: (id: TreeNodeId) => void;
113+
109114
/**
110115
* Programmatically show a node by `id`.
111116
* The matching node will be expanded, selected, and focused

0 commit comments

Comments
 (0)