Skip to main content

Official dialogs extension for SuperNanno

Project description

NannoKit.Dialogs

Official dialogs extension for SuperNanno — a modern, lightweight set of file and message dialogs built for Textual applications.

NannoKit.Dialogs provides clean, high-level APIs for common user interactions:

  • OpenFile — select one or multiple files
  • OpenFolder — browse and select a folder
  • SaveFile — choose a location and filename with optional overwrite confirmation
  • messagebox — flexible notification and confirmation dialogs

Designed to integrate seamlessly into SuperNanno and work standalone in any Textual app.

Features

  • Automatic resolution of the running Textual App (no manual passing required in most cases)
  • Full keyboard navigation and mouse support
  • Filterable directory tree (hidden files, glob patterns)
  • Editable location field for quick path navigation
  • Multiselect support in OpenFile
  • Validation (must_exist) with inline feedback
  • Consistent styling and Escape-to-cancel behavior
  • Priority-aware isolationmessagebox and filedialogs never interrupt or replace each other; see Isolation & Priority below
  • Composable — dialogs can call each other internally (e.g. SaveFile's overwrite prompt)
  • Thorough test coverage with Textual's Pilot harness
  • Installable as a standalone package or as part of the SuperNanno ecosystem

Installation

pip install nannokit.dialogs

To also install SuperNanno core (when available):

pip install "nannokit.dialogs[supernanno]"

Quick Start

from nannokit.dialogs import OpenFile, OpenFolder, SaveFile, messagebox
from pathlib import Path

# Open file(s)
OpenFile.show(
    initial_directory=".",
    filters=["*.py", "*.toml", "*.md"],
    callback=lambda path: print("Selected:", path),
)

# Open folder
OpenFolder.show(
    initial_directory=".",
    callback=lambda folder: print("Folder:", folder),
)

# Save file
SaveFile.show(
    default_filename="untitled.txt",
    callback=lambda path: print("Save to:", path),
)

# Message dialog
messagebox.show(
    "Save changes before closing?",
    title="SuperNanno",
    buttons=messagebox.buttons.YES_NO_CANCEL,
    type=messagebox.type.WARNING,
    callback=lambda choice: print("Choice:", choice),
)

Integration with SuperNanno

In your main App class, attach the dialog manager once (recommended):

from textual.app import App
from nannokit.dialogs.core import DialogManager

class SuperNannoApp(App):
    def on_mount(self) -> None:
        DialogManager.attach(self)

After this, you can call any dialog from event handlers, actions, or bindings without additional setup.

Isolation & Priority

messagebox and filedialogs are completely isolated from one another: neither can silently cancel, replace, or bury the other. Every dialog carries a priority tier, and a shared DialogQueue decides what happens when a new dialog is requested while another is already on screen:

Situation Behaviour
Nothing currently showing The dialog is shown immediately (same as always).
A lower-priority dialog is showing The new one is stacked on top right away — Textual's screen stack keeps the interrupted dialog's state fully intact underneath, so it just picks up where it left off once the new one is dismissed.
An equal or higher-priority dialog is showing The new one is queued and shown automatically as soon as the current one is dismissed — it never interrupts, cancels, or is dropped.

Default priority tiers (nannokit.dialogs.core.DialogPriority):

class DialogPriority:
    LOW = 30      # messagebox.type.INFO / SUCCESS
    MEDIUM = 50   # OpenFile, OpenFolder, SaveFile, OpenPath
    HIGH = 100    # messagebox.type.WARNING / ERROR

This is why SaveFile's built-in overwrite confirmation (a WARNING messagebox, HIGH) always appears on top of the SaveFile dialog that spawned it (MEDIUM) and must be answered before SaveFile can proceed — and, symmetrically, why an informational messagebox.show() fired from a background task never yanks focus away from a file dialog the user is actively using.

You normally don't need to think about any of this — it's automatic. If you do need to override a dialog's default tier for a specific call, every .show(...) accepts an explicit priority=:

from nannokit.dialogs import messagebox
from nannokit.dialogs.core import DialogPriority

# An INFO box that must still interrupt an open file dialog:
messagebox.show(
    "Critical background task failed.",
    type=messagebox.type.INFO,
    priority=DialogPriority.HIGH,
    callback=on_result,
)

# ...or the equivalent, priority-first convenience form:
messagebox.show_with_priority(
    DialogPriority.HIGH,
    "Critical background task failed.",
    type=messagebox.type.INFO,
    callback=on_result,
)

OpenFile, OpenFolder, SaveFile, and OpenPath all accept the same priority= kwarg and expose the same show_with_priority(...) helper.

API Overview

File Dialogs

  • OpenFile.show(...) — Supports multiselect, filters, must_exist, priority
  • OpenFolder.show(...) — Folder-only selection
  • SaveFile.show(...) — Includes overwrite confirmation by default
  • All dialogs accept initial_directory, title, show_hidden, priority, and a callback

MessageBox

messagebox.show(
    message: str,
    title: str = "Message",
    buttons: list[str] | None = None,
    type: str = messagebox.type.INFO,
    callback: Callable[[str | None], None] | None = None,
    priority: int | None = None,
)
  • Available button presets: OK, OK_CANCEL, YES_NO, YES_NO_CANCEL, RETRY_CANCEL, etc.
  • Available types: INFO, WARNING, ERROR, SUCCESS. WARNING/ERROR default to DialogPriority.HIGH; INFO/SUCCESS default to DialogPriority.LOW.

Package Structure

nannokit/dialogs/
├── core/              # Shared manager, priority queue, base screen, and utilities
│   ├── manager.py      # DialogManager - resolves the running App
│   ├── queue.py        # DialogQueue - priority-aware presentation scheduler
│   ├── priority.py     # DialogPriority - LOW / MEDIUM / HIGH tiers
│   └── base.py         # DialogScreenBase - shared ModalScreen plumbing
├── messagebox/         # Message dialog implementation
├── filedialogs/        # OpenFile, OpenFolder, SaveFile + shared tree
└── styles/             # TCSS stylesheets

Development

# Install in editable mode with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

Roadmap / Extending

The priority/queue architecture was designed so that adding a new dialog (e.g. a ColorPicker) only requires:

  1. Subclassing DialogScreenBase and setting self.priority in __init__ (defaults to DialogPriority.MEDIUM if you don't).
  2. Calling cls._present(instance) from your dialog's own show() classmethod — isolation and queueing are handled for you.

Ideas for follow-up work:

  • A DialogPriority.CRITICAL tier (above HIGH) for things like an unhandled-exception dialog that must pre-empt even a WARNING messagebox.
  • Let DialogQueue coalesce duplicate/near-identical pending requests (e.g. two identical INFO toasts queued back to back) into one.
  • A shared DialogTheme palette (the module already exists as a reserved extension point) so a future ColorPicker and the existing dialogs pull colors from one place instead of independent .tcss hex values.
  • Optional async/await-style await OpenFile.ask(...) sugar on top of the existing callback API, for call sites that would rather await a result than provide a callback.

License

BSD 3-Clause License — see LICENSE for details.


Part of the SuperNanno ecosystem. Built to make powerful Textual applications even easier to develop.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nannokit_dialogs-0.1.32.tar.gz (29.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nannokit_dialogs-0.1.32-py3-none-any.whl (38.8 kB view details)

Uploaded Python 3

File details

Details for the file nannokit_dialogs-0.1.32.tar.gz.

File metadata

  • Download URL: nannokit_dialogs-0.1.32.tar.gz
  • Upload date:
  • Size: 29.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.9.0

File hashes

Hashes for nannokit_dialogs-0.1.32.tar.gz
Algorithm Hash digest
SHA256 a11e0ad9645a3502e17d7c2e9b3cfaa231b6ee0255f6be723bb6b82a91750ce9
MD5 989c3f225692cbe3599ed4d6425f3bda
BLAKE2b-256 201c78a221f309f9d570309977d1fc6b8667c5faa6a8ab0e10c0ad906e3e4abe

See more details on using hashes here.

File details

Details for the file nannokit_dialogs-0.1.32-py3-none-any.whl.

File metadata

File hashes

Hashes for nannokit_dialogs-0.1.32-py3-none-any.whl
Algorithm Hash digest
SHA256 e8b10030c34e60c3a25f8e3e2b8a627662634199d7f40a268ff1aeb4beb32af2
MD5 70820472d6cdd1f3ad2534a4b55d6c27
BLAKE2b-256 08d3ec65a4aac620634cbdb9c18c31fdc83a0132d740dede4fb59e2f0911e8ab

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page