# Rack Presentation Improvements Design **Date:** 2026-06-24 **Status:** Approved **Parent spec:** `notes/dev/specs/2026-06-24-rack-documentation-design.md` (extension) ## Goal Improve the graphical presentation of the generated rack page: make the elevation **interactive** (inline SVG, clickable boxes, hover tooltips), encode device **status** visually, add a **legend**, and **polish** both the elevation and the mermaid power/network graphs. No new data is modelled; this is a rendering upgrade of what `gen_rack.py` already produces. ## Context - `render_svg` writes a standalone `rack01-elevation.svg`, embedded in `rack01.md` as `![Rack rack01 elevation](rack01-elevation.svg)` — i.e. an ``, which is a **flat image**: links and tooltips inside it do not work. - `render_power`/`render_network` emit default-themed mermaid flowcharts with uncoloured, non-clickable nodes. - The occupancy table already links to host pages; the SVG and graphs do not. - `md_in_html` is enabled in `mkdocs.yml`, so raw inline HTML/SVG in a Markdown page is rendered. Mermaid is enabled (Phase 2). - `use_directory_urls` is unset → defaults to **true**: pages build to `//index.html`, so a host page is served at `/hardware//` and the rack page at `/infrastructure/racks/rack01/`. The site is served at the domain root (`docs.makerfloss.eu`). - `KIND_COLORS` already maps kinds → fill colours. There is no status encoding, legend, link, or tooltip today. ## Decisions ### A. Inline, interactive elevation - `render_page` embeds the SVG markup **inline** in `rack01.md`, inside a `
` block, replacing the `![…](rack01-elevation.svg)` image line. (`md_in_html` passes the raw block through.) - The standalone `rack01-elevation.svg` is **still generated** (identical markup, still drift-checked) and offered below the diagram as a `[Download SVG](rack01-elevation.svg)` link. - The `` opening tag gains `style="max-width:100%;height:auto"` so it scales on narrow screens. - **Clickable boxes:** every device drawing (rail box, shelf-occupant box, 0U rail bar, shelf strip) is wrapped in ``. URLs are **root-relative final URLs** — mkdocs does **not** rewrite `.md`/source-relative hrefs inside raw inline SVG, and `use_directory_urls` + domain-root hosting make `/hardware//` correct and robust. - **Tooltips:** the `` wrapper's first child is an SVG `` carrying full details: `" · · · cluster: · "`, where `` is the U-range (rail item), `0U ` (0U rail), or `//slot ` (mounted item). Text run through `_esc`. ### B. Status encoded as border Fill stays the kind colour; the box **border** encodes `status` via a `_status_stroke(status) -> (stroke, stroke_width, dash)` helper: | status | stroke | width | dash | |--------|--------|-------|------| | in-use | `#333` | 1.5 | none | | staging | `#333` | 1.5 | `4 2` (dashed) | | broken | `#e15759` | 3 | none | | spare | `#bbbbbb` | 1.5 | none | | donated | `#bbbbbb` | 1.5 | none | | (other/missing) | `#333` | 1.5 | none | Applied to every device rect (rail `draw_device` and shelf-occupant boxes). The shelf strip and the faint empty-U slots keep their existing styling. ### C. Legend A legend strip is drawn at the **bottom of the SVG canvas**, below the columns; the canvas height grows by a fixed `LEGEND_H` band: - **Kind swatches:** for each `kind` actually present in the rack (sorted), a small colour rect + the kind name. - **Status key:** four small sample borders (solid, dashed, red-thick, grey) with labels `in-use`, `staging`, `broken`, `spare`. ### D. Aesthetic polish - **U-numbers in both gutters:** the existing left-gutter U-number column is mirrored to the right of the rear column. - **Column frame:** a thin outer stroke rectangle around each column's full body (front and rear). - **Mermaid graphs** (`render_power`/`render_network`): - **Colour nodes by kind:** emit a `style fill:,stroke:#333,color:#ffffff` line per node, looking the kind up from the rack items (`KIND_COLORS`, falling back to `DEFAULT_COLOR`). - **Clickable nodes:** emit `click "/hardware//"` for every node whose hostname resolves to a rack item; off-rack nodes get no click. - Edge labels and layout are unchanged. ## Technical constraints (rationale carried into implementation) - ``-embedded SVG is inert → inlining is required for links/tooltips. - mkdocs rewrites Markdown `.md` links but **not** raw `href`/`click` URLs inside inline SVG or mermaid → emit final root-relative URLs `/hardware//`. - `md_in_html` (already enabled) renders the raw `
` block. ## Integration | File | Change | |------|--------| | `scripts/gen_rack.py` | helpers `_host_url`, `_status_stroke`, `_tooltip`; `render_svg` (status borders, ``+`` wrapping, both-gutter U-numbers, column frame, legend, `style=` on `<svg>`); `render_page` (inline SVG `<div>` + download link); `render_power`/`render_network` (per-node `style` + `click`) | | `tests/test_gen_rack.py` | assertions for links, titles, status strokes, legend, both-gutter numbers, inline page block, mermaid style/click | | `docs/infrastructure/racks/rack01.md`, `rack01-elevation.svg` | regenerated | No `mkdocs.yml`, `Makefile`, `.forgejo/workflows/docs.yml`, or `overview_config.yml` changes. Occupancy table and all validation unchanged. ## Test plan - **`render_svg`:** output contains `<a href="/hardware/srv04/"`, a `<title>` with the host details, a dashed stroke for a `staging` fixture and a thick red stroke for a `broken` fixture, kind swatches for the kinds present, U-number text on both sides; deterministic for reordered input. - **`render_page`:** contains `<div class="rack-elevation">` and `<svg`, the `[Download SVG](rack01-elevation.svg)` link, and **no** `![`-image embed of the elevation. - **`render_power`/`render_network`:** contain `style <id> fill:` lines coloured by kind and `click <id> "/hardware/<host>/"` lines; still start with ` ```mermaid ` + `flowchart LR`. - **Drift / build / visual:** `make docs-check` exits 0; `mkdocs build --strict` passes; on the rendered page the elevation boxes are clickable, hovering shows the tooltip, the legend is visible, and the mermaid nodes are coloured and clickable. ## Out of scope - The summary dashboard (U-utilisation / counts) — not selected. - Dark-mode-specific palettes. - A cluster colour system — cluster appears in the tooltip only.