Files
soleprint/soleprint/atlas2/docgen/style/lucid.json

374 lines
12 KiB
JSON

{
"name": "lucid",
"note": "Visual language for generated diagrams. Keyed on `kind`, which is the only IR field style may read. Rules name SLOTS, never hexes; a theme binds slot -> colour. That indirection is the point: it is the same vocabulary `soleprint/common/theme/tokens.css` and `docs/graphs/themes/*.gvpr` already use, so a diagram and the page around it are one visual language. docs/graphs/README.md states the rule.",
"default_theme": "dark",
"themes": {
"lucid": {
"note": "Print and light, for documents and anything that gets exported. Extracted from real architecture diagrams, then re-bound onto spr's slots. Ask for it with `--theme lucid`.",
"slots": {
"surface-0": "#FFFFFF",
"surface-1": "#FAFAFA",
"surface-2": "#F5F7FA",
"border": "#BDBDBD",
"border-strong": "#9E9E9E",
"text": "#333333",
"text-muted": "#616E7C",
"text-dim": "#9AA5B1",
"text-on-fill": "#000000",
"accent": "#FFB74D",
"accent-soft": "#FFF3E0",
"artery": "#E53935",
"artery-soft": "#FFEBEE",
"atlas": "#43A047",
"atlas-soft": "#E8F5E9",
"station": "#1E88E5",
"station-soft": "#E3F2FD",
"ok": "#43A047",
"error": "#E53935",
"muted": "#E0E0E0",
"muted-soft": "#FAFAFA",
"alt-1": "#B39DDB",
"alt-1-soft": "#EDE7F6",
"alt-2": "#FFF176",
"alt-2-soft": "#FFFDE7"
}
},
"dark": {
"note": "The default. Every value is a tokens.css variable or a --system-accent, so a diagram embedded in a page matches it without anyone choosing. artery/atlas/station are exactly what artery/index.html:30, atlas/index.html:25 and station/index.html:29 set. `--theme lucid` switches to the print palette.",
"slots": {
"surface-0": "#0a0a0a",
"surface-1": "#141414",
"surface-2": "#1a1a1a",
"border": "#333333",
"border-strong": "#4a4a4a",
"text": "#e5e5e5",
"text-muted": "#a3a3a3",
"text-dim": "#666666",
"text-on-fill": "#0a0a0a",
"accent": "#d4a574",
"accent-soft": "#242424",
"artery": "#b91c1c",
"artery-soft": "#fca5a5",
"atlas": "#15803d",
"atlas-soft": "#86efac",
"station": "#1d4ed8",
"station-soft": "#93c5fd",
"ok": "#3ecf8e",
"error": "#f06565",
"muted": "#555568",
"muted-soft": "#141414",
"alt-1": "#4f9cf9",
"alt-1-soft": "#141414",
"alt-2": "#f5a623",
"alt-2-soft": "#141414"
}
}
},
"geometry": {
"note": "Pinned to tokens.css rather than retyped. The supplied spec and spr's tokens agreed on six of these independently: radius 4-6px, label 10-11px, header 12-14px, padding 8px, hairline 1px, and a Segoe-UI-through-Arial sans stack.",
"radius-sm": 4,
"radius": 6,
"hairline": 1,
"font": "Helvetica",
"font-note": "PostScript-style names, because they are the only spelling Graphviz maps to a real SVG font-weight. `fontname=\"Arial Bold\"` passes through verbatim as font-family=\"Arial Bold\" \u2014 a family no browser has, so it renders neither Arial nor bold. `Helvetica-Bold` emits font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\", which is a real stack with a real weight. It also measures wider (128pt vs 116pt for the same label), so boxes are sized for the text that actually renders instead of overflowing it.",
"font-size-sm": 10,
"font-size-base": 11,
"font-size-header": 13,
"padding": "0.20,0.10",
"font-bold": "Helvetica-Bold"
},
"graph": {
"bgcolor": "surface-0",
"fontcolor": "text",
"rankdir": "TB",
"nodesep": 0.5,
"ranksep": 0.6,
"pad": 0.3
},
"nodes": {
"default": {
"shape": "box",
"rounded": true,
"fill": "surface-0",
"border": "border",
"text": "text",
"note": "Every unknown kind lands here rather than crashing. A new extractor renders plainly and legibly on day one.",
"bold": true
},
"component": {
"shape": "box",
"rounded": true,
"fill": "surface-0",
"border": "border",
"text": "text",
"bold": true
},
"datastore": {
"shape": "cylinder",
"rounded": false,
"fill": "surface-0",
"border": "border",
"text": "text",
"bold": true
},
"bucket": {
"shape": "trapezium",
"rounded": false,
"fill": "surface-0",
"border": "border",
"text": "text",
"note": "An approximation. DOT has no S3-bucket silhouette; trapezium is the nearest native shape.",
"bold": true
},
"module": {
"shape": "box",
"rounded": true,
"fill": "surface-2",
"border": "border-strong",
"text": "text",
"bold": true
},
"class": {
"shape": "box",
"rounded": true,
"fill": "surface-0",
"border": "station",
"text": "text",
"bold": true
},
"function": {
"shape": "box",
"rounded": true,
"fill": "surface-0",
"border": "border",
"text": "text-muted",
"font-size": "font-size-sm",
"bold": true
},
"external": {
"shape": "box",
"rounded": true,
"fill": "muted-soft",
"border": "muted",
"text": "text-muted",
"dashed": true,
"note": "A name that could not be resolved. Drawn as the boundary it is, and never dropped \u2014 a missing dependency that looks like a complete diagram is the worse failure.",
"bold": true
},
"task": {
"shape": "box",
"rounded": true,
"fill": "surface-2",
"border": "station",
"text": "text",
"bold": true,
"note": "A unit of work in a pipeline \u2014 an Airflow task, a build step. Distinct from `module` so a schedule does not render as if it were code structure."
},
"sensor": {
"shape": "hexagon",
"rounded": false,
"fill": "surface-2",
"border": "accent",
"text": "text",
"bold": true,
"note": "A task that waits on something outside the pipeline."
},
"endpoint": {
"shape": "box",
"rounded": true,
"fill": "surface-2",
"border": "station",
"text": "text",
"bold": true,
"note": "An HTTP route. From a spec, or from what was actually called."
},
"operation": {
"shape": "box",
"rounded": true,
"fill": "surface-2",
"border": "accent",
"text": "text",
"bold": true,
"note": "A GraphQL operation \u2014 usually one endpoint carrying many, which is why it is its own kind rather than a path."
}
},
"groups": {
"default": {
"rounded": false,
"dashed": true,
"fill": "surface-2",
"border": "border",
"text": "text-muted",
"bold": true
},
"boundary": {
"rounded": false,
"dashed": false,
"fill": "surface-0",
"border": "border-strong",
"header-fill": "accent",
"text": "text-on-fill",
"bold": true,
"note": "Type A. The header is a filled bar across the top of the container in the source spec; DOT gives a label plus a cluster bgcolor and no separate bar. See limits.header-bar."
},
"zone": {
"rounded": false,
"dashed": true,
"fill": "surface-2",
"border": "border",
"text": "text-muted",
"note": "Type B. Dashed area boundary.",
"bold": true
},
"artery": {
"rounded": false,
"dashed": true,
"fill": "artery-soft",
"border": "artery",
"text": "text-muted",
"bold": true
},
"atlas": {
"rounded": false,
"dashed": true,
"fill": "atlas-soft",
"border": "atlas",
"text": "text-muted",
"bold": true
},
"station": {
"rounded": false,
"dashed": true,
"fill": "station-soft",
"border": "station",
"text": "text-muted",
"bold": true
},
"pipeline": {
"rounded": false,
"dashed": true,
"fill": "surface-2",
"border": "border",
"text": "text-muted",
"bold": true,
"note": "One DAG, when several are drawn together."
}
},
"edges": {
"default": {
"color": "text",
"arrowhead": "normal",
"arrowsize": 0.7,
"text": "text-muted"
},
"imports": {
"color": "border-strong",
"arrowhead": "normal",
"arrowsize": 0.6,
"text": "text-dim"
},
"inherits": {
"color": "station",
"arrowhead": "empty",
"arrowsize": 0.8,
"text": "text-muted"
},
"calls": {
"color": "text",
"arrowhead": "normal",
"arrowsize": 0.7,
"text": "text-muted"
},
"async": {
"color": "text",
"arrowhead": "normal",
"arrowsize": 0.7,
"dashed": true,
"text": "text-muted"
},
"flow": {
"color": "artery",
"arrowhead": "normal",
"arrowsize": 0.7,
"dashed": true,
"text": "artery"
},
"ok": {
"color": "ok",
"arrowhead": "normal",
"arrowsize": 0.7,
"dashed": true,
"text": "ok"
},
"foreign_key": {
"color": "station",
"arrowhead": "normal",
"arrowsize": 0.7,
"text": "text-muted"
},
"references": {
"color": "border-strong",
"arrowhead": "normal",
"arrowsize": 0.6,
"dashed": true,
"text": "text-dim"
},
"depends": {
"color": "border-strong",
"arrowhead": "normal",
"arrowsize": 0.7,
"text": "text-muted"
},
"triggers": {
"color": "accent",
"arrowhead": "normal",
"arrowsize": 0.8,
"text": "accent"
},
"follows": {
"color": "accent",
"arrowhead": "normal",
"arrowsize": 0.7,
"text": "accent",
"note": "Observed order. Consecutive, not caused-by; the weight is the signal."
},
"accepts": {
"color": "border-strong",
"arrowhead": "normal",
"arrowsize": 0.6,
"text": "text-dim"
},
"returns": {
"color": "station",
"arrowhead": "normal",
"arrowsize": 0.6,
"text": "text-dim"
}
},
"domain_slots": {
"note": "How a group picks its colour without the IR ever naming one. The IR says which spr model a group belongs to (attrs.domain \u2014 semantic); this maps that to a slot. Same mechanism as --system-accent. Where a group has no domain, the emitter assigns the rotation below by sorted id, so the choice is deterministic and two runs give the same bytes.",
"artery": "artery",
"atlas": "atlas",
"station": "station",
"soleprint": "accent",
"rotation": [
"accent",
"alt-1",
"alt-2",
"station",
"atlas",
"artery"
]
},
"limits": {
"note": "Where DOT stops. Recorded rather than worked around; the full spec is kept here so a richer emitter needs no re-authoring. See the plan's 'Use DOT until it hits its limits'.",
"header-bar": "Type A's filled 100%-width header rectangle. DOT clusters have a label and a bgcolor, not a header bar. Needs an HTML-like label table.",
"dasharray": "stroke-dasharray is not parameterised \u2014 style=dashed is one pattern, so 4,4 and 5,5 collapse. Async and thematic edges must differ by colour, not by dash.",
"corner-radius": "style=rounded is binary, so radius-sm (4) and radius (6) render identically.",
"icon-above-label": "Icon centered above a centered label needs an HTML-like label or image+labelloc; text only here.",
"sequence-badge": "A numbered circle on an edge. xlabel carries the number; the circle, its fill and its border are not expressible.",
"bucket-shape": "trapezium approximates the S3 bucket silhouette.",
"ranged-widths": "The spec gives 1-2px and 1-1.5px; penwidth is scalar, so these pin to geometry.hairline."
}
}