Tree & Flow Variants
30 dynamic, zero-dependency tree canvases — add, edit, remove nodes and copy the source
Fulfilment Pipeline
Branching workflow with stage labels — like the warehouse fulfilment screenshot.
Hover any node to add a child, rename or remove it. Drag the grip handle on draggable variants to reparent or reorder. Read-only variants disable every affordance.
Search matches node labels. Sort re-orders each parent's children. Tags / smart filter mark which nodes match; Dim fades non-matches in place, Hide removes them from the tree.
Order Pool
Fulfillment
Pick
Task Release
Full Pallet Pull
AI Recommended
Case → LPN Build
Order Consolidation
Order Audit
Pallet Wrap
Print Labels
Stage by Carrier
Load LTL Shipment
Sort & Pack
Install & set up
Everything this tree needs: 6 generated files to copy and 7 shared engine files the CLI can install for you.
Choose how data is fetched
Two independent choices. The default adds no dependency at all — the command below and the code both follow whatever you pick.
HTTP client — used by services.ts
Where results live — used by hooks.ts
Adds no extra packages.
Install it with the CLI
Installs every file below and its packages in one command. The steps after this are only for doing it by hand.
npx afnoui add tree/tree-fulfilmentOr install the packages yourself
Only needed if you copied the files by hand instead of running the command above.
Runtime dependencies
npm install react react-dom lucide-react clsx tailwind-mergeDev dependencies
None — nothing extra is needed at build time.
- Requires AfnoUI components: badge.
- Bring `cn` from your `@/lib/utils` (clsx + tailwind-merge).
- Zero graph-library dependency — TreeCanvas computes layouts + drag itself.
- The GraphToolbar (search / sort / filter) installs only for variants with `showToolbar: true`.
Generated files
Generated files are yours to copy and edit; shared engine files are installed once and reused.
Generated per tree(6)
Shared engine — copy once(7)
The composed component — drop into any page. Includes the GraphToolbar search/sort/filter bar.
import { useState } from "react";
import { TreeCanvas } from "@/components/tree/TreeCanvas";
import type { TreeNode } from "@/components/tree/types";
import { GraphToolbar, useGraphFilter, defaultGraphFilter } from "@/components/graph";
import { initialTree } from "./data";
import { treeConfig } from "./config";
import { useFulfilmentPipelineHandlers } from "./hooks";
/**
* FulfilmentPipeline — a fully-typed, self-contained tree with a search / sort /
* filter toolbar above the canvas.
*
* Drop into any page:
* <FulfilmentPipeline />
*
* To plug into a backend, put requests in `./services.ts` and glue them in `./hooks.ts`. To remove the
* toolbar, delete the `GraphToolbar`/`useGraphFilter` wiring below and set
* `showToolbar: false` in `./config.ts`.
*/
export function FulfilmentPipeline() {
const [tree, setTree] = useState<TreeNode>(initialTree);
const [filter, setFilter] = useState(defaultGraphFilter);
const { handleNodeAdd, handleNodeUpdate, handleNodeRemove, handleNodeMove } = useFulfilmentPipelineHandlers();
const { tree: filteredTree, matches, stats, allTags } = useGraphFilter(tree, filter);
return (
<div className="flex flex-col gap-2">
<GraphToolbar
filter={filter}
onChange={setFilter}
allTags={allTags}
matched={stats.matched}
total={stats.total}
/>
<TreeCanvas
config={treeConfig}
tree={filter.mode === "hide" ? filteredTree : tree}
onTreeChange={setTree}
highlightIds={filter.mode === "dim" ? matches : undefined}
onNodeAdd={handleNodeAdd}
onNodeUpdate={handleNodeUpdate}
onNodeRemove={handleNodeRemove}
onNodeMove={handleNodeMove}
/>
</div>
);
}