Changelog
Version history of dash-flows. The timeline on this page is rendered from
CHANGELOG.md, reproduced below.
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
Changed
- dash-improve-my-llms floored at 2.8.0 (the ledger round, sync items
12+13). lib/analytics_tracker.py now delegates bot classification to the package's classify() instead of its own year-old User-Agent list (which filed ClaudeBot — Anthropic's training crawler — under "search"). Reporting consequence: human_hits DROPS and bot_hits RISES on the day this deploys, because UA-less and library clients (httpx, Go-http-client, node-fetch, an empty UA) move from human to crawler. That is the number becoming true, not a regression — the hub's day-over-day view will show the step.
- The ledger gains a
readstable (on_document_read→ new
AnalyticsTracker.record_read): one row per corpus document the package serves (tier, verdict, bytes, verified vendor). lib/ traffic_rollup.py's rollup gains an additive vendors[] block on any day with reads, and a new /admin/traffic page shows this host its own vendor × day / vendor → tier ledger, gated exactly like the control board.
- Render now deploys the
releasebranch, written only by
.github/workflows/cd.yml's deploy job as a fast-forward push after the CI matrix is green (sync item 13). A push to main is a candidate, not a deploy; verify now runs only when deploy succeeds and re-checks /healthz build == $GITHUB_SHA itself before smoke testing. See DIVERGENCES.md's posture fence (deploy: release-branch).
- **Training crawlers (GPTBot, ClaudeBot, CCBot, …) are allowed by
default** (sync item 15): run.py's RobotsConfig(block_ai_training= False, …) — since sync item 12 every corpus read is a ledger row this app keeps, so a training-crawler fetch is now recorded and priceable instead of walled outright. robots.txt carries no Disallow stanza for them at all; the package's bot middleware stops 403ing / and /healthz for them too. allow_ai_search / allow_traditional are unchanged.
- **Navigation, /changelog, /api and /admin/traffic follow the fleet's
navigation contract (sync item 16): the sidebar's sections now come from each docs page's frontmatter (category: + order:) against a fork-owned CATEGORY_ORDER, never a hand-edited page_order list; the top bar gains an Other Apps hover menu (the network's primary applications, from lib/network_directory.py) and a version badge; the sidebar's Resources section is third-party only (dmc + React Flow); a new /changelog page renders this file as a timeline; a new /api page documents every dash_flows component's props, generated from the installed package's metadata.json; /admin/traffic gains a dmc.DatePickerInput day picker (replacing a bare dcc.Dropdown) and a People** section separating the v3 human numbers from the crawler ledger below it; pages/home.py renders through markdown2dash instead of dcc.Markdown. Admin pages (/admin/control-board, /admin/traffic) are hidden from the sidebar and search unless the viewer is the owner. See DIVERGENCES.md divergence 11 for the two lines this fork kept (the wordmark, the SPA page-view beacon).
- The network battery's default User-Agent names the browser lane
(sync item 17): scripts/network_smoke.py's UA now leads with a Chrome/AppleWebKit token before the internal token — at dash-improve-my-llms ≥ 2.8 a UA with no browser engine token is crawler-lane, so the old bare-internal-token default made every default-UA check (the manifest link, the social card) read the prerendered crawler document instead of the browser one.
- The 1.6.41/1.6.42 navigation-contract remainder (sync item 18):
frontmatter gains a nav: short-sidebar-label field (separate from name:, which stays the <title>/og:title/llms.txt heading) and sidebar links show a lock icon on auth/admin-tier pages; /api's sitemap lastmod now reads the committed dash_flows/api_metadata.json extract's generated stamp (built by python scripts/build_api_metadata.py — re-run it when a component's props change) instead of always being absent; /changelog parses every heading shape the fleet writes (hyphen, en dash, em dash, bare or bracketed version, prose-first releases with no ### sections) and gains a sitemap lastmod of its own; the AppShell gains a keyboard skip-link to #main-content; lib/constants.py gains LOGO_ICON/WORDMARK_COLOR/WORDMARK_VISIBLE_FROM, lifting the header's identity out of components/header.py.
Fixed
- **
docs/api_reference/api_reference.md's.. kwargs::prop tables
reached the browser only** (sync item 18 contract highlight 7-amended, muicharts' finding): a markdown2dash directive renders Dash components, so its table exists only in the React tree — the machine lane (/api-reference/llms.txt, the crawler document) and the non-JS prerender are built from the markdown source, where the directive line is stripped. Measured before the fix: zero markdown table rows anywhere outside a JavaScript browser, across all five .. kwargs:: directives on that page. pages/markdown.py now expands .. kwargs:: fence-aware into a real markdown table, the same treatment it already gave .. source::, through a new lib.directives.kwargs.props_markdown() — one parse (props_for()) for both the directive's own table and the expansion, so the two lanes cannot drift apart again.
- This file had a phantom release. The
## Migration Guide
section at the foot of this CHANGELOG parsed as a release (the 1.6.41 heading match accepts unbracketed ## label — date, and free text came through with it), rendering an extra Timeline card with no version number. pages/changelog.py now requires an UNBRACKETED ## heading to look like a release — a version, an ISO date, or Unreleased — before treating it as one; bracketed headings (## [x.y.z]) stay trusted as intent.
tests/test_nav_contract.py's "every test client names a UA" pin
is now resolved per CALL SITE instead of per file — the file-scoped substring check could pass a file whose headers= sat on an unrelated code path while its actual .test_client() calls stayed bare. tests/test_excluded_links_hidden.py's admin-leak sweep now covers /llms-small.txt and /llms-full.txt, not only /llms.txt.
- **The read ledger counted the network's own health sweeps and
batteries as crawler traffic** (sync 1.6.43 item 1): record_read — the on_document_read hook the 2.8.0 floor added — never learned the internal-traffic contract track_visit has held since it existed. A request carrying lib.constants.INTERNAL_UA_TOKEN now drops before any field is read, keyed on the event's ua field (not user_agent, which EVENT_FIELDS does not have).
/healthzread as missing two keys to every automated reader
(sync item 10): this host served dash where the fleet key set names dash_version, and no backend at all. Every value on the wire was correct, but the hub's hourly sweep, the F4 battery, cd.yml's build-match wait and scripts/network_smoke.py all read the payload BY KEY NAME, so a renamed key is indistinguishable from a missing one. dash_version and backend are now served BESIDE dash (additive — an extra costs nothing, a substitute costs a red cell). DIVERGENCES.md §3 corrected in the same change: it had recorded this key set as a deliberate divergence, which is what kept several rounds of syncs from fixing it — the file layout is the real divergence, the key set never was.
[1.3.0] - 2026-08-01
Changed — flows.2plot.dev joins the 2plot network standard
The docs site now matches the pattern proven on 2plot.ai, 2plot.dev, boilerplate.2plot.dev, leaflet.2plot.dev and email.2plot.dev. What that means in practice:
- One identity, every surface.
lib/constants.pydefines
SITE_BRAND = "dash-flows — React Flow node graphs for Dash" (package name leads — the library rule; "Pip Install Python" is the byline, never the name), and it now reaches the <title>, the /llms.txt H1, the llms viewer's brand chip, the home prose, the README and every share-card headline. tests/test_site_identity.py pins all of them, because every one of these falls back to a framework default silently.
dash-improve-my-llms>=2.3.4is now required (run.py refuses to boot
below the floor) and replaces lib/seo.py entirely: /robots.txt, /sitemap.xml, /llms.txt, /<page>/llms.txt, the crawler prerender, canonical/og:url and the cross-host ## Network directory (lib/network_directory.py) all come from the package. The one thing lib/seo.py did that the package does not — re-pointing canonical/og:url on client-side navigation — moved into templates/index.html as the network-standard History-API script.
- The analytics stack is the network's.
lib/satellite_analytics.pysplit
into the standard lib/analytics_tracker.py (which drops internal-network and /healthz traffic at WRITE time — the internal-traffic contract's inbound half), lib/traffic_rollup.py, lib/satellite_reporter.py (flock lease so one worker reports per interval) and lib/bulletin.py. This app's own SPA page-view beacon — the reason its session numbers are honest when every other Dash site reports single-page visits — survives the split as lib/pageview_beacon.py. The outbound half of the contract is new here: ad_client and the traffic reporter now send the 2plot-internal UA, so this site's readers stop being counted as bot traffic on the hub.
- The app id is
flowseverywhere — the network-directory key, never the
package name — across AD_APP_ID, SATELLITE_APP_KEY and the bulletin.
- Every page ships a real social card. No
register_page()call passed
image_url= before, so Dash emitted og:image="" on every page — an empty tag that unfurls worse than none, because scrapers treat it as the declared image and render a blank card. All pages now point at cdn.2plot.ai/github_assets/flows.2plot.dev.png (1200x630, rendered by scripts/make_social_card.py), the template declares only the auxiliary tags Dash omits, and scripts/smoke_live.py reads the CDN object's IHDR bytes after every deploy.
- gunicorn floored at 23 (CVE-2024-6827, CVE-2024-1135 — request
smuggling). markdown2dash 0.1.2 pins gunicorn<22, so it now installs with --no-deps everywhere (Dockerfile, CI, requirements-docs.txt lists its real dependencies) and CI asserts the gunicorn version inside the built image.
Added — CI/CD, from nothing
This repo had no .github/workflows at all. It now has the boilerplate's proven shape: ci.yml (actionlint first — an invalid workflow file is the one defect CI structurally cannot report; flake8; the secretless pytest suite — zero secrets in CI on purpose, so fail-closed postures are provable; the real Docker image built, version-fingerprinted inside, booted and probed by scripts/network_smoke.py — the same battery CD runs against production; an examples matrix across Dash 4.2.0/4.4.1 and Python 3.10–3.13; a wheel build proving the dash>=4.1.0 floor in a clean venv with nothing but Dash) and cd.yml (owns main, requires CI, then 120s settle + five consecutive healthy probes — Render swaps instances, so a single 200 can come from the dying instance — then the battery plus scripts/smoke_live.py against https://flows.2plot.dev, where peer checks warn and own-host checks fail).
Changed — the wheel states its real floor
setup.py now declares install_requires=['dash>=4.1.0'] (the first release with the multi-backend constructor this component targets). CI installs the wheel with exactly dash==4.1.0 and nothing else, and asserts top_level.txt == ["dash_flows"] so no docs-site directory can ever leak into the package.
Changed
- Dash 4.2+ support: minimum
dash>=4.0.0(dev pindash[dev]>=4.2.0). Dash 4 keeps
React 18, so no component-side React migration was required. Multi-backend (Flask/FastAPI/Quart) and websocket callbacks are available to consuming apps.
- dash-mantine-components pinned to
>=2.8.0for examples and the docs app. - @xyflow/react bumped to
^12.11.1(latest 12.x).zustandremains pinned to4.x
(React Flow requires ^4.4.0).
Added
- Markdown-driven documentation app at the repo root (
run.py,pages/,docs/,
components/, lib/) seeded from the Dash Documentation Boilerplate. Each component is documented in docs/<topic>/<topic>.md with live .. exec:: demos, .. source:: code, and .. kwargs:: prop tables generated from the existing examples/.
- Every example runnable inline in the docs: 34 of the 35
examples/apps now have
an embeddable twin (docs/<topic>/exNN.py, ids namespaced exNN-) rendered live via .. exec::, plus the full source and a "How it works" breakdown on its category page. 23_callback_stress_test is intentionally source-only (performance harness).
- Validation harnesses committed under
scripts/:smoke_examples.py(import gate),
smoke_runtime.py (WSGI runtime gate: /, /_dash-layout, /_dash-dependencies), and validate_docs.py (docs render gate). Results matrix in SMOKE_RESULTS.md (35/35 import + runtime). Browser-fidelity test in tests/test_examples_render.py.
Removed
- R and Julia language bindings dropped — the project targets Python/Dash only.
Removed R/, man/, src/jl/, src/DashFlows.jl, NAMESPACE, DESCRIPTION, Project.toml, .Rbuildignore, and the duplicate JS bundle copies under deps/ and inst/. build:backends no longer generates R/Julia (--r-prefix/--jl-prefix removed).
- Repo clutter removed from version control:
SKILLS.md,dash_flows_SKILLS.md,
review_checklist.md, REACT_FLOW_COMPARISON.md, and the tracked .idea/ IDE config.
- Pre-migration remnants removed:
usage.py(superseded by the docs app — use
python run.py), the old JS dev demo (src/demo/, root index.html, webpack.serve.config.js, the npm start script, webpack-dev-server), the stale boilerplate tests tests/test_usage.py/tests/test_handle.py (replaced by tests/test_examples_render.py), unreferenced assets/logo.svg/assets/group-node.png, the unused webpack require in webpack.config.js, and the deprecated babel-eslint parser (now @babel/eslint-parser; run npm install once to refresh the lockfile).
Fixed
- Populated the previously empty
LICENSEfile with the MIT license text. - "Maximum update depth exceeded" render loop: the outbound
nodes/edges
setProps effects in DashFlows.react.js now guard on a serialized diff (mirroring the nodeConnections effect), so React Flow's asynchronous node re-measurement can no longer drive a setProps↔setNodes loop.
- React Flow error 008 ("null source/target handle") on resizable nodes:
ResizableNode now renders a default target (top) + source (bottom) handle pair when data.handles is omitted or empty (matching DefaultNode), so edges bind to it instead of failing. The data.handles prop is now optional.
- MiniMap ignored the light/dark preference: removed the inline
colorMode-based background override so the MiniMap follows the --df-minimap-* CSS variables, which track both React Flow's .dark class and Mantine's data-mantine-color-scheme (correct even for colorMode="system").
- Dark-mode fidelity across the docs example twins: replaced hardcoded light
colors on cards/panels/buttons with Mantine CSS variables; converted native html.Buttons to dmc.Button (ex15/ex18/ex19); synced the ex20/ex21 canvases' colorMode to the page theme via color-scheme-storage; and themed the ex14 metric-card node text so it stays legible on dark canvases.
Roadmap (carried over from REACT_FLOW_COMPARISON.md)
- Refactor
DashFlows.react.js(~2500 lines) into focused hooks
(useSmartHandles, useFlowState, useConnectionValidation, useViewportActions, useImageExport, useCopyPaste, useElkLayout).
- Lazy-load
elkjs(~1.45 MB, ~77% of the bundle) via dynamic import on first
layoutOptions use.
- Remove the
ramdadependency in favor of native JS. - Memoize smart-handle edge computation; document
onlyRenderVisibleElementsfor large flows.
[1.2.0] - 2026-04-03
Added
React Flow 12.10.1 Pass-Through Props
- connectionDragThreshold (number): Minimum drag distance in pixels before a connection line appears, preventing accidental connections
- zIndexMode (
"default"/"elevate"): Selected elements automatically elevate above others when set to"elevate" - autoPanOnNodeFocus (boolean): Viewport auto-pans when focusing nodes via Tab key for improved keyboard navigation
Floating Edges
- FloatingEdge component: New
floatingedge type that connects to the nearest point on each node's border instead of fixed handle positions - Uses
useInternalNodehook for real-time border intersection calculation - Natural-looking connections for arbitrary node layouts
Helper Lines (Alignment Guides)
- helperLines (boolean): Visual alignment guides appear when dragging nodes near other nodes
- helperLineThreshold (number, default 5): Snap distance in pixels for alignment detection
- Automatic snapping to horizontal and vertical alignment
Add Node on Edge Drop
- addNodeOnEdgeDrop (boolean): Drag a connection from a handle and drop on empty canvas to create a new node
- edgeDroppedNode (output): Callback data with
nodeId,position,source, andhandleTypeof the dropped connection
Node Connections Tracking
- nodeConnections (output): Real-time map of
nodeIdto{incoming: [...], outgoing: [...]}with edge/node details - Automatically updated when edges change
Undo/Redo System
- enableUndoRedo (boolean): Enable history tracking for node/edge changes
- undoRedoMaxHistory (number, default 50): Maximum number of history snapshots
- undoRedoAction (
{action: 'undo' | 'redo'}): Trigger undo or redo from callbacks - undoRedoState (output):
{canUndo, canRedo, undoCount, redoCount}for UI state - Tracks node position changes, additions, deletions, and edge connections
- Uses React Flow's
experimental_useOnNodesChangeMiddlewareandexperimental_useOnEdgesChangeMiddleware
Computing Flows (Graph Traversal)
- computeAction (
{action: 'compute' | 'computeNode', nodeId?, inputData?}): Trigger topological sort computation - computeResult (output):
{traversalOrder, nodeInputs, timestamp}with Kahn's algorithm results - JavaScript-side topological sort; Python handles all business logic and value propagation
Sub-flows (Collapsible Group Nodes)
- toggleCollapseNode (string): Set to a group node ID to toggle its collapse/expand state
- collapsedGroups (output): Array of currently collapsed group node IDs
- Double-click a group node to toggle collapse
- Child nodes and internal edges hidden when collapsed; group shrinks to compact view
- External edges remain connected at the group level
- GroupNode supports
data.collapsedWidthanddata.collapsedHeightfor compact dimensions
ViewportPortal (Floating Annotations)
- viewportOverlays (array): Floating overlays anchored to flow coordinates that move with pan/zoom
- Each overlay:
{x, y, content, style}— positioned in flow space, not screen space - Add, remove, and edit annotations dynamically via callbacks
Animated Layout Transitions
- animateLayout (boolean): Smooth animated transitions when applying ELK layouts
- animateLayoutDuration (number, default 300): Animation duration in milliseconds
- Ease-out cubic interpolation from current to target positions
Accessibility (ARIA Support)
- ariaLabelConfig (object): Custom ARIA labels for
nodes,edges,controls,minimapregions - Per-node/edge
ariaLabelin data for screen reader support - nodesFocusable / edgesFocusable (boolean): Enable Tab key navigation through nodes and edges
- disableKeyboardA11y (boolean): Disable keyboard shortcuts when needed
Resize Constraints
- ResizableNode and GroupNode now support constraint props in
data: keepAspectRatio(boolean): Lock aspect ratio during resizeminWidth/minHeight(number): Minimum dimensions in pixelsmaxWidth/maxHeight(number): Maximum dimensions in pixels
Glass Connection Line
- Custom glass morphism styled connection line preview while dragging new edges
- Blue dashed line with glow and drop shadow effect
Type-Colored MiniMap
- Custom MiniMap node rendering with colors based on node type (green=input, blue=default, purple=output, amber=toolbar)
EdgeToolbar on ButtonEdge
- ButtonEdge now supports
data.showToolbar(boolean) to display an EdgeToolbar on selection - Toolbar includes edit (inline label editing) and delete actions
- Custom styling via
data.toolbarStyle
Smart Handle Positioning
- smartHandles (boolean): Automatically routes edges to the closest side of each node
- Renders handles on all 4 sides and selects optimal connection points
- Alternative manual control via
data.sourcePosition/data.targetPositionper node
Delete Elements Action
- deleteElementsAction (
{nodeIds: [...], edgeIds: [...]}): Programmatic deletion routed throughreactFlowInstance.deleteElements()for undo/redo compatibility
New Examples
- Example 24:
24_smart_handles.py— Smart handle auto-routing demo - Example 25:
25_phase1_features.py— Phase 1 feature showcase (drag threshold, zIndex, auto-pan, EdgeToolbar) - Example 26:
26_floating_edges.py— Floating edge border intersection demo - Example 27:
27_helper_lines.py— Alignment guide and snap demo - Example 28:
28_add_node_on_drop.py— Add node on edge drop with connection tracking - Example 29:
29_accessibility.py— ARIA labels and keyboard navigation - Example 30:
30_resize_constraints.py— Aspect ratio and min/max resize limits - Example 31:
31_animated_layout.py— Smooth layout transitions with ELK - Example 32:
32_undo_redo.py— Full undo/redo system demo - Example 33:
33_computing_flows.py— Topological sort and data flow computation - Example 34:
34_viewport_portal.py— Floating viewport annotations - Example 35:
35_subflows.py— Collapsible group nodes with boundary edge remapping
New Python Wrapper Components (auto-generated)
AnimatedSvgEdge,ButtonEdge,ButtonHandle,DataEdge,DefaultNodeFloatingEdge,GroupNode,InputNode,NodeSearch,NodeStatusIndicatorNodeTooltip,OutputNode,SimpleBezierEdge,SmoothStepEdgeStepEdge,StraightEdge,ToolbarNode
Changed
- @xyflow/react upgraded from 12.3.5 to 12.10.1 (7 minor versions, 33 releases, no breaking changes)
- elkjs upgraded from 0.8.2 to 0.9.3
- zustand upgraded from 4.4.7 to 4.5.5 (stays on 4.x — React Flow requires ^4.4.0)
- React 18+ Compatibility: Converted
DashFlows.defaultPropsto JavaScript default parameters to eliminate deprecation warnings - GroupNode Refactoring: Simplified to React Fragment; styling applied directly to
.react-flow__node-group - Node Base Styling: Changed from fixed
widthtomax-widthfor better layout flexibility
Fixed
- React defaultProps Warning: Eliminated React 18+ deprecation warning across all components
- GroupNode Nested Container: Fixed nested wrapper div rendering issue
- CSS
!importantrules added to ensure layout class overrides apply correctly
[1.1.0] - 2025-12-15
Added
Custom Icons with DashIconify
- DashIconify Integration: InputNode, DefaultNode, and OutputNode now support custom icons via DashIconify
- Icon Props: New
iconprop accepts DashIconify components or any Dash component for custom node icons - Icon Color: New
iconColorprop allows customizing the icon container background color - Show/Hide Icon: New
showIconprop to toggle icon visibility (useful for text-only nodes)
Node Layout System
- Layout Prop: New
layoutprop with two options: "stacked"(default): Vertical arrangement with icon above text"horizontal": TwoCHANGELOG.md-column layout with icon on left, text on right- Content-Aware Sizing: Nodes automatically adjust size based on content configuration:
- Icon-only nodes: Compact sizing that fits the icon (no wasted space)
- Text-only nodes: Centered text without reserved icon space
- Full content nodes: Standard layout with icon and text
Enhanced Node Data Props
- Title Prop: New
titleprop as alias forlabel(for clarity when using body text) - Body Prop: New
bodyprop for description text below the title/sublabel - Sublabel Prop: Secondary text displayed below the main label
New Example
- Example 22:
22_custom_icons.py- Interactive demo showcasing: - Custom icons with DashIconify
- Layout toggle (stacked/horizontal)
- Show/hide icon toggle
- Dynamic icon, title, and body text updates via DMC forms
Changed
- Node Base Styling: Changed from fixed
widthtomax-widthfor better layout flexibility - CSS Layout Classes: Added
!importantflags to ensure layout overrides work correctly
Fixed
- Horizontal Layout: Fixed horizontal layout not being applied correctly due to CSS specificity issues
- Icon-Only Node Width: Fixed icon-only nodes being too wide by using
inline-flexdisplay
New Examples
- Example 23:
23_callback_stress_test.py- Stress test for Dash callbacks with DashFlows - 50 initial nodes in 5x10 grid
- Multiple simultaneous callbacks monitoring events
- Batch operations and live metrics
- Event logging for debugging
Changed
- Node Base Styling: Changed from fixed
widthtomax-widthfor better layout flexibility - CSS Layout Classes: Added
!importantflags to ensure layout overrides work correctly - React 18+ Compatibility: Converted
DashFlows.defaultPropsto JavaScript default parameters to eliminate React deprecation warnings - GroupNode Simplification: Refactored GroupNode to use React Fragment instead of wrapper divs, styling applied directly to
.react-flow__node-group
Fixed
- Multi-select Not Working: Added
multiSelectionKeyCode="Shift"support in example 07 - Right-click Context Menu: Fixed context menu callback in example 07 to display node data
- React defaultProps Warning: Fixed React 18+ deprecation warning by using default parameters instead of
Component.defaultProps - GroupNode Nested Container: Fixed GroupNode appearing with nested container by simplifying component to render only NodeResizer and label badge
- Viewport Control Buttons: Fixed Pan to Top Left/Center/Bottom Right buttons in example 09 by correcting the
viewportActionobject structure - Dark Mode Toggle (DMC): Fixed Mantine dark mode toggle in example 11 using modern
data-mantine-color-schemeattribute pattern
Technical
- Added CSS classes for content detection:
.df-icon-only,.df-text-only,.df-full-content - Added CSS classes for layouts:
.df-layout-stacked,.df-layout-horizontal - Added horizontal layout structure with
.df-node-icon-columnand.df-node-text-column - Added Iconify API fallback for rendering DashIconify icons when namespace unavailable
- Enhanced
renderDashComponentfunction to handle serialized Dash component format from callbacks - Added comprehensive JSDoc descriptions to all component propTypes for better IDE support
- GroupNode now styles
.react-flow__node-groupdirectly with!importantrules for proper React Flow integration
[1.0.0] - 2024-12-10
Added
New Node Types
- DefaultNode: Standard node with fully configurable handles
- InputNode: Source node with green accent styling and output handles
- OutputNode: Sink node with purple accent styling and input handles
- GroupNode: Container node for visually grouping related nodes
- ToolbarNode: Node with floating toolbar that appears on selection
- ResizableNode: Node that users can resize with drag handles
New Edge Types
- SimpleBezierEdge: Smooth curved Bezier connections
- SmoothStepEdge: Rounded right-angle step connections
- StepEdge: Sharp right-angle step connections
- StraightEdge: Direct straight-line connections
- AnimatedSvgEdge: Edge with animated flowing dot effect
- ButtonEdge: Edge with interactive delete button
- DataEdge: Edge that displays data labels inline
New UI Components
- NodeStatusIndicator: Visual status wrapper for nodes with loading, success, and error states
- NodeTooltip: Hover tooltip component for nodes
- NodeSearch: Search and filter nodes in the flow
- ButtonHandle: Interactive button-styled handle component
- DevTools: Development debugging panel
Theming System
- Glass Morphism Theme: Default theme with blur effects and transparency
- Solid Theme: Opaque cards with traditional shadows
- Minimal Theme: Clean, border-focused minimal design
- Color Schemes: 6 color schemes (default, ocean, forest, sunset, midnight, rose)
- Dark Mode Support: Automatic dark mode via React Flow, Mantine, or custom classes
- CSS Custom Properties: Full theming via CSS variables for customization
Status Indicators
- Loading state with blue pulsing glow animation
- Success state with green border and checkmark badge
- Error state with red border, X badge, and shake animation
- Initial state (no visual indicator)
Handle Configuration
- Configurable handle positions (top, right, bottom, left)
- Multiple handles per position
- Custom handle IDs for precise edge connections
- Handle styling customization
Examples
- 21 comprehensive example files covering all features
- Basic usage to advanced implementations
- Context menus, drag-and-drop, copy/paste demonstrations
- ELK layout integration examples
- Dash component embedding examples
Changed
- Upgraded to React Flow 12.3.5 (@xyflow/react)
- Complete rewrite of theming system with CSS custom properties
- Improved handle hover states with smooth transitions
- Enhanced node selection styling
- Better dark mode color contrast
Fixed
- Node status indicator loading animation now works properly with rounded corners
- Fixed CSS class name mismatch between JavaScript components and stylesheets
- Improved glass effect rendering across browsers
- Fixed handle positioning for custom node types
Technical
- Built on React 18.2
- Uses Zustand for state management
- ELK.js integration for automatic layouts
- html-to-image for flow export functionality
- Full TypeScript prop-types definitions
[0.0.4] - 2024-11-XX
Added
- Configurable handles feature
- Callback to view nodes for debugging
- DevTools component
Changed
- Updated version number
[0.0.3] - 2024-XX-XX
Added
- Initial public release
- Basic DashFlows component
- React Flow integration
- AnimatedCircleNode
- AnimatedNodeEdge
Migration Guide
From 0.0.x to 1.0.0
- Update import statements: Component names remain the same, but ensure you're importing from
dash_flows:
from dash_flows import DashFlows, DefaultNode, InputNode, OutputNode
- Node status indicators: The status indicator CSS classes have been updated. If you were using custom CSS targeting the old classes, update to:
.df-node-status-loading-borderfor loading state.df-node-status-successfor success state.df-node-status-errorfor error state
- Theming: The new theming system uses CSS custom properties. Apply theme classes to your container:
DashFlows(
id='flow',
className='df-theme-glass df-scheme-ocean',
...
)
- Handle configuration: Handles are now configured via the node's
data.handlesarray instead of separate props.
Note for AI agents: This is the static, prerendered view of an interactive Dash application served because we detected a non-JS user agent. Full prose docs:
- /changelog/llms.txt — LLM-friendly documentation
- /sitemap.xml
- /robots.txt