cloudflare / cloudflare/kumo

Flow: per-connector styling, wrapping layout, and standalone Flow.Node

Open
#613 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
3.9k
Forks
177
Avg merge
1d 5h
Merged PRs (30d)
48

Description

## Summary

`Flow` is a great fit for linear/parallel workflow diagrams, but its node and connector rendering are tightly coupled, which blocks a class of "labelled ladder" diagrams: sequences where each connector carries semantic meaning (colour/direction) and where the diagram should wrap rather than pan. Today the only escape hatch is to abandon `Flow` entirely and hand-roll connectors.

This issue proposes three related enhancements so `Flow` can cover these cases natively.

## Motivating use case

We have a "tier ladder" in an internal admin tool: the rate plans in a product family shown left-to-right as an upgrade/downgrade path. The connectors are the information, not just decoration:

- Green connector: the path from the lowest tier up to the account's currently-active tier ("already traversed").
- Red, reversed connector: a downgrade candidate.
- Neutral connector: everything else.

The ladder also lives in a dense, narrow column, so it wraps into rows of three with a "continues below" down-connector, rather than panning horizontally.

We evaluated migrating this to `Flow` and could not, for the reasons below.

## Current limitations (v2.6.0)

1. **Connectors are owned entirely by `` and expose no per-connector styling.** Connector geometry is computed in `FlowDiagram` from registered node rects; the only per-node knob that reaches a connector is `disabled` (greys it). There is no supported way to say "the connector arriving at / leaving this node is red" or "this connector points the other way". (See `packages/kumo/src/components/flow/`.)

2. **`Flow.Node` cannot be used outside ``.** `Flow.Node` calls `useDescendantsContext`, which throws `useDescendantsContext must be used within DescendantsProvider` when there is no `` ancestor. So consumers cannot reuse just the node presentation while composing their own connectors.

3. **Layout is single-line + pan only; no wrapping mode.** When a horizontal diagram overflows its container it pans. There is no row-wrapping layout for dense/narrow containers.

The net effect: `Flow` is all-or-nothing. If you need any per-connector semantics or a wrapping layout, you must drop `Flow` and reimplement connectors by hand, losing the component's measurement/anchor machinery.

## Proposed enhancements

Any one of these would help; ideally 1 + 3.

1. **Per-connector styling API.** For example, a `connector` prop on `Flow.Node` (styling the incoming edge) or a `renderConnector`/`connectorVariant` prop on `Flow` / `Flow.Parallel`:

```tsx

Tier 1
Tier 2 (active)
Tier 3 (downgrade)

```

A small set of semantic variants (`default | success | danger | muted`) that map to Kumo tokens would cover most cases; a render prop would cover the rest.

2. **Wrapping layout mode.** An opt-in `layout="wrap"` (or `wrap` / `columns`) on `Flow` that flows nodes into rows when they exceed the container width, with connectors drawn per-row and an inter-row indicator, as an alternative to `canvas` panning.

3. **Standalone `Flow.Node` presentation.** Let `Flow.Node` render its styled body when there is no `DescendantsProvider` (no-op the connector registration) instead of throwing, so the node's look-and-feel can be reused while a consumer composes connectors themselves. This decouples node presentation from the connector engine.

## Why native support is preferable

Hand-rolling connectors means reimplementing `getBoundingClientRect` tracking, `ResizeObserver`, scroll/resize remeasurement, and anchor bookkeeping that `Flow` already does well. Exposing a thin styling/layout seam would let these semantic-ladder diagrams stay on `Flow` and benefit from that machinery.

Happy to help prototype the connector-styling seam if the direction sounds reasonable.

Contributor guide

Open the contributing guide

Research direction

Start in packages/kumo/src/components/flow/ and read FlowDiagram, Flow.Node, and useDescendantsContext to understand node registration and connector geometry. First choose and scope one of the three proposed enhancements; done means the selected behavior and API work without breaking existing Flow usage.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript
Domain
design, frontend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.