feat: merge Docusaurus and Gitea documentation skills
validate / validate (push) Successful in 6s

This commit is contained in:
2026-08-14 12:32:08 +00:00
parent cfb006d7ea
commit b08614dc90
28 changed files with 4202 additions and 1 deletions
+409
View File
@@ -0,0 +1,409 @@
# React Flow Documentation Visualizations
Use [React Flow](https://reactflow.dev/) when structured documentation data needs an interactive spatial view: roadmaps, Gantt-like timelines, dependency graphs, or traceability maps between Features, requirements, and architectural decisions. React Flow is a renderer and interaction layer, not the authoritative data store and not a built-in layout engine.
This capability assumes the local YAML data pattern in [local-yaml-data-database.md](local-yaml-data-database.md). Build nodes and edges from validated source YAML records. Never maintain a second copy of roadmap or relationship data inside TSX or MDX.
## Appropriate uses
Use React Flow for:
- a roadmap organized by Epic, lane, status, release, or date;
- a Gantt-like roadmap where time determines horizontal position and lane determines vertical position;
- Feature-to-Feature dependencies;
- Requirement-to-Feature n:m traceability;
- architectural decision-to-Feature n:m traceability;
- a combined, filterable delivery or architecture dependency map.
Do not use React Flow for ordinary prose, small static tables, or a linear list with no useful spatial relationship. Keep a semantic table fallback for every visualization so the information remains searchable, printable, and accessible without client-side JavaScript.
## Official baseline
Use the current package name documented by React Flow:
```text
pnpm add @xyflow/react
```
Import the required base stylesheet once in the visualization component or shared theme entry:
```ts
import '@xyflow/react/dist/style.css';
```
Relevant official guidance:
- [Quick Start](https://reactflow.dev/learn)
- [Layouting overview](https://reactflow.dev/learn/layouting/layouting)
- [Accessibility](https://reactflow.dev/learn/advanced-use/accessibility)
- [Server-side rendering](https://reactflow.dev/learn/advanced-use/ssr-ssg-configuration)
- [Testing](https://reactflow.dev/learn/advanced-use/testing)
React Flow does not provide one automatic graph layout. Its official layouting guide describes external options including Dagre, D3, and ELK. Choose and document the layout deliberately.
## Component boundary
Keep data loading, graph adaptation, layout, and rendering separate:
```text
data/**/*.yml
↓ build-time validation
DocumentationDatabase
↓ pure adapter
GraphModel { nodes, edges, fallbackRows, legend }
↓ pure layout
PositionedGraphModel
↓ React component
RoadmapFlow | DependencyMap
↓ MDX composition
Documentation page
```
Recommended source structure:
```text
src/components/documentation-data/
├── react-flow/
│ ├── DocumentationFlow.tsx
│ ├── RoadmapFlow.tsx
│ ├── DependencyMap.tsx
│ ├── nodes/
│ │ ├── FeatureNode.tsx
│ │ ├── RequirementNode.tsx
│ │ └── ArchitectureDecisionNode.tsx
│ ├── adapters/
│ │ ├── roadmapGraph.ts
│ │ ├── featureDependencyGraph.ts
│ │ ├── requirementFeatureGraph.ts
│ │ └── decisionFeatureGraph.ts
│ ├── layout/
│ │ ├── ganttLayout.ts
│ │ └── dependencyLayout.ts
│ └── DocumentationFlow.module.css
└── fallbacks/
├── RoadmapTable.tsx
└── TraceabilityTable.tsx
```
Adapters and layout functions must be pure TypeScript functions. Test them without a browser. React components receive already validated records or a typed graph model; they do not parse files.
## Docusaurus client boundary
React Flow 12 supports server rendering when node dimensions and handle positions are supplied. That is an advanced path. For normal interactive Docusaurus documentation, use Docusaurus `BrowserOnly` to avoid hydration differences and browser-global failures:
```tsx
import BrowserOnly from '@docusaurus/BrowserOnly';
import type {Props} from './DependencyMap';
export default function DependencyMapClient(props: Props) {
return (
<BrowserOnly fallback={<div>Loading dependency map…</div>}>
{() => {
const DependencyMap = require('./DependencyMap').default;
return <DependencyMap {...props} />;
}}
</BrowserOnly>
);
}
```
Use `@docusaurus/BrowserOnly`, not an unguarded `window` check scattered through components. If server-rendered graph HTML is an explicit requirement, follow the official React Flow 12 SSR guidance and provide deterministic node `width` and `height`, handle positions, and initial viewport data.
## Required canvas sizing
React Flow requires a parent with explicit dimensions. Never rely on content height:
```css
.canvas {
width: 100%;
height: min(72vh, 760px);
min-height: 420px;
border: 1px solid var(--ifm-color-emphasis-300);
border-radius: 0;
}
:global(.react-flow__node),
:global(.react-flow__controls-button),
:global(.react-flow__minimap) {
border-radius: 0;
}
```
Use sharp edges throughout. Do not introduce pill nodes, rounded cards, rounded controls, or rounded filter inputs.
## Shared read-only renderer
Documentation views are read-only unless an editing workflow is separately approved. Disable accidental graph mutation:
```tsx
import {
Background,
Controls,
MiniMap,
ReactFlow,
ReactFlowProvider,
type Edge,
type Node,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
export function DocumentationFlow({nodes, edges}: {
nodes: Node[];
edges: Edge[];
}) {
return (
<div className={styles.canvas} aria-label="Documentation dependency map">
<ReactFlowProvider>
<ReactFlow
nodes={nodes}
edges={edges}
fitView
nodesDraggable={false}
nodesConnectable={false}
deleteKeyCode={null}
nodesFocusable
edgesFocusable
disableKeyboardA11y={false}
minZoom={0.35}
maxZoom={1.8}
proOptions={{hideAttribution: false}}
>
<Controls showInteractive={false} />
<MiniMap pannable zoomable />
<Background />
</ReactFlow>
</ReactFlowProvider>
</div>
);
}
```
Keep attribution behavior compliant with the installed package's license and React Flow terms. Do not hide attribution merely for visual preference.
## Roadmap and Gantt-like layout
React Flow is not a dedicated Gantt package. Implement a Gantt-like roadmap as a deterministic node layout over validated scheduling fields.
Recommended Feature source fields:
```yaml
id: feature-001
title: Display project lifecycle state
epic_id: epic-001
status: in-progress
depends_on_feature_ids:
- feature-000
roadmap:
start: 2026-08-01
end: 2026-08-21
lane: portal
progress: 60
```
Layout rules:
1. Parse dates in one declared timezone and reject invalid ranges.
2. Compute `x` from `start` relative to the roadmap's minimum date.
3. Compute node width from the duration between `start` and `end`.
4. Compute `y` from the stable lane order in data or configuration.
5. Draw Feature dependency edges from `depends_on_feature_ids`.
6. Render release or milestone markers as non-connectable custom nodes.
7. Preserve a consistent time scale while zooming; include a visible date-axis component outside the graph viewport.
8. Provide filters for Epic, status, lane, release, and owner without mutating source data.
9. Provide a table fallback ordered by lane, start date, end date, and stable Feature ID.
Do not let dragging persist a new schedule. A documentation reader moving a node is not a data edit. If manual positioning is required for a non-time-based roadmap, store approved coordinates in source YAML and validate them.
For a roadmap without dates, use a phase or status-column layout. Keep phases in source data and calculate positions deterministically. Do not infer ordering from file enumeration.
## Dependency layouts
### Feature dependencies
Build one node per Feature and one directed edge per `depends_on_feature_ids` entry. Reject missing Feature IDs. Detect cycles and either fail validation for a declared DAG or render cycles with an explicit warning when cyclic relationships are valid domain data.
For ordinary directed acyclic Feature graphs, use Dagre:
```text
pnpm add @dagrejs/dagre
```
Dagre is appropriate for a compact, deterministic directed layout. Set node dimensions before layout and map Dagre's center-based coordinates to React Flow positions.
### Complex or grouped dependencies
For larger maps with nested Epics, compound nodes, multiple ports, or stronger edge-routing requirements, use ELK:
```text
pnpm add elkjs
```
ELK layout is asynchronous. Resolve it before rendering the final graph and show a stable loading state. Do not run a new layout on every React render.
### Requirement-to-Feature traceability
Create typed nodes and edges from canonical requirement `feature_ids`:
```text
Functional Requirement ── satisfies/constrains ──> Feature
Non-functional Requirement ── constrains ──> Feature
```
Use distinct node types, edge styles, labels, and a visible legend. Filters must distinguish functional and non-functional requirements. Do not encode meaning only with color.
### Architectural decision-to-Feature traceability
Create typed nodes and edges from canonical architectural decision `feature_ids`:
```text
Architectural Decision ── governs/affects ──> Feature
```
Display decision status and link each node to its canonical documentation route. A superseded decision remains traceable but must be visually and textually identified as superseded.
### Combined maps
A combined map may include Features, requirements, and architectural decisions, but it must start with a constrained default scope. Large all-record graphs become unreadable and expensive. Require one or more of:
- selected Epic;
- selected Feature;
- selected requirement type;
- selected decision status;
- bounded dependency depth;
- search result or explicit ID list.
Apply filtering before layout so hidden nodes do not consume space.
## Adapter contract
A graph adapter should return all rendering and fallback information from one source:
```ts
export type DocumentationGraph = {
nodes: Node<DocumentationNodeData>[];
edges: Edge<DocumentationEdgeData>[];
fallbackRows: TraceabilityRow[];
legend: LegendItem[];
warnings: GraphWarning[];
};
export function requirementFeatureGraph(
database: DocumentationDatabase,
filter: RequirementFeatureFilter,
): DocumentationGraph;
```
Requirements for every adapter:
- stable node IDs equal stable database IDs;
- stable edge IDs derived from source type, source ID, relation, and target ID;
- no random coordinates or IDs;
- no filesystem access;
- no mutation of database records;
- explicit behavior for missing, filtered, superseded, or cyclic records;
- table fallback rows derived in the same function as nodes and edges.
## MDX composition
MDX chooses the view and scope. It does not define nodes or edges:
```mdx
---
title: "Explore Feature dependencies"
description: "Inspect Feature dependencies and related requirements."
---
import DependencyMapClient from '@site/src/components/documentation-data/react-flow/DependencyMapClient';
import TraceabilityTable from '@site/src/components/documentation-data/fallbacks/TraceabilityTable';
<DependencyMapClient
mode="feature-requirements"
epicId="epic-001"
/>
<TraceabilityTable
mode="feature-requirements"
epicId="epic-001"
/>
```
The map and table must consume the same adapter output or the same normalized selector so they cannot disagree.
## Accessibility
React Flow provides keyboard and screen-reader support. Preserve it:
- keep `nodesFocusable` and `edgesFocusable` enabled;
- keep `disableKeyboardA11y={false}`;
- provide meaningful `ariaLabel` values for custom nodes and edges;
- ensure custom node links and controls have visible focus states;
- provide text labels in addition to colors and line styles;
- provide a legend that explains node types, statuses, and edge meanings;
- provide an adjacent semantic table fallback with the same filtered records;
- preserve keyboard access to filters, fit-view controls, and linked detail pages;
- test at 200% zoom and in both light and dark themes.
Read-only means mutation is disabled, not navigation or focus.
## Performance
- Memoize node types outside React components.
- Build graph data with pure selectors and memoize by database revision and filter state.
- Filter before layout.
- Avoid recreating nodes and edges on every render.
- Do not render the full database by default.
- Use bounded dependency depth for large graphs.
- Lazy-load the BrowserOnly visualization component.
- Run asynchronous ELK layout only when the relevant graph input changes.
- Measure browser interaction with representative production-size data, not only two-node examples.
## Testing and verification
Test pure transformation and layout behavior first:
- scheduling dates produce stable Gantt `x`, width, and lane `y` values;
- Feature dependencies produce the expected directed edges;
- Requirement and architectural decision n:m mappings produce complete edges;
- filters remove nodes before layout;
- dangling IDs fail validation before graph construction;
- stable inputs produce byte-equivalent graph IDs and coordinates;
- fallback table rows represent the same relationships as graph edges;
- cycles follow the declared policy.
Then test React behavior:
- the BrowserOnly fallback renders during static generation;
- the canvas mounts with explicit width and height;
- nodes and edges are keyboard focusable;
- graph mutation is disabled;
- filters, detail links, fit view, pan, and zoom work;
- missing and empty datasets render useful states;
- table fallback remains usable without the graph.
Required delivery checks:
```text
pnpm data:validate
pnpm data:check
pnpm test
pnpm typecheck
pnpm build
```
After the production build, exercise each affected page in a real browser. Verify light and dark themes, desktop and narrow widths, keyboard navigation, labels, filters, links, pan/zoom, empty states, and the table fallback. Then verify the exact Gitea Actions SHA and deployed route.
## Acceptance checklist
- [ ] `@xyflow/react` and its base stylesheet are installed and imported.
- [ ] React Flow receives validated build-time data from source YAML through a pure adapter.
- [ ] Roadmap scheduling and Feature dependencies are stored in YAML, not TSX or MDX.
- [ ] Gantt-like positions are deterministic from dates and lanes.
- [ ] Dagre or ELK is chosen explicitly for dependency layout; React Flow is not described as providing automatic layout.
- [ ] Feature, requirement, and architectural decision relationships use stable IDs and typed nodes/edges.
- [ ] Docusaurus uses `BrowserOnly`, or the advanced React Flow 12 SSR dimensions are fully configured.
- [ ] The canvas has explicit width and height.
- [ ] Documentation views disable dragging, connecting, and deletion.
- [ ] Keyboard and screen-reader support remains enabled.
- [ ] Sharp styling applies `border-radius: 0` to nodes, controls, minimaps, filters, and surrounding panels.
- [ ] Every visualization has a semantic table fallback derived from the same adapter.
- [ ] Unit, component, type, production build, browser, Actions, and deployed-route checks pass.