Portal Community

Reading isReadonly

// The most common subscription — disabling edit interactions
function NodeConfigForm({ nodeId }: { nodeId: string }) {
    const isReadonly = useDesignerModeStore(state => state.isReadonly);

    return (
        <form>
            <input
                name="label"
                disabled={isReadonly}
                // ...
            />
            {!isReadonly &&
                <button type="submit">Save</button>}
        </form>
    );
}

Conditional Rendering Per Mode

// Show different toolbar content depending on mode
function CanvasToolbar() {
    const currentMode = useDesignerModeStore(state => state.currentMode);

    return (
        <div className="toolbar">
            {currentMode === 'design' && <DesignToolbarActions />}
            {currentMode === 'execution' && <ExecutionProgressBar />}
            {currentMode === 'readonly' && <ReadonlyBadge />}
        </div>
    );
}

Reading Execution Mode State

import { shallow } from 'zustand/shallow';

// Subscribe to multiple fields efficiently
function ExecutionSummaryPanel() {
    const { executionId, runProgress, currentMode } = useDesignerModeStore(
        state => ({
            executionId: state.executionId,
            runProgress: state.runProgress,
            currentMode: state.currentMode
        }),
        shallow
    );

    if (currentMode !== 'execution') return null;

    return (
        <div>
            <p>Execution: {executionId}</p>
            <p>{runProgress.completedNodes} / {runProgress.totalNodes} completed</p>
        </div>
    );
}

Calling Transition Actions

// Stable action references — no shallow needed
function RunButton({ processId }: { processId: string }) {
    const enterExecutionMode = useDesignerModeStore(state => state.enterExecutionMode);

    async function handleRun() {
        const { executionId } = await processApiClient.startExecution(processId);
        enterExecutionMode(executionId);
    }

    return <button onClick={handleRun}>Run</button>;
}
Prefer isReadonly over checking currentMode for disabling edits. If a new mode is added in the future that also disables editing, components checking isReadonly will automatically handle it without code changes.