Strategies
ireko has four strategies: grid, radial, tree and layers. A strategy arranges the children of one node. It gets the size of each child and the extent of its subtree, and it gives an offset for each child. The engine does all other work: the recursion, the padding, the fit and the absolute positions. Thus a strategy is a small function, and you can write your own.
Try each option
Section titled “Try each option”The controls come from the option schema of each strategy. The engine uses the same schema to examine the options of a node.
root radial {
a
b { b1 b2 b3 }
c
d
e { e1 e2 e3 }
f
}import { grid, layout, radial } from "ireko";
const root = radial("root",
"a", grid("b", "b1", "b2", "b3"), "c", "d", grid("e", "e1", "e2", "e3"), "f",
);
const result = layout({ root });13 boxes. The audit finds no defect.Open in the playground →
The grid strategy puts the children in rows and columns. Each column is as wide as its widest child, and each row is as tall as its tallest child. A child counts with its whole subtree, so a large subtree gets a large cell.
row {
small
large { a b c d e }
medium { x y }
}The number of columns depends on the mode:
- In the
linkedmode, the default is one row. Then no edge crosses a sibling box. Withside: leftorside: right, the default is one column. - In the
nestedmode, the default is an approximately square grid. - Set
columnsto select a number.
In the linked mode, side selects where the children go:
root { a b c }| Option | Type | Default | Description |
|---|---|---|---|
columns | integer (0 or more) | 0 | The number of columns. With 0, the nested mode makes an approximately square grid, and the linked mode makes one row. |
justify | "start" | "center" | "end" | "center" | The horizontal place of a child in its cell. |
align | "auto" | "start" | "center" | "end" | "auto" | The vertical place of a child in its cell. With auto, linked children align at the top, and nested children at the center. |
uniform | boolean | false | If true, all cells have the size of the largest cell. |
side | "bottom" | "top" | "left" | "right" | "bottom" | In the linked mode, the side of the node where the children go. |
distance | number (0 or more) | 0 | In the linked mode, the distance between the node and its children. The value 0 means 1.5 times the gap. |
radial
Section titled “radial”The radial strategy puts the children on a ring. Each child subtree fits in a circle around the center of its box. Two neighbors need an angle that keeps their circles apart by the gap. On a full ring, the strategy finds the smallest radius at which these angles fill the ring. Thus a small child takes less of the ring than a large child.
hub radial nested {
tiny
big radial nested { a b c d e f }
mid nested { x y z }
tiny2
tiny3
}With sweep less than 360, the children go on an arc. Each child is at the middle of an equal part of the arc, and the largest circle sets the radius.
root radial { a b c d e }| Option | Type | Default | Description |
|---|---|---|---|
startAngle | number (-360 to 360) | -90 | The angle of the first child, in degrees. The value 0 is to the right, and -90 is at the top. |
sweep | number (1 to 360) | 360 | The angle of the arc that holds the children, in degrees. The value 360 is a full ring. |
clockwise | boolean | true | If true, the children follow the clockwise direction on the screen. |
distance | number (0 or more) | 0 | In the linked mode, the smallest distance between the node and the circle of a child. The value 0 means the gap. |
The tree strategy puts the children in one row, on one side of the node, like the linked grid. The grid keeps the extents of the subtrees apart: the rectangles that hold each subtree. The tree strategy keeps their shapes apart. Thus a subtree that is narrow at the top fits under the edge of its neighbor. This layout is a tidy tree.
ceo {
cto { platform { infra { network storage compute } } web { ui api } }
cfo { finance }
coo { ops { warehouse { north south east west } } support }
}The strategy packs the row two times: from the first child to the last, and from the last to the first. Then it takes the mean of the two places of each child. Both packings keep each pair of subtrees apart, so the mean keeps them apart too. The small subtrees go to the middle of their space.
The tree strategy gives the direction of its edges to the router. With the orthogonal router, the edges make the buses of an organization chart. The gallery has this chart with labels.
| Option | Type | Default | Description |
|---|---|---|---|
side | "bottom" | "top" | "left" | "right" | "bottom" | The side of the node where the children go. |
distance | number (0 or more) | 0 | The distance between the node and its children. The value 0 means 1.5 times the gap. |
align | "center" | "start" | "end" | "center" | The place of the node along the row of its children: over the middle, the first child or the last child. |
layers
Section titled “layers”The layers strategy puts the children in layers, in the direction of the edges between them: a flowchart. The edges come from the input. An edge between two subtrees counts for the two children that hold them.
ci "CI" nested layers {
push "git push"
lint test build
pack "package"
review nested layers(side: right) { approve stage }
deploy
}
push -> lint
push -> test
push -> build
lint -> pack
test -> pack
build -> pack
pack -> approve
approve -> stage
stage -> deploy
deploy -> push "next"The strategy has three steps:
- It turns around the edges that close a cycle.
- It gives each child the layer of its longest path from a child with no edge into it.
- It orders each layer by the mean place of the neighbors of each child, so fewer edges cross.
Each layer is as deep as its deepest subtree, and the subtrees in a layer keep the gap. The strategy gives the direction of the flow to the router. Thus the forward edges leave the bottom of a box and enter the top of the next box.
For a large directed graph with many crossings, use dagre or ELK: they have better crossing reduction. The layers strategy is for the flow inside one container.
| Option | Type | Default | Description |
|---|---|---|---|
side | "bottom" | "top" | "left" | "right" | "bottom" | The side where the edges go: the first layer is on the other side. |
distance | number (0 or more) | 0 | The distance between two layers. The value 0 means 2 times the gap. |
align | "center" | "start" | "end" | "center" | The place of a layer across the direction of the edges: at the start, at the middle or at the end. |
Options of each container
Section titled “Options of each container”Each strategy also has gap, padding and header. The engine reads them, not the strategy. Modes and fit explains them.
Write the options
Section titled “Write the options”The text language puts the options in parentheses after the name of the strategy. The builder takes them in an object. Plain objects use layout: { type, ...options }.
team grid(columns: 3, uniform: true) nested { a b c d e }grid.nested("team", { columns: 3, uniform: true }, "a", "b", "c", "d", "e");
const same = { id: "team", mode: "nested", layout: { type: "grid", columns: 3, uniform: true }, children: [/* ... */] };An option with a wrong type or out of its range gives the finding INVALID_OPTION, and the strategy uses the default.