๐ฒย ย Directory Tree
Submitted by streamlit-extras
Summary
Collapsible directory tree with Material icons and optional click-to-select.
Functions
directory_tree
Display a collapsible directory tree.
Renders a nested directory structure with Material icons and expand/collapse toggles. Toggling directories is purely client-side (no reruns). Optionally, clicking a node can return its path to Python.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tree
|
dict[str, Any]
|
Nested dict representing the file tree. Keys are file/directory names. Values of None indicate files; dict values indicate directories containing more entries. |
required |
expanded
|
bool | int
|
Controls initial expansion. |
False
|
border
|
bool
|
Whether to show a border around the tree container. |
False
|
color
|
str | None
|
Color for directory folder icons. Defaults to |
'primary'
|
on_select
|
Literal['rerun', 'ignore']
|
Selection mode. "ignore" means clicks don't trigger reruns (purely visual). "rerun" means clicking a node sends the path back to Python and triggers a rerun. |
'ignore'
|
height
|
int | None
|
Optional max height in pixels. If set, the tree scrolls when content exceeds this height. |
None
|
key
|
str | None
|
Unique key for this widget instance. |
None
|
Returns:
| Type | Description |
|---|---|
str | None
|
The selected node path (e.g. "src/utils/helpers.py") when |
str | None
|
on_select="rerun" and a node has been clicked, otherwise None. |
Raises:
| Type | Description |
|---|---|
StreamlitAPIException
|
If tree is not a dict. |
Example:
```python
directory_tree(
{
"src": {"main.py": None, "utils": {"helpers.py": None}},
"README.md": None,
}
)
```
Source code in src/streamlit_extras/directory_tree/__init__.py
Import:
- You should add this to the top of your .py file
Examples
example_basic
def example_basic() -> None:
"""Basic directory tree display."""
st.write("### Basic Tree (collapsed by default)")
directory_tree(
{
"src": {
"app.py": None,
"components": {
"header.tsx": None,
"sidebar.tsx": None,
},
"utils": {
"helpers.py": None,
"constants.py": None,
},
},
"tests": {
"test_app.py": None,
},
"README.md": None,
"pyproject.toml": None,
},
key="basic_tree",
)
st.write("### Fully expanded")
directory_tree(
{
"src": {
"app.py": None,
"components": {
"header.tsx": None,
"sidebar.tsx": None,
},
"utils": {
"helpers.py": None,
"constants.py": None,
},
},
"tests": {
"test_app.py": None,
},
"README.md": None,
"pyproject.toml": None,
},
expanded=True,
key="expanded_tree",
)
st.write("### Expand one level deep (expanded=1)")
directory_tree(
{
"my_app": {
"src": {
"main.py": None,
"models": {
"user.py": None,
"post.py": None,
},
"routes": {
"auth.py": None,
"api.py": None,
},
},
"tests": {
"test_main.py": None,
"test_models.py": None,
},
"pyproject.toml": None,
},
},
expanded=1,
key="depth1_tree",
)
example_colors
def example_colors() -> None:
"""Folder icon color options."""
st.write("### Default (primary color)")
directory_tree(
{
"project": {
"src": {"index.ts": None, "utils": {"format.ts": None}},
"package.json": None,
},
},
expanded=True,
border=True,
key="color_primary",
)
st.write("### No color (color=None)")
directory_tree(
{
"project": {
"src": {"index.ts": None, "utils": {"format.ts": None}},
"package.json": None,
},
},
expanded=True,
border=True,
color=None,
key="color_none",
)
st.write("### Custom colors")
col1, col2, col3 = st.columns(3)
with col1:
directory_tree(
{"docs": {"guide.md": None, "api.md": None}},
expanded=True,
color="#2196F3",
key="color_blue",
)
with col2:
directory_tree(
{"src": {"main.py": None, "utils.py": None}},
expanded=True,
color="#4CAF50",
key="color_green",
)
with col3:
directory_tree(
{"assets": {"logo.svg": None, "style.css": None}},
expanded=True,
color="#FF9800",
key="color_orange",
)
example_height
def example_height() -> None:
"""Fixed height with scrollable overflow."""
st.write("### Fixed height (height=150)")
directory_tree(
{
"large_project": {
"src": {
"components": {
"Button.tsx": None,
"Modal.tsx": None,
"Sidebar.tsx": None,
"Header.tsx": None,
"Footer.tsx": None,
"Card.tsx": None,
"Avatar.tsx": None,
},
"hooks": {
"useAuth.ts": None,
"useTheme.ts": None,
"useData.ts": None,
},
"pages": {
"Home.tsx": None,
"Dashboard.tsx": None,
"Settings.tsx": None,
"Profile.tsx": None,
},
"App.tsx": None,
"index.tsx": None,
},
"public": {
"index.html": None,
"favicon.ico": None,
},
"package.json": None,
"tsconfig.json": None,
"README.md": None,
},
},
expanded=True,
border=True,
height=150,
key="height_tree",
)
st.write("### Long filenames get ellipsis")
directory_tree(
{
"src": {
"this_is_a_very_long_filename_that_should_be_truncated_with_ellipsis.tsx": None,
"another_extremely_long_component_name_for_testing_overflow.test.tsx": None,
"components": {
"SuperLongComponentNameThatExceedsTheContainerWidth.tsx": None,
"short.ts": None,
},
},
},
expanded=True,
border=True,
key="long_names_tree",
)
st.write("### Taller height (height=300)")
directory_tree(
{
"monorepo": {
"apps": {
"web": {
"src": {"App.tsx": None, "main.tsx": None},
"package.json": None,
},
"mobile": {
"src": {"App.tsx": None, "main.tsx": None},
"package.json": None,
},
"api": {
"src": {"server.ts": None, "routes.ts": None},
"package.json": None,
},
},
"packages": {
"ui": {"src": {"Button.tsx": None, "Input.tsx": None}},
"utils": {"src": {"format.ts": None, "validate.ts": None}},
"config": {"src": {"theme.ts": None, "env.ts": None}},
},
"turbo.json": None,
"package.json": None,
},
},
expanded=2,
border=True,
height=300,
key="height_tree_tall",
)
example_interactive
def example_interactive() -> None:
"""Interactive tree with click-to-select."""
st.write("### Click to select a file")
selected = directory_tree(
{
"frontend": {
"src": {
"App.tsx": None,
"index.tsx": None,
"components": {
"Button.tsx": None,
"Modal.tsx": None,
"Sidebar.tsx": None,
"Header.tsx": None,
},
},
"package.json": None,
"tsconfig.json": None,
},
"backend": {
"main.py": None,
"routes": {
"auth.py": None,
"api.py": None,
"users.py": None,
},
"models": {
"user.py": None,
"session.py": None,
},
},
},
on_select="rerun",
border=True,
expanded=2,
height=200,
key="interactive_tree",
)
if selected:
st.success(f"Selected: `{selected}`")