From ff5a2c8a038f336ad325d9771cbad1bef13a1b9d Mon Sep 17 00:00:00 2001 From: HerbertJulio Date: Thu, 25 Jun 2026 15:13:40 -0300 Subject: [PATCH 1/2] feat(flow): add Flow component (ENG-46487) --- .specs/flow.md | 172 ++++++++++++++++ .../components/data/flow/Flow.stories.js | 191 ++++++++++++++++++ packages/webkit/package.json | 5 + .../src/components/data/flow/connectors.ts | 146 +++++++++++++ .../data/flow/flow-anchor/flow-anchor.vue | 45 +++++ .../data/flow/flow-anchor/package.json | 11 + .../data/flow/flow-list/flow-list.vue | 71 +++++++ .../data/flow/flow-list/package.json | 11 + .../data/flow/flow-node/flow-node.vue | 53 +++++ .../data/flow/flow-node/package.json | 11 + .../data/flow/flow-parallel/flow-parallel.vue | 82 ++++++++ .../data/flow/flow-parallel/package.json | 11 + .../webkit/src/components/data/flow/flow.vue | 84 ++++++++ .../src/components/data/flow/injection-key.ts | 12 ++ .../src/components/data/flow/package.json | 11 + 15 files changed, 916 insertions(+) create mode 100644 .specs/flow.md create mode 100644 apps/storybook/src/stories/components/data/flow/Flow.stories.js create mode 100644 packages/webkit/src/components/data/flow/connectors.ts create mode 100644 packages/webkit/src/components/data/flow/flow-anchor/flow-anchor.vue create mode 100644 packages/webkit/src/components/data/flow/flow-anchor/package.json create mode 100644 packages/webkit/src/components/data/flow/flow-list/flow-list.vue create mode 100644 packages/webkit/src/components/data/flow/flow-list/package.json create mode 100644 packages/webkit/src/components/data/flow/flow-node/flow-node.vue create mode 100644 packages/webkit/src/components/data/flow/flow-node/package.json create mode 100644 packages/webkit/src/components/data/flow/flow-parallel/flow-parallel.vue create mode 100644 packages/webkit/src/components/data/flow/flow-parallel/package.json create mode 100644 packages/webkit/src/components/data/flow/flow.vue create mode 100644 packages/webkit/src/components/data/flow/injection-key.ts create mode 100644 packages/webkit/src/components/data/flow/package.json diff --git a/.specs/flow.md b/.specs/flow.md new file mode 100644 index 000000000..beb09e741 --- /dev/null +++ b/.specs/flow.md @@ -0,0 +1,172 @@ +--- +name: flow +category: data +structure: composition +status: approved +spec_version: 1 +figma: + url: + node_id: +checksum: 1639b821be408187cef9eb07bd4b08f9cf22f7b3e802b85f44f28f50284ba0d5 +created: 2026-06-25 +last_updated: 2026-06-25 +--- + +# Flow — Component Spec + +## Purpose + +Flow renders a directed flow diagram: a vertical sequence of steps (`flow-node`) joined by decorative connectors, with optional parallel branches (`flow-parallel`) and custom attachment points (`flow-anchor`). Use it to visualize pipelines, workflows, and step-by-step processes inside a data view; unlike `data-table` it expresses ordered/branching relationships rather than tabular records. Design source (rewritten to our conventions, never inherited as-is): the kumo "Flow" component group at https://kumo-ui.com/components/flow/. Scope boundary: large diagrams pan via a native `overflow: auto` scroll container on the root — free 2D drag-pan is intentionally out of scope (it would require an external positioning library forbidden by `.claude/rules/dependencies.md`). There is no Figma frame for this component; tokens are inferred from intent and recorded in the Theme gaps table. + +## Usage + +```vue + + + +``` + +## Sub-components + +- `flow-node/flow-node.vue` — A single step in the flow. Connectors that touch a disabled node render at reduced opacity (mirrored by `data-disabled`). Content via the `default` slot. +- `flow-anchor/flow-anchor.vue` — Marks a custom connector attachment point inside a node. `type` restricts the anchor to the incoming (`start`) or outgoing (`end`) connector; omitted means both. Content via the `default` slot. +- `flow-parallel/flow-parallel.vue` — Container that lays out parallel branches side by side with junction connectors. `align` controls the horizontal alignment of the branches. +- `flow-list/flow-list.vue` — Container for a sequence of `flow-node` with automatic connectors drawn between consecutive nodes. Content via the `default` slot. + + + +## Props + +| Prop | Type | Default | Required | JSDoc | +|---|---|---|---|---| +| `align` | `'start' \\| 'center'` | `'start'` | no | Vertical alignment of nodes within the diagram. | + +## Events + +| _none_ | — | — | + +## Slots + +| Slot | Scope | Notes | +|---|---|---| +| `default` | — | Diagram content: `flow-list`, `flow-node`, `flow-parallel`. | + +## States + +- Visual states: `default`, `focus-visible`, `disabled` +- `data-disabled` mirrors the `disabled` prop on `flow-node` +- `data-align` mirrors the `align` prop on `flow` and `flow-parallel` +- `data-type` mirrors the `type` prop on `flow-anchor` + +## Motion & Animations + +_none_ + +## Tokens + +| Region | Token (DESIGN.md) | +|---|---| +| typography (node label) | `.text-body-md` | +| typography (compact label) | `.text-label-md` | +| node surface | `var(--bg-surface)` | +| node border | `var(--border-default)` | +| node text | `var(--text-default)` | +| connector stroke | `var(--border-default)` | +| disabled text | `var(--text-disabled)` | +| spacing | `var(--spacing-md)` | +| shape | `var(--shape-button)` | +| ring | `var(--ring-color)` | + +## Theme gaps + +| Figma variable | Temporary primitive | Follow-up | +|---|---|---| +| raised node surface (`bg-surface-raised`) | `var(--bg-surface)` | TODO: tokenizar `--bg-surface-raised` | + +## Accessibility (WCAG 2.1 AA) + +- Visible focus: `focus-visible:ring-2 focus-visible:ring-[var(--ring-color)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--bg-canvas)]` +- Keyboard map: `Tab` moves focus through focusable nodes in document order; no arrow-key roving (the diagram is a static list/group). +- ARIA: root `flow` is `role="list"`; each `flow-node` is `role="listitem"` with accessible text content; `flow-parallel` is `role="group"`; connectors and anchors are decorative and carry `aria-hidden="true"`. +- Contrast ≥4.5:1 (text) / ≥3:1 (large + icons), including the disabled state. +- `motion-reduce:transition-none motion-reduce:transform-none` not required — the component is static (no motion). +- Touch target ≥40×40 px where a node is interactive. + +## Stories (Storybook) + +Composite stories are justified below because Flow is a composition component whose value is in how parts compose, not in a single `kind`/`size` axis: + +- Default — a sequential `flow-list` of `flow-node` joined by connectors. +- Parallel — a `flow-parallel` rendering parallel branches with junction connectors (demonstrates the composition that a single `kind`/`size` axis cannot). +- Disabled — a `flow-node` with the `disabled` prop, showing the reduced-opacity connectors. + +## Constraints — DO NOT + + + +- Do not add props beyond the Props table above. If you need a prop that is not listed, emit `BLOCKED: missing prop ` and stop — do not invent. +- Do not add events beyond the Events table above. Same rule for slots and sub-components. +- Do not invent imports. Every `@aziontech/webkit/*` path must exist in `packages/webkit/package.json#exports`. Every relative import must resolve to a real file. Every npm package must be installed. +- Do not use HEX/RGB/HSL colors, Tailwind palette names (e.g. `bg-blue-500`), raw typography classes (e.g. `text-sm`), `any`, `@ts-ignore`, or `class` inside `defineProps`. +- Do not install or import positioning/animation libraries (`@floating-ui/*`, `popper.js`, `tippy.js`, `gsap`, `framer-motion`, `motion`, `@vueuse/motion`, `@formkit/auto-animate`, drag-drop runtimes, scroll virtualization libs). Use CSS + Vue primitives (``, ``). See `.claude/rules/dependencies.md`. +- Do not improvise animations. Every `animate-*` / `transition-*` class must come from `packages/theme/src/tokens/semantic/animations.js`; every motion-bearing class pairs with `motion-reduce:*` on the same class string; no component-local `@keyframes`. +- Do not create class presets in JavaScript (`const kindClasses = {...}`, `const sharedClasses = [...]`, `const sizeClasses = {...}`, `const rootClasses = computed(...)`). Variants live on `data-*` attributes consumed by Tailwind `data-[attr=value]:`. All utilities live inline on the root element's `class` attribute. No `