Drag & Drop¶
Any container view in Nib supports drag-and-drop file handling through the on_drop parameter. When a user drags files or directories from Finder onto your view, Nib invokes your callback with a list of absolute file paths.
Basic usage¶
Pass an on_drop callback to any container view:
import nib
def main(app: nib.App):
app.title = "Drop Zone"
app.icon = nib.SFSymbol("arrow.down.doc")
app.width = 300
app.height = 250
status = nib.Text("Drop files here", foreground_color=nib.Color.GRAY)
def handle_drop(paths: list[str]):
status.content = f"Received {len(paths)} file(s)"
for path in paths:
print(f"Dropped: {path}")
app.build(
nib.VStack(
controls=[
nib.SFSymbol("arrow.down.circle", font=nib.Font.system(48)),
status,
],
spacing=16,
padding=32,
on_drop=handle_drop,
border_color="gray",
border_width=1,
corner_radius=12,
)
)
nib.run(main)
Callback signature¶
The on_drop callback receives a single argument. A list of absolute file system path strings:
def handle_drop(paths: list[str]):
for path in paths:
print(path)
# e.g., "/Users/me/Desktop/report.pdf"
The paths are absolute and can point to either files or directories.
Supported container views¶
The on_drop parameter is available on all views that inherit from the base View class. Common choices for drop zones include:
VStack,HStack,ZStackScrollViewListGroupForm
nib.HStack(
controls=[nib.Text("Drop here")],
on_drop=handle_drop,
padding=24,
)
Working with dropped files¶
Reading file contents¶
def handle_drop(paths: list[str]):
for path in paths:
if path.endswith(".txt"):
with open(path, "r") as f:
content = f.read()
text_view.content = content
Checking file types¶
import os
def handle_drop(paths: list[str]):
images = [p for p in paths if p.lower().endswith((".png", ".jpg", ".jpeg", ".gif"))]
if images:
status.content = f"Received {len(images)} image(s)"
else:
status.content = "No images found"
Handling directories¶
import os
def handle_drop(paths: list[str]):
for path in paths:
if os.path.isdir(path):
files = os.listdir(path)
status.content = f"Folder with {len(files)} items"
else:
size = os.path.getsize(path)
status.content = f"{os.path.basename(path)} ({size:,} bytes)"
Related¶
- Modifiers for
on_drop - FilePicker: open and save dialogs
- VStack:
on_dropcontainer - Hotkeys and Clipboard: clipboard access