File explorer and IDE
A code editor window built with ui.workspace: a title bar with project and branch, a filterable project tree with git status colors, editor tabs and breadcrumbs, the code editor with syntax highlighting, git markers and a minimap, a terminal with tabs, an outline panel and a status bar.


The screenshot follows the site’s theme: switch between light and dark at the top of the page to see the block in One Light and One Dark.
Run it
Section titled “Run it”From the repository root:
python examples/blocks/file_explorer.pyWhat it shows
Section titled “What it shows”ui.workspaceplaces the docks; they can be resized by dragging.ui.TreeNode.from_pathsbuilds the tree from a list of paths, with git statuses.ui.Tab.for_filepicks the icon and color of each file type.ui.terminalunderstands ANSI colors.
Components used
Section titled “Components used”| Component | Used for |
|---|---|
| Workspace | The window layout |
| Tree | Project files |
| Tab bar | Open files |
| Breadcrumbs | Path |
| Editor | Code |
| Terminal | Terminal |
| Title bar | Title bar |
| Status bar | Status bar |
| Toolbar | Editor toolbar |
| Panel header | Panel titles |
| List item | Outline |
The whole block, ready to copy. It only needs pip install pyzed-ui.
"""IDE layout block: a project tree, editor tabs with breadcrumbs, a terminal, an outline panel and a status bar."""
import pyzed as pzfrom pyzed import ui
FILES = { "src/app/main.py": '''"""Acme Cloud desktop client."""
import pyzed as pzfrom pyzed import ui
from .api import Clientfrom .views import Sidebar, Deployments
class AcmeApp(pz.App): title = "Acme Cloud" size = (1280, 800)
def __init__(self): self.client = Client.from_env() self.deployments = [] self.selected = None
def on_start(self): return self.refresh()
async def refresh(self): return ("loaded", await self.client.deployments())
def update(self, message): kind, data = message if kind == "loaded": self.deployments = data
def view(self): return ui.workspace( Deployments(items=self.deployments), left=Sidebar(selected=self.selected), )
if __name__ == "__main__": pz.run(AcmeApp)''', "src/app/api.py": "import httpx\n\n\nclass Client:\n ...\n", "src/app/views.py": "import pyzed as pz\n", "src/app/__init__.py": "", "tests/test_app.py": "def test_refresh():\n ...\n", "pyproject.toml": "[project]\nname = \"acme-cloud\"\n", "README.md": "# Acme Cloud\n", ".gitignore": "__pycache__/\n",}STATUS = {"src/app/main.py": "modified", "src/app/views.py": "created", "README.md": "modified"}OUTLINE = [("class", "AcmeApp", 0), ("variable", "title", 1), ("variable", "size", 1), ("method", "__init__", 1), ("method", "on_start", 1), ("method", "refresh", 1), ("method", "update", 1), ("method", "view", 1)]OUTLINE_ICON = {"class": ("box", "warning"), "method": ("square-function", "accent"), "variable": ("variable", "info")}TERMINAL = ("$ uv run pytest -q\n" "\x1b[32m........................................\x1b[0m [100%]\n" "\x1b[32m40 passed\x1b[0m in 1.84s\n" "$ pyzed dev src/app/main.py\n" "\x1b[36m●\x1b[0m watching src/ for changes · hot reload on\n")
class FileExplorer(pz.App): title = "acme-cloud — main.py" size = (1200, 760)
def __init__(self): self.tree = ui.TreeNode.from_paths(list(FILES), status=STATUS) self.expanded = {"src", "src/app", "tests"} self.open = ["src/app/main.py", "src/app/api.py", "README.md"] self.active = "src/app/main.py" self.texts = dict(FILES) self.cursor = (24, 18) self.query = ""
# -- actions --------------------------------------------------------------------------- def toggle(self, node_id): self.expanded ^= {node_id}
def select(self, node_id): if node_id in FILES: if node_id not in self.open: self.open.append(node_id) self.active = node_id
def close(self, path): self.open.remove(path) if self.active == path: self.active = self.open[-1] if self.open else None
def edit(self, text): self.texts[self.active] = text
# -- view ------------------------------------------------------------------------------ def project(self): return pz.column([ ui.panel_header("acme-cloud", [ui.icon_button("file-plus", None, size="xs", tooltip="New file"), ui.icon_button("folder-plus", None, size="xs", tooltip="New folder"), ui.icon_button("list-collapse", lambda: setattr(self, "expanded", set()), size="xs", tooltip="Collapse all")]), pz.container(ui.search_input(self.query, lambda v: setattr(self, "query", v), placeholder="Filter files…", size="sm"), padding=(4, 8)), ui.tree(self.tree, expanded=self.expanded, selected=self.active, on_toggle=self.toggle, on_select=self.select), ])
def outline(self): rows = [] for kind, name, depth in OUTLINE: icon, color = OUTLINE_ICON[kind] rows.append(ui.list_item(name, None, icon=icon, icon_color=self.resolved_theme().color(color), indent=depth * 14, height=26, selected=name == "refresh")) return pz.column([ui.panel_header("Outline", [ui.icon_button("arrow-down-a-z", None, size="xs")], icon="list-tree"), pz.column(rows, padding=(4, 4))])
def editor(self): if self.active is None: return ui.empty_state("No open files", "Pick a file in the project panel.", icon="file") tabs = [ui.Tab.for_file(p, dirty=p == "src/app/main.py", status=STATUS.get(p)) for p in self.open] parts = self.active.split("/") return pz.column([ ui.tab_bar(tabs, self.active, on_select=self.select, on_close=self.close, end=[ui.icon_button("columns-2", None, size="sm", tooltip="Split right")]), ui.toolbar([ui.breadcrumbs([("folder", parts[0]), *parts[1:], "AcmeApp", "refresh"])], [ui.icon_button("play", None, size="sm", tooltip="Run"), ui.icon_button("sparkles", None, size="sm", tooltip="Inline assist")]), ui.editor("ide-editor", self.texts[self.active], path=self.active, on_change=self.edit, markers={19: "modified", 20: "modified", 24: "created"}, minimap=True), ])
def view(self): line, col = self.cursor return ui.workspace( self.editor(), title_bar=ui.title_bar( [ui.title_button("acme-cloud", chevron=True), ui.title_button("feat/deployments", icon="git-branch", muted=True)], [ui.icon_button("bell", None, size="sm"), ui.avatar("KV")], center=ui.title_button("Search files…", icon="search", muted=True)), left=self.project(), right=self.outline(), bottom=pz.column([ ui.tab_bar([ui.Tab("zsh", "zsh", icon="terminal"), ui.Tab("tests", "tests", icon="flask-conical")], "zsh", end=[ui.icon_button("plus", None, size="sm"), ui.icon_button("x", None, size="sm")]), ui.terminal(TERMINAL), ]), status_bar=ui.status_bar( [ui.status_item("feat/deployments", icon="git-branch"), ui.status_item("0", icon="circle-x"), ui.status_item("2", icon="triangle-alert", icon_color=self.resolved_theme().warning)], [ui.status_item(f"Ln {line}, Col {col}"), ui.status_item("UTF-8"), ui.status_item("Python 3.13"), ui.status_item(None, icon="sparkles", tooltip="AI agent")]), left_width=250, right_width=220, bottom_height=172, )
if __name__ == "__main__": pz.run(FileExplorer)Make it yours
Section titled “Make it yours”Change theme (or self.theme = pz.themes.get("One Dark").with_accent("#e11d48")), replace the sample data with your own and split pieces into components when they grow. An AI agent with the MCP server can read this block with read_example("blocks/file_explorer") and adapt it for you.