Reflex bindings for Atlassian Pragmatic drag and drop (sortable lists, Kanban) in pure Python
Project description
reflex-pragmatic-drag-and-drop
Reflex bindings for Atlassian's Pragmatic drag and drop. Build sortable lists and Kanban boards in pure Python, without writing JavaScript.
Wraps the full suite: @atlaskit/pragmatic-drag-and-drop (core),
-hitbox (closest edge), -auto-scroll, and -react-drop-indicator.
Status
Functional core (Phases 1–3 of the plan) with a test suite. See specs/
for the complete design (PRD, API, Tech Design, Data Model, Plan).
Requirements
- Python ≥ 3.12 · Reflex ≥ 0.9 ·
uvpackage manager
Installation and running (Kanban demo)
uv sync # installs Python dependencies
uv run reflex run # installs @atlaskit packages in .web and starts on :3000
Open http://localhost:3000 and drag the cards between columns.
Usage
import reflex as rx
import reflex_pragmatic_dnd as dnd
class State(rx.State):
msg: str = ""
@rx.event
def on_drop(self, payload: dict):
self.msg = f"{payload['source']} -> {payload.get('target')}"
def index():
return rx.box(
# Global listener: a single handler for the whole page.
dnd.monitor(on_drop=State.on_drop),
# A draggable element that carries data.
dnd.draggable(
rx.text("Drag me"),
drag_id="card-1",
item_data={"cardId": "card-1"},
),
# A drop target with edge detection (for reordering).
dnd.drop_target(
rx.text("Drop it here"),
drop_id="zone-1",
target_data={"kind": "zone"},
with_closest_edge=True,
allowed_edges=["top", "bottom"],
),
rx.text(State.msg),
)
Components
| Factory | Wraps | Events |
|---|---|---|
dnd.draggable(...) |
draggable (element adapter) |
on_drag_start, on_drop |
dnd.drop_target(...) |
dropTargetForElements (+ hitbox) |
on_drag_enter, on_drag_leave, on_drop |
dnd.monitor(...) |
monitorForElements |
on_drag_start, on_drop |
dnd.scroll_container(...) |
autoScrollForElements |
— |
Full details on props and payloads: specs/api/component-api-v1.md.
State reducers (optional)
The library includes two pure functions that transform the payload of
monitor(on_drop=...) into the new state, implementing the rules of
specs/data-model/event-payloads.md §4.
They do not mutate their inputs and return the original object unchanged on a no-op
(dropping outside, onto itself, or onto an unknown column):
@rx.event
def handle_drop(self, payload: dict):
self.cards = dnd.move_card(self.cards, payload, columns=["todo", "doing", "done"])
@rx.event
def reorder(self, payload: dict):
self.items = dnd.reorder_list(self.items, payload)
Visual states (CSS)
drop_target exposes attributes on the DOM for styling during the drag, and
draggable marks the element in progress:
| Attribute | Value | Component |
|---|---|---|
data-dragging |
true/false |
draggable |
data-over |
true/false |
drop_target |
data-closest-edge |
top/bottom/left/right/"" |
drop_target (with with_closest_edge) |
data-drop-id |
the drop_id |
drop_target |
dnd.drop_target(
rx.text("Drop it here"),
drop_id="zone-1",
with_closest_edge=True,
# Highlight the target and draw a line on the closest edge.
style={
"&[data-over='true']": {"background": "var(--accent-3)"},
"&[data-closest-edge='top']": {"box_shadow": "inset 0 2px 0 var(--accent-9)"},
"&[data-closest-edge='bottom']": {"box_shadow": "inset 0 -2px 0 var(--accent-9)"},
},
)
Examples
- Sortable Kanban:
reflex_pragmatic_drag_and_drop/reflex_pragmatic_drag_and_drop.py(default app). - Sortable list:
examples/sortable_list.py.
Structure
reflex_pragmatic_dnd/ # the library (wrappers + JSX glue)
reflex_pragmatic_drag_and_drop/ # Kanban demo app
examples/ # additional examples
specs/ # SDD documentation
How it works
A local React glue (pragmatic_dnd.jsx, bundled with rx.asset) attaches
Pragmatic to the DOM elements via useEffect/useRef and emits JSON-serializable
payloads. NoSSRComponent wrappers expose them as Reflex components with typed
events. Only discrete events (start/drop) cross the WebSocket; the continuous
computation happens on the client. See
specs/technical/architecture.md.
Tests
uv run pytest
Covers the pure reducers (transformation rules from Data Model §4 and edge cases
from API Spec §4), the states of the demo/example app, and the wrapper contract
(tags, snake↔camel props, events, NoSSRComponent, pinned @atlaskit
dependencies).
License
MIT.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file reflex_pragmatic_drag_and_drop-0.1.0.tar.gz.
File metadata
- Download URL: reflex_pragmatic_drag_and_drop-0.1.0.tar.gz
- Upload date:
- Size: 17.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
67c272f130be697f167ebf0e03d53c4767b0ae9cf0c62a9df541b9916bdd9600
|
|
| MD5 |
7cd33658f491f2c68530336d01ea6de6
|
|
| BLAKE2b-256 |
80dafc221e95e3632843175e75eb320494457c69a99da7195a007084663068f7
|
File details
Details for the file reflex_pragmatic_drag_and_drop-0.1.0-py3-none-any.whl.
File metadata
- Download URL: reflex_pragmatic_drag_and_drop-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6b12c184b19d58a74bfacd9c78f95a6617f9ae5ae54a3941720f70c4b9b71198
|
|
| MD5 |
039d482222f761fa79ba2f610a52d8da
|
|
| BLAKE2b-256 |
c2a7e61e0ef1a10ea4dac8a1acd52d02c1c0d34e483ac736ba8e72a4f3015c40
|