Skip to content
Extensões

Workflow Diagram

Editor de fluxo interativo com nos, arestas conectaveis, zoom/pan, painel de propriedades e toolbar. Baseado em React (@xyflow/react) e executado como ilha isolada dentro do monolito PHP.

components/workflow-diagram.cssislands/src/islands/WorkflowDiagram/Abrir no Figma

Uso

Quando e como utilizar o editor de fluxo para modelar processos com nos e arestas conectaveis.

  • JSON data — Carrega nos e arestas de um endpoint JSON via atributo data-props no container. O componente faz fetch automatico ao montar.
  • Inline data — Dados passados diretamente no atributo data-props como JSON serializado, sem fetch externo.
  • Programmatic — Monta a ilha manualmente via ArenitoIslands.mount() passando o elemento container e as props como objeto JavaScript.
Este e um React Island que requer o script arenito-islands.js carregado na pagina. O bundle inclui @xyflow/react e suas dependencias. Sem o script, o container permanece vazio.

Exemplos

Veja abaixo os exemplos interativos do editor de fluxo, incluindo toolbar, painel de propriedades e diferentes tipos de nos.

Carregando exemplo...

Anatomia

Estrutura interna do componente e seus elementos.

ParteElementoDescricao
Container.workflow-diagramWrapper principal com position relative e width 100%
Toolbar.workflow-diagram__toolbarBarra de ferramentas superior com flex row e gap 8px
Toolbar Btn.workflow-diagram__toolbar-btnBotao da toolbar, Inter 13px w500
Btn Primary.workflow-diagram__toolbar-btn--primaryModificador com background brand e texto branco
Separator.workflow-diagram__toolbar-separatorDivisor vertical 1px entre grupos de botoes
Body.workflow-diagram__bodyFlex container para canvas e painel lateral
Canvas.workflow-diagram__canvasArea do ReactFlow com nodes, edges e controles
Panel.workflow-diagram__panelPainel lateral de propriedades, width 280px
Panel Title.workflow-diagram__panel-titleTitulo do painel, Space Grotesk 14px w600
Panel Field.workflow-diagram__panel-fieldGrupo de campo com label + input
Panel Label.workflow-diagram__panel-labelLabel do campo, Inter 12px, texto secundario
Panel Input.workflow-diagram__panel-inputInput com borda e focus ring
Node.workflow-diagram__nodeNo base 60x60, circular, border 2px solid
Node Start.workflow-diagram__node--startNo inicial com fill verde #10B981
Node Process.workflow-diagram__node--processNo de processo com fill azul accent-300
Node Decision.workflow-diagram__node--decisionNo de decisao losango, rotacao 45deg, #F59E0B
Node End.workflow-diagram__node--endNo final com fill vermelho #EF4444
Node Label.workflow-diagram__node-labelTexto do no, Inter 11px, text-align center
Edge Label.workflow-diagram__edge-labelLabel da aresta com background e borda arredondada
Minimap.workflow-diagram__minimapMinimap no canto inferior direito com opacity 0.7
Vazio.workflow-diagram__emptyEstado sem dados, borda dashed e padding 48px

Tipos de Nos

O editor suporta 4 tipos de nos com estilos visuais e posicoes de Handle distintas.

Cada tipo de no possui um estilo visual especifico que indica sua funcao no fluxo. Os Handles (pontos de conexao) sao posicionados de acordo com a semantica do no.

TipoClasse modificadoraEstilo visualHandles
Start.workflow-diagram__node--startCirculo verde (#10B981), border 2px1 source (bottom)
Process.workflow-diagram__node--processCirculo azul (accent-300), border 2px1 target (top), 1 source (bottom)
Decision.workflow-diagram__node--decisionLosango amarelo (#F59E0B), rotacao 45deg1 target (top), 2 sources (right, bottom)
End.workflow-diagram__node--endCirculo vermelho (#EF4444), border 2px1 target (top)

O no de decisao usa transform: rotate(45deg) no container e rotate(-45deg) no label para manter o texto legivel. As arestas que saem do no de decisao podem receber labels como "Sim" e "Nao" via .workflow-diagram__edge-label.

Eventos

CustomEvents disparados pelo componente para integracao com o monolito PHP.

O Workflow Diagram emite CustomEvents no elemento container para que o codigo do monolito possa reagir a acoes do usuario sem acoplar-se ao React.

EventodetailQuando dispara
arenito:workflow:save{ nodes: Node[], edges: Edge[] }Usuario clica no botao Salvar da toolbar
arenito:workflow:node-click{ nodeId: string, nodeType: string, data: object }Usuario clica em um no do diagrama
js
document.querySelector('[data-island="WorkflowDiagram"]')
  .addEventListener('arenito:workflow:save', (e) => {
    console.log('Nodes:', e.detail.nodes);
    console.log('Edges:', e.detail.edges);
  });

Propriedades

Classes CSS disponiveis para configurar o editor de fluxo.

PropriedadeTipoDefaultDescrição
.workflow-diagramclasseContainer principal do editor de fluxo.
.workflow-diagram__toolbarclasseBarra de ferramentas superior com botoes de acao.
.workflow-diagram__toolbar-btnclasseBotao individual da toolbar (13px w500).
.workflow-diagram__toolbar-btn--primaryclasseModificador para botao primario (background brand).
.workflow-diagram__toolbar-separatorclasseSeparador vertical entre grupos de botoes.
.workflow-diagram__bodyclasseWrapper flex do canvas e painel lateral.
.workflow-diagram__canvasclasseArea do ReactFlow com nodes e edges.
.workflow-diagram__panelclassePainel lateral de propriedades do no selecionado (280px).
.workflow-diagram__panel-titleclasseTitulo do painel de propriedades (14px w600).
.workflow-diagram__panel-fieldclasseGrupo de campo no painel (label + input).
.workflow-diagram__panel-labelclasseLabel do campo (12px, texto secundario).
.workflow-diagram__panel-inputclasseInput do campo com borda e focus state.
.workflow-diagram__nodeclasseNo customizado base (60x60, circular, border 2px).
.workflow-diagram__node--startclasseNo inicial verde (#10B981).
.workflow-diagram__node--processclasseNo de processo azul (accent-300).
.workflow-diagram__node--decisionclasseNo de decisao losango (rotacao 45deg, #F59E0B).
.workflow-diagram__node--endclasseNo final vermelho (#EF4444).
.workflow-diagram__node-labelclasseLabel de texto do no (11px, text-align center).
.workflow-diagram__edge-labelclasseLabel da aresta com background e borda.
.workflow-diagram__minimapclasseMinimap posicionado no canto inferior direito.
.workflow-diagram__emptyclasseEstado vazio com borda tracejada.

Codigo

Snippets prontos para copiar e usar no seu projeto.

HTML com data-island e data-props

html
<div data-island="WorkflowDiagram"
     data-props='{
       "nodes": [
         { "id": "1", "type": "start", "position": { "x": 250, "y": 0 }, "data": { "label": "Inicio" } },
         { "id": "2", "type": "process", "position": { "x": 250, "y": 120 }, "data": { "label": "Analise" } },
         { "id": "3", "type": "decision", "position": { "x": 250, "y": 240 }, "data": { "label": "Aprovado?" } },
         { "id": "4", "type": "end", "position": { "x": 250, "y": 360 }, "data": { "label": "Fim" } }
       ],
       "edges": [
         { "id": "e1-2", "source": "1", "target": "2" },
         { "id": "e2-3", "source": "2", "target": "3" },
         { "id": "e3-4", "source": "3", "target": "4", "label": "Sim" }
       ]
     }'>
</div>

Montagem programatica via ArenitoIslands.mount()

js
const container = document.getElementById('workflow-container');

ArenitoIslands.mount(container, 'WorkflowDiagram', {
  nodes: [
    { id: '1', type: 'start', position: { x: 250, y: 0 }, data: { label: 'Inicio' } },
    { id: '2', type: 'process', position: { x: 250, y: 120 }, data: { label: 'Revisao' } },
    { id: '3', type: 'decision', position: { x: 250, y: 240 }, data: { label: 'OK?' } },
    { id: '4', type: 'end', position: { x: 250, y: 360 }, data: { label: 'Concluido' } }
  ],
  edges: [
    { id: 'e1-2', source: '1', target: '2' },
    { id: 'e2-3', source: '2', target: '3' },
    { id: 'e3-4', source: '3', target: '4', label: 'Sim' }
  ]
});

Integracao com Factory (PHP)

php
<div id="workflow-fiscalizacao"
     data-island="WorkflowDiagram"
     data-endpoint="/api/workflow/fiscalizacao/<?= $processo_id ?>">
</div>

<script src="/assets/arenito-islands.js"></script>

Fonte de Dados

O componente aceita dados em JSON com arrays de nodes e edges seguindo o schema do ReactFlow.

JSON (formato recomendado)

O objeto JSON raiz contem dois arrays: nodes para os nos do diagrama e edges para as conexoes entre eles.

json
{
  "nodes": [
    {
      "id": "1",
      "type": "start",
      "position": { "x": 250, "y": 0 },
      "data": { "label": "Cadastro" }
    },
    {
      "id": "2",
      "type": "process",
      "position": { "x": 250, "y": 120 },
      "data": { "label": "Analise Documental" }
    },
    {
      "id": "3",
      "type": "decision",
      "position": { "x": 250, "y": 240 },
      "data": { "label": "Documentos OK?" }
    },
    {
      "id": "4",
      "type": "end",
      "position": { "x": 250, "y": 360 },
      "data": { "label": "Aprovado" }
    }
  ],
  "edges": [
    { "id": "e1-2", "source": "1", "target": "2" },
    { "id": "e2-3", "source": "2", "target": "3" },
    { "id": "e3-4", "source": "3", "target": "4", "label": "Sim" },
    { "id": "e3-2", "source": "3", "target": "2", "label": "Nao" }
  ]
}

Mapeamento de campos

CampoTipoObrigatorioDescricao
idstringSimIdentificador unico do no ou aresta
typestringSimTipo do no: start, process, decision ou end
positionobjectSimCoordenadas { x, y } do no no canvas
dataobjectSimDados do no, incluindo label para o texto exibido
sourcestringSim (edge)ID do no de origem da aresta
targetstringSim (edge)ID do no de destino da aresta
labelstringNao (edge)Texto exibido na aresta (ex: "Sim", "Nao")

Dark Mode

O editor de fluxo adapta automaticamente ao tema escuro via classe .dark.

No dark mode, o canvas recebe um fundo escuro e os nos ajustam suas cores de borda e fill para manter contraste adequado. O painel lateral e a toolbar seguem os tokens semanticos de superficie.

PropriedadeLightDark
Canvas background--surface-base-neutral-container-default--surface-base-neutral-container-default
Toolbar background--surface-base-neutral-container-emphasis--surface-base-neutral-container-emphasis
Node borderrgba(0,0,0,0.15)rgba(255,255,255,0.15)
Node label color--text-base-neutral-default--text-base-neutral-default
Edge stroke--border-base-neutral-default--border-base-neutral-default
Edge label background--surface-base-neutral-container-default--surface-base-neutral-container-default
Panel background--surface-base-neutral-container-emphasis--surface-base-neutral-container-emphasis
Panel input border--border-base-neutral-default--border-base-neutral-default
Minimap backgroundrgba(0,0,0,0.06)rgba(255,255,255,0.06)

Os tokens semanticos de superficie e texto herdam automaticamente os valores do dark mode. A toolbar e o painel lateral mantam a mesma estrutura em ambos os temas, ajustando apenas cores de fundo e borda.

Design System interno do GALES