Install
Works with Drupal: ^11.3 || ^12.0Using Composer to manage Drupal site dependencies
Alternative installation files
Release notes
Release date: 24. March 2026
Requires: Drupal 11.3+ or 12.0+, PHP 8.3+, Modeler API 1.1+
License: GPL-2.0-or-later
We are pleased to announce the first public release of the Workflow Modeler — a modern, React Flow-based visual modeler for Drupal that integrates with the Modeler API to support platforms like ECA, AI Agents, and other workflow-driven systems.
This release represents 347 commits across 410 files totalling over 119,000 lines of code, delivering a fully-featured visual workflow editor with professional-grade UX, accessibility, testing, and extensibility.
Overview
The Workflow Modeler provides an interactive canvas for building, editing, testing, and debugging workflow models directly within Drupal. It is model-owner agnostic — any module that implements the Modeler API’s ModelOwnerInterface can use the Workflow Modeler as its visual editor. The primary integration today is with the ECA (Events – Conditions – Actions) framework.
Architecture
The module has a minimal PHP backend (4 source files) and a comprehensive React/TypeScript frontend:
- Backend: A
WorkflowModelerplugin class implementing the Modeler API’sModelerBase, a form-to-JSON converter for rendering Drupal forms in React, a YAML schema lookup service, and HTMX link integration hooks. - Frontend: A TypeScript application built on React 18, React Flow 11, and Zustand 4, bundled with esbuild. Over 150 source files, 41 custom hooks, and 14 domain-specific stores.
Canvas
- Infinite canvas with panning (mouse wheel) and zooming (Ctrl+wheel), following the Figma gesture scheme
- Grid snapping for clean node alignment
- Five node types: Start (event), Custom (action/element), Gateway (XOR/AND), Subprocess, and Placeholder (for condition-first authoring)
- Two edge types: Default connections and Condition edges with attached condition configuration
- Drag-and-drop nodes from the component library onto the canvas
- Edge connections: Click-and-drag from source to target node handles
- Draggable edge control points for custom curve shapes
- Edge ordering: Visual “Flow 1”, “Flow 2” badges with reorder dropdown when nodes have multiple outgoing edges
- Multi-selection: Shift+Click or Shift+Drag for selection rectangles, with a dedicated panel for bulk operations including bulk delete
- Smart auto-positioning to avoid overlaps when using quick-add
- Pan to new events: Canvas automatically pans to newly added event nodes
- Minimap for navigating large models
- Fit view to see the entire model at once
Auto-Layout
A flow-based depth-first layout algorithm (462 lines) automatically arranges models for readability:
- Traverses from start nodes through successors respecting edge conditions for vertical spacing
- Prevents crossing between adjacent event flows
- Handles back-edge cycles and single-child gateway condensing
- Respects locked elements, only repositioning unlocked nodes and edges
- Condensed layout with dynamically expanding spacing
Quick-Add Authoring
- Quick-add button: Appears on nodes and edges to add connected components with a single click
- Quick-add popup: Section-based component browser replacing the former category tabs, with inline search
- Quick-add event button: Dedicated light-blue “Add event” button in the toolbar
- Condition-first authoring: Selecting a condition from quick-add creates a placeholder node with the condition pre-attached, allowing users to choose the target action afterwards
- Context-aware filtering: Quick-add popups only show plugins valid for the current workflow context and satisfied dependency constraints
Property Panel
- Node properties: Plugin name, editable label (inline), description, documentation link, annotation, and dynamically loaded configuration form
- Edge properties: Source/target info, condition plugin selection and configuration, annotation
- Configuration forms: Drupal form arrays converted to JSON and rendered entirely in React, supporting textfield, textarea, number, checkbox, select, markup, and YAML editor with schema validation from Drupal config schema
- Inline label editing with ContentEditableField supporting token visualization as chips
- Token drag-and-drop: Drag tokens from the replay data panel into configuration fields with visual drop zone indicators
- Panel resize: Draggable vertical and horizontal resize handles between panels
- Panel collapse/expand: Each panel has a collapse toggle with state persistence
Replay and Testing
Replay Visualization
- Dedicated replay panel positioned between the canvas and the property panel
- Step list: Visual list of execution steps with icons and labels for each step type (started, execute, add successor, ignore successor, access denied)
- Visual highlighting: Nodes highlighted with execution state; edges color-coded green (successor added) or red (successor ignored)
- Floating indicators: Circular check/cross marks at edge midpoints during replay
- Playback controls: Play, pause, stop, step forward, step backward with speed control (0.5x, 1x, 2x)
- Step data display: Hierarchical token data viewer with collapsible sections and draggable tokens
- Entry selector: Dropdown to switch between multiple recorded execution entries
- Bidirectional sync: Selecting a replay step highlights the corresponding canvas element and vice versa
- Smart panning: Only pans the viewport when the selected element is outside the view
Live Testing
- In-modeler test runner: Trigger a test execution, poll for results every 1.5 seconds, and display replay data when complete
- Save-then-test: If unsaved changes exist, prompts to save first and then auto-triggers the test after save completes
- Abort support: Cancel button with
AbortControllerfor in-flight requests - Error/warning handling: Backend errors displayed as Drupal messages
Template Token Support
- Global tokens: Site-wide Drupal tokens displayed in the replay panel, draggable into configuration fields
- Template tokens: Model-specific tokens displayed when editing a template model
- Token chips:
[token:path]references rendered as visual chips in contenteditable fields - Drag-and-drop: Tokens draggable from the data panel into any configuration field, with drop zone indicators
Context and Dependencies
- Context filtering: Dropdown in the canvas toolbar to select an active context; only plugins listed in the context’s component definitions are shown in the component palette and quick-add popups
- Context configuration: Pre-populated configuration values for newly added components based on context
- Plugin dependencies: Runtime enforcement of predecessor constraints; plugins with dependency entries are only shown when at least one required predecessor exists in the current workflow
Export
Four export formats:
| Format | Method | Description |
|---|---|---|
| Recipe | Backend | Opens the Drupal recipe export form, generating a distributable recipe with composer.json, recipe.yml, and README.md |
| Archive | Backend | Downloads a compressed tar.gz of configuration files |
| JSON | Client-side | Portable format with nodes, edges, metadata, required modules, optional replay data, config form schemas, and component definitions; can be loaded in the standalone viewer |
| SVG | Client-side | Visual snapshot rendered as a standalone SVG with nodes, edges, labels, and annotations; resolves CSS variables and handles text wrapping |
Standalone Viewer
The Workflow Modeler ships with a standalone viewer that can be embedded in any web page without a Drupal backend:
- Built as a separate bundle (
modeler-viewer.bundle.js+modeler-viewer.bundle.css) - Initialize with:
WorkflowModelerViewer.init('#container', { modelUrl: 'model.json' }) - Read-only mode with optional replay playback
- Includes pre-loaded config form schemas so property panels work without a backend
- Supports
collapsePanelsoption for maximizing canvas space
View Modes
- Fullscreen:
position: fixed, covers the entire viewport (default in Drupal) - Restored: Draggable and resizable floating window; position and size persisted to
localStorage - Toggle via toolbar button; minimum dimensions: 480×360px
Dark Mode
- Toggle in the toolbar menu
- All colors use
--modeler-*CSS custom properties; no hardcoded colors - Preference persisted to
localStorageacross sessions - Full light and dark variable sets with proper contrast ratios
- Exposed via Plugin API:
api.isDarkMode(),api.setDarkMode(),api.onDarkModeChange()
Undo/Redo
- 50-entry snapshot stack with full node and edge copies
- History saved before: node moves, additions, deletions, configuration edits, paste operations, quick-add, auto-layout
- Toolbar buttons and keyboard shortcuts: Ctrl+Z (undo), Ctrl+Shift+Z / Ctrl+Y (redo)
- Integrated with the Plugin API — mutation methods automatically manage history
Copy and Paste
- Supports single and multi-selection copy/paste
- Pasted elements offset by (50px, 50px) from originals with new unique IDs
- Internal edges between copied nodes are preserved
- Cross-browser tab clipboard via encrypted
localStoragestorage - Screen reader announcements for copy/paste operations
- Integrated with undo/redo history
Keyboard Shortcuts
| Shortcut | Action |
|---|---|
| Delete | Delete selected nodes/edges |
| Ctrl+C / Cmd+C | Copy selected elements |
| Ctrl+V / Cmd+V | Paste elements |
| Ctrl+Z / Cmd+Z | Undo |
| Ctrl+Shift+Z / Cmd+Shift+Z | Redo |
| Ctrl+Y | Redo (alternative) |
| Ctrl+F / Cmd+F | Focus search |
| Escape | Clear search / close dialogs |
| Shift+Click | Add/remove from multi-selection |
| Shift+Drag | Multi-select box |
| Mouse wheel | Vertical canvas panning |
| Ctrl+Wheel | Zoom |
Shortcuts are context-aware and auto-disabled inside form fields.
Permissions
Six granular permissions control modeler features:
| Permission | Controls |
|---|---|
| edit metadata | Editing model label, version, tags, changelog, documentation |
| switch context | Changing the active context filter |
| edit template | Editing an existing template model |
| create template | Marking a model as a template |
| test | Triggering test executions |
| replay | Using the replay panel and loading replay data |
Localization
All user-facing strings are wrapped in a t() translation function that integrates with Drupal’s translation system (Drupal.t()) and falls back gracefully in non-Drupal contexts (tests, Storybook, standalone viewer). A custom ESLint rule (609 lines) enforces that no untranslated strings are used in JSX text or attribute values.
Accessibility
The Workflow Modeler targets WCAG AA compliance:
- Text contrast: 4.5:1 minimum for normal text, 3:1 for large text
- Non-text contrast: 3:1 for icons, borders, and UI elements
- Focus indicators: 2px blue outline with offset on all interactive elements
- Focus trapping: Modal dialogs trap Tab cycling with Escape-to-close; focus restored on close
- Touch targets: Minimum 44×44px on touch devices
- Screen reader support: ARIA labels on all buttons,
aria-liveregions for dynamic announcements, proper combobox roles, edge order badge roles - Status announcer: Dedicated hook for screen reader messages on save, delete, copy/paste, and other operations
- Motion preferences:
prefers-reduced-motionreduces all animations to near-zero duration - High contrast:
prefers-contrast: highapplies higher contrast CSS variables automatically - Scrollable regions: Proper
tabIndex,role="region", andaria-labelon scrollable containers
Plugin API
The modeler exposes a public JavaScript API at window.WorkflowModeler for third-party extensions:
Extension Points
registerPanel(descriptor)/unregisterPanel(id)— add custom panels (left, right, or bottom) with configurable width, collapse, and resizeregisterWidget(descriptor)/unregisterWidget(id)— add toolbar widgets (left or right)onReady(callback)— subscribe to the modeler ready event- DOM event:
workflow-modeler:readydispatched when the React app mounts
Public API (30+ methods)
- Getters:
getNodes(),getEdges(),getNodeById(),getEdgeById(),getSelectedNode(),getSelectedEdge(),getModelData(),isReadOnly(),isDarkMode(),getHistoryState(),getErrors(),getComponents(),getComponentLabels(),getContexts(),getSelectedContextId(),getFilteredNodeIds() - Subscriptions:
onSelectionChange,onNodesChange,onEdgesChange,onModelDataChange,onDarkModeChange,onContextChange,onComponentsChange,onReadOnlyChange - Mutations:
addNode(),updateNode(),removeNode(),addEdge(),updateEdge(),removeEdge(),setCondition(),removeCondition(),selectNode(),selectEdge(),clearSelection(),focusNode(),fitView(),autoLayout(),setDarkMode(),setFlowFilter()
All getters return deep-cloned snapshots. Mutations are no-ops in read-only mode and automatically integrate with undo/redo history. The API is designed for additive-only changes across minor versions.
Security
- XSS prevention: DOMPurify sanitization for all HTML content
- CSRF protection: Token-validated requests for all backend communication
- Encrypted clipboard: Cross-tab clipboard data stored with encryption in
localStorage - Response validation: External API data validated before use
- Error boundaries: React error boundaries prevent component crashes from cascading
Testing
The module ships with comprehensive test coverage:
| Test Type | Framework | Scope |
|---|---|---|
| Unit tests | Jest + React Testing Library | 109 test files covering components, hooks, stores, utils, and plugins; includes jest-axe for component-level a11y |
| E2E tests | Playwright | 14 spec files covering core functionality, replay, quick-add, condition authoring, export, label editing, property panel, permissions, read-only mode, undo/redo, layout, and accessibility |
| Component docs & a11y | Storybook 8.6 + axe-playwright | 35 story files with a11y audits run in both light and dark mode |
| PHP | PHPUnit, PHPCS, PHPStan | Backend code quality and standards |
All tests are enforced as hard gates in the CI/CD pipeline.
Documentation
The module ships with a comprehensive MkDocs-based documentation site covering:
- Getting Started: Installation and first steps
- Interface: Canvas, Property Panel, Toolbar, Replay Panel
- Working with Models: Creating, editing, saving and closing
- Components: Nodes, edges and conditions, configuration forms
- Features: Keyboard shortcuts, search, dark mode, flow filtering, export, standalone viewer, view modes, permissions
- Replay & Testing: Viewing replay data, live testing, tokens and data
- Accessibility: Full WCAG AA compliance documentation
- UI Development: Architecture, Plugin API, component development, state management, testing, build and quality, security
Architecture diagrams (SVG), automatically generated screenshots (via Playwright), and multiple logo sizes are included.
Tech Stack Summary
| Layer | Technology |
|---|---|
| UI framework | React 18.2 |
| Graph visualization | React Flow 11.10 |
| State management | Zustand 4.4 (14 stores) |
| Language | TypeScript 5.9 (strict mode) |
| Bundler | esbuild 0.27 |
| Unit testing | Jest + React Testing Library |
| E2E testing | Playwright |
| Component documentation | Storybook 8.6 |
| a11y testing | jest-axe + axe-playwright |
| XSS prevention | DOMPurify 3.3 |
| Drupal integration | Modeler API 1.1 |