
Bonsai
A batteries-included Tree View for Jetpack Compose
Features
Roadmap
- iOS support
- Draggable nodes
- FileObserver (Android) and/or WatchService (JVM) integration
Import to your project
Add the desired dependencies to your module's build.gradle:
implementation "cafe.adriel.bonsai:bonsai-core:${latest-version}"
implementation "cafe.adriel.bonsai:bonsai-file-system:${latest-version}"
implementation "cafe.adriel.bonsai:bonsai-json:${latest-version}"
Current version: 
Usage
Bonsai comes with a handy DSL for creating high-performance, customizable trees:
- Start by creating a new tree with
Tree<T>{}
- Create nodes with
Leaf<T>() and Branch<T>()
- Call
Bonsai() to render the tree
@Composable
fun BonsaiExample {
tree = Tree {
Branch() {
Branch() {
Branch() {
Branch() {
Leaf(, customIcon = { EmojiIcon() })
Leaf(, customIcon = { EmojiIcon() })
}
}
Branch() {
Branch() {
Leaf(, customIcon = { EmojiIcon() })
}
Branch() {
Leaf(, customIcon = { EmojiIcon() })
}
}
}
}
}
Bonsai(tree)
}
Output:
Take a look at the sample app for working examples.
File System integration
Import cafe.adriel.bonsai:bonsai-file-system module to use it.
val tree = FileSystemTree(
rootPath = File(path),
selfInclude = true
)
Bonsai(
tree = tree,
style = FileSystemBonsaiStyle()
)
Output:
JSON integration
Import cafe.adriel.bonsai:bonsai-json module to use it.
val tree = JsonTree(
json = responseJson
)
Bonsai(
tree = tree,
style = JsonBonsaiStyle()
)
Output:

Expanding & Collapsing
Easily control the expanded/collapsed state of your Tree:
toggleExpansion(node)
collapseRoot() / expandRoot()
collapseAll() / expandAll()
Selecting
Selected/Unselected state is also pretty simple to control:
selectedNodes
toggleSelection(node)
selectNode(node) / unselectNode(node)
clearSelection()
Click handling
Its also possible to set custom click behaviors for your Tree. Control single, double and long clicks by using the expand and select APIs.
Bonsai(
tree = tree,
onClick = { node ->
tree.clearSelection()
tree.toggleExpansion(node)
},
onDoubleClick = { node -> },
onLongClick = { node -> }
)
Styling
Change your Tree appearance as you wish. Take a look at BonsaiStyle class for all available customizations.
Bonsai(
tree = tree,
style = BonsaiStyle(
toggleIconRotationDegrees = 0f,
toggleIcon = { node ->
rememberVectorPainter(
if (node is BranchNode && node.isExpanded) Icons.Outlined.UnfoldLess
else Icons.Outlined.UnfoldMore
)
},
nodeIconSize = 18.dp,
nodeShape = CutCornerShape(percent = 20),
nodeCollapsedIcon = { rememberVectorPainter(Icons.Outlined.Circle) },
nodeExpandedIcon = { rememberVectorPainter(Icons.Outlined.Adjust) },
nodeNameTextStyle = MaterialTheme.typography.overline
)
)
Output:
Custom nodes
Need a deeper customization? You can set customIcons and customNames for each Leaf<T>() and Branch<T>() nodes.
Leaf(
content = "Wolf",
customIcon = { EmojiIcon("🐺") }
)
Output:
