Diagrams
DiagramInspector
What the reader just picked, written out beside the picture.
Usage
When to reach for it
Ships from@misoto22/design/diagrams
import { DiagramInspector } from '@misoto22/design/diagrams'Notes
What the reader just picked, written out.
A diagram can hold about eight words per node before it stops being a diagram and starts being a document with lines drawn on it. Everything past those eight — the port, the owning team, the file it was read out of, the six relationships it takes part in — belongs beside the picture rather than inside it, and this is that place.
NOT A DIALOG, and that is deliberate. An inspector is a REGION that changes with the selection, not a modal. Giving it role="dialog" would trap focus and demand dismissal for something the reader never opened — they clicked a node, and the panel followed. So it is a labelled region with aria-live="polite", which is what makes a screen reader announce the new selection without stealing the cursor from whatever the reader was doing.
The relationships are real buttons when they carry onSelect, which is how the diagram becomes navigable from the keyboard: a reader can walk the graph peer by peer without ever touching the picture.
Anatomy
| Element | Description |
|---|---|
| Regionrequired | A <section> named "<title> details" with aria-live="polite", on a panel plate. A region and not a dialog: nothing traps focus and nothing demands dismissal, because the reader clicked a node rather than opening a window. |
| Headingrequired | The eyebrow over the title — what KIND of thing this is, then what it is called. The eyebrow is where the plate’s own kicker word belongs, so the panel and the picture say the same thing about the same node. |
| Facts | A definition list, one term and value per row, the value settable in mono for an id, a path, a port. A list rather than a grid of divs, because a grid tells a screen reader nothing about which value belongs to which label. |
| Relationships | One row per edge the node takes part in, each becoming a real button when it carries onSelect. The arrow glyph is hidden and the direction spelled out beside it, so "to" and "from" are heard rather than guessed. |
| Close | A small control named for what it does — clearing the selection, not closing a window. It is the only thing that can empty the panel. |
| Actions | A wrap of caller-supplied buttons under the facts: copy the id, open the source the node was read out of. |
Best practices
Do
- Pair it with the figure’s onSelectNode. That is what turns the hidden summary list into real buttons, and without it the panel can only ever be filled by a pointer — the plates in the picture are presentational by construction.
- Give every relationship an onSelect. The rows become buttons and the graph becomes walkable peer by peer, which is how a keyboard reader gets from a node to the node it is connected to without going back through the list.
- Move the long facts here and leave about eight words on the plate. A box holding a port, an owning team and a file path grows to fit all three rather than clipping them, and a figure of boxes that size is a document with lines drawn on it.
Don’t
- Two facts sharing a label are two rows, and neither says which is which. They are keyed by position, so both render — and a panel with "Source" twice leaves the reader deducing from the values what the labels should have said. Name them apart when they mean different things.
- floating pins the panel over the surface, so it covers that corner of the diagram for as long as it is mounted. It has no dismissal contract of its own — passing no onClose leaves the reader nothing to press and the corner hidden until the selection changes.
Examples
default
What a selection puts on the screen: the kind of thing it is, its name, the facts too long to print on a plate, and every relationship it takes part in with the direction spelled out. It is a labelled region with aria-live, not a dialog — the reader clicked a node rather than opening a panel, so nothing here traps focus or has to be dismissed before the page works again. mono is for values a reader may retype; the facts are a definition list, so a screen reader can say which value belongs to which label.
API
FastAPI, behind the load balancer. Owns every read the cache misses.
- 8000
- ap-southeast-2
- api
- fromCloudFront
- toRedis
- toPostgres
nothing selected
The panel has no empty state of its own — title is required, so there is no way to render one with nothing in it, and what a reader sees before they pick anything is the caller’s to draw. Draw something: a column that vanishes when the selection clears takes the rest of the layout with it every time somebody closes the panel. The relationship row is a real button because it carries onSelect, which is what lets a keyboard walk the graph peer by peer without ever reaching the picture; onClose returns to the empty case.
Pick a component to see what it is and what reaches it.
pinned over the figure
floating turns the panel into a plate pinned to the bottom-left of the nearest positioned ancestor, so the wrapper has to establish one or it will pin itself to something further up the page. Pin it when the figure owns the viewport and a panel in the flow underneath would be off-screen at the moment it is needed; leave it inline when the figure is one item in an article. activeIds lights the same node the panel is about, and neither reaches into the other — the picture and the panel are two consumers of one selection. actions is where what a reader does with the selection goes. The region takes its accessible name from title, so two panels on one page must not inspect the same node — this one selects the datastore rather than the service the first example is about.
3 elements and 2 relationships.
- CloudFront (cloud) — CDN
- API (backend) — FastAPI
- Postgres (database)
- CloudFront → API: HTTPS
- API → Postgres: SQL
Postgres
The primary, and the end of the request path above it.
- db
- 1
Accessibility
- A labelled region with aria-live="polite", not a dialog: the reader clicked a node, they did not open anything, so focus is never trapped or demanded.
- Relationships are real buttons when they carry onSelect, which is how the graph becomes walkable peer by peer from the keyboard.