fluent-filepicker
Fluent Design file picker widgets for PyQt6.
Drop-in widgets that let users select files via drag & drop or a native file dialog — styled after Microsoft's Fluent Design System, with full dark and light theme support.
Features
- Single-file and multi-file picker widgets
- Drag & drop with live valid / invalid visual feedback
- Native file-dialog integration (single and multi-select)
- Extension filtering with "Supported: .pdf, .png …" hint
- Compact flow-wrapped file chips with remove buttons
- Extension colour-coded badges (PDF → red, XLSX → green, …)
- Dark and light Fluent themes
- No external dependencies beyond PyQt6
Requirements
| Dependency | Version |
|---|---|
| Python | ≥ 3.9 |
| PyQt6 | ≥ 6.4.0 |
Installation
pip install fluent-filepicker
Quick start
Single-file picker
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout
from fluent_filepicker import DropSingleFileWidget, Theme
app = QApplication(sys.argv)
window = QMainWindow()
container = QWidget()
layout = QVBoxLayout(container)
picker = DropSingleFileWidget(theme=Theme.DARK)
picker.set_allowed_extensions(["pdf", "docx", "png"])
picker.set_dialog_title("Choose a document")
picker.file_selected.connect(lambda path: print(f"Selected: {path}"))
picker.file_cleared.connect(lambda: print("Selection cleared"))
layout.addWidget(picker)
window.setCentralWidget(container)
window.resize(500, 300)
window.show()
sys.exit(app.exec())
Multi-file picker
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout
from fluent_filepicker import DropMultiFilesWidget, Theme
app = QApplication(sys.argv)
window = QMainWindow()
container = QWidget()
layout = QVBoxLayout(container)
picker = DropMultiFilesWidget(theme=Theme.LIGHT)
picker.set_allowed_extensions(["jpg", "png", "webp"])
picker.set_max_file_count(10)
picker.set_dialog_title("Choose images")
picker.files_changed.connect(lambda paths: print(f"{len(paths)} file(s) selected"))
picker.file_added.connect(lambda path: print(f"Added: {path}"))
picker.file_removed.connect(lambda path: print(f"Removed: {path}"))
layout.addWidget(picker)
window.setCentralWidget(container)
window.resize(600, 400)
window.show()
sys.exit(app.exec())
API reference
Theme
from fluent_filepicker import Theme
Theme.DARK # dark Fluent theme (default)
Theme.LIGHT # light Fluent theme
DropSingleFileWidget
DropSingleFileWidget(
parent=None,
theme=Theme.DARK,
allowed_extensions=None, # e.g. ["pdf", "png"]
)
Signals
| Signal | Payload | Description |
|---|---|---|
file_selected |
str |
Emitted when a file is selected |
file_cleared |
— | Emitted when the selection is cleared |
Methods
| Method | Description |
|---|---|
set_theme(theme) |
Switch dark / light theme |
set_allowed_extensions(exts) |
Set accepted extensions (None = all) |
set_dialog_title(title) |
File-dialog window title |
set_dialog_directory(path) |
Default directory for the dialog |
set_hint_text(text) |
Text shown in the empty drop zone |
set_browse_text(text) |
Clickable "browse" text in the drop zone |
set_browse_button_text(text) |
Label of the button below the drop zone |
set_browse_button_visible(visible) |
Show / hide the browse button |
current_file() |
Return current path or None |
set_file(path) |
Programmatically set / clear the file |
clear_file() |
Clear selection and emit file_cleared |
has_file() |
True if a file is selected |
DropMultiFilesWidget
DropMultiFilesWidget(
parent=None,
theme=Theme.DARK,
allowed_extensions=None,
)
Signals
| Signal | Payload | Description |
|---|---|---|
files_changed |
list[str] |
Emitted on any change to the file list |
file_added |
str |
Emitted when a file is added |
file_removed |
str |
Emitted when a file is removed |
Methods
| Method | Description |
|---|---|
set_theme(theme) |
Switch dark / light theme |
set_allowed_extensions(exts) |
Set accepted extensions (None = all) |
set_max_file_count(n) |
Maximum number of files (None = unlimited) |
set_dialog_title(title) |
File-dialog window title |
set_dialog_directory(path) |
Default directory for the dialog |
set_hint_text(text) |
Text shown in the drop zone |
set_browse_text(text) |
Clickable "browse" text in the drop zone |
set_browse_button_text(text) |
Label of the "Add files" button |
set_browse_button_visible(visible) |
Show / hide the button |
current_files() |
Return list[str] of current paths |
set_files(paths) |
Replace the file list programmatically |
add_file(path) |
Add a single file; returns True if added |
remove_file(path) |
Remove a specific file |
clear_files() |
Remove all files |
file_count() |
Number of files currently selected |
has_files() |
True if at least one file is selected |
Theming
Both widgets adapt automatically when you call set_theme():
from fluent_filepicker import Theme
picker.set_theme(Theme.LIGHT)
picker.set_theme(Theme.DARK)
For system-level auto-switching you can connect to your own theme-change signal and propagate it:
system_theme_changed.connect(
lambda dark: picker.set_theme(Theme.DARK if dark else Theme.LIGHT)
)
Supported extension colours
Badges on file chips are colour-coded automatically:
| Category | Extensions | Colour |
|---|---|---|
| Red | ||
| Word | doc, docx | Blue |
| Excel | xls, xlsx | Green |
| PowerPoint | ppt, pptx | Orange |
| Images | png, jpg, jpeg, gif, webp | Teal |
| SVG | svg | Amber |
| Python | py | Steel blue |
| JavaScript | js | Yellow |
| TypeScript | ts | Blue |
| HTML | html | Orange-red |
| CSS | css | Blue |
| JSON | json | Dark amber |
| Plain text | txt | Grey |
| Archives | zip, rar, 7z | Purple |
| Video | mp4 | Blue |
| Audio | mp3, wav | Mint |
Unknown extensions receive a neutral grey badge.
License
MIT — see LICENSE for details.
Metadata
Release files for fluent-filepicker 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| fluent_filepicker-0.1.0.tar.gz | 19.9 kB | Without provenance | Details for fluent_filepicker-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| fluent_filepicker-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for fluent_filepicker-0.1.0-py3-none-any.whl |
Total release size: 40.6 kB
Release files / fluent_filepicker-0.1.0.tar.gz
| Download URL | fluent_filepicker-0.1.0.tar.gz |
|---|---|
| Size | 19.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f2babb3f23494ce90bb27ba7be86db32004f3e7584b26388ec569c2c921f8f70
|
|
BLAKE2b-256 checksum How to use checksums |
80b4ecaf1f37ba6a1abb1e14e29f769ab74907c97d3886401ff25f04e92683b6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.2
|
Release files / fluent_filepicker-0.1.0-py3-none-any.whl
| Download URL | fluent_filepicker-0.1.0-py3-none-any.whl |
|---|---|
| Size | 20.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c9085ba1ba367b62120931029d9971857e0cf54e5bb236efc6d4ef6bf82956ea
|
|
BLAKE2b-256 checksum How to use checksums |
16c831640e3568967c4ba34ce1f252e1f86f2be418881c2c1403d8ad7e0a66a3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.2
|
Security for fluent-filepicker 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.