Repository: expo/expo
File: docs/ui/components/ConfigPluginHierarchy/index.tsx (TypeScript)

Code before:
});

const initialEdges: Edge[] = [
  createEdge('e1-2', '1', '2'),
  createEdge('e2-3', '2', '3'),
  createEdge('e3-4', '3', '4'),
];

export const ConfigPluginHierarchy: React.FC<ConfigPluginHierarchyProps> = ({
  highlightedNodeId,
  highlightedNodeIds,
}) => {
  const [nodes, setNodes] = useNodesState(createNodes(highlightedNodeId, highlightedNodeIds));
  const [edges] = useEdgesState(initialEdges);

  React.useEffect(() => {
    setNodes(createNodes(highlightedNodeId, highlightedNodeIds));
  }, [highlightedNodeId, highlightedNodeIds, setNodes]);

  const diagramAlt = nodesData
    .map(n => {
      const names = [n.title, n.extraTitle].filter(Boolean).join(', ');
      const sub = n.subtitle ? ` (${n.subtitle})` : '';
      return `${names}${sub} [${n.badge}]`;
    })
    .join(' → ');

  return (
    <div
      className="mb-4 h-[300px] w-full overflow-hidden rounded-lg border border-default bg-default"
      data-md="diagram"
      data-md-alt={diagramAlt}>
      <style dangerouslySetInnerHTML={{ __html: nodeHandleStyles }} />
      <ReactFlow
        nodes={nodes}
        edges={edges}
        fitView
        fitViewOptions={{ padding: 0.1 }}
        nodesDraggable={false}
        nodesConnectable={false}
        elementsSelectable={false}
        panOnDrag={false}
        zoomOnScroll={false}
        zoomOnDoubleClick={false}>
        <Background variant={BackgroundVariant.Dots} gap={16} size={0.3} />
      </ReactFlow>
    </div>
  );
};


Review comment (suggestion):
Just a suggestion, but we could join with a newline here as well, so instead of one long line like:
```
withMyPlugin ("myPlugin") [Config Plugin] → withAndroidPlugin, withIosPlugin [Plugin Function] → withAndroidManifest, withInfoPlist [Mod Plugin Function] → mods.android.manifest, mods.ios.infoplist [Mod]
```
we get this:
```
withMyPlugin ("myPlugin") [Config Plugin]
→ withAndroidPlugin, withIosPlugin [Plugin Function]
→ withAndroidManifest, withInfoPlist [Mod Plugin Function]
→ mods.android.manifest, mods.ios.infoplist [Mod]
```

Code after:
});

const initialEdges: Edge[] = [
  createEdge('e1-2', '1', '2'),
  createEdge('e2-3', '2', '3'),
  createEdge('e3-4', '3', '4'),
];

export const ConfigPluginHierarchy: React.FC<ConfigPluginHierarchyProps> = ({
  highlightedNodeId,
  highlightedNodeIds,
}) => {
  const [nodes, setNodes] = useNodesState(createNodes(highlightedNodeId, highlightedNodeIds));
  const [edges] = useEdgesState(initialEdges);

  React.useEffect(() => {
    setNodes(createNodes(highlightedNodeId, highlightedNodeIds));
  }, [highlightedNodeId, highlightedNodeIds, setNodes]);

  const diagramAlt = nodesData
    .map(n => {
      const names = [n.title, n.extraTitle].filter(Boolean).join(', ');
      const sub = n.subtitle ? ` (${n.subtitle})` : '';
      return `${names}${sub} [${n.badge}]`;
    })
    .join('\n→ ');

  return (
    <div
      className="mb-4 h-[300px] w-full overflow-hidden rounded-lg border border-default bg-default"
      data-md="diagram"
      data-md-alt={diagramAlt}>
      <style dangerouslySetInnerHTML={{ __html: nodeHandleStyles }} />
      <ReactFlow
        nodes={nodes}
        edges={edges}
        fitView
        fitViewOptions={{ padding: 0.1 }}
        nodesDraggable={false}
        nodesConnectable={false}
        elementsSelectable={false}
        panOnDrag={false}
        zoomOnScroll={false}
        zoomOnDoubleClick={false}>
        <Background variant={BackgroundVariant.Dots} gap={16} size={0.3} />
      </ReactFlow>
    </div>
  );
};