Skip to content

Make the visimer.com hero a live, editable Mermaid diagram (#3353) - #25

Merged
inkeep-oss-sync[bot] merged 1 commit into
mainfrom
copybara/sync
Aug 9, 2026
Merged

Make the visimer.com hero a live, editable Mermaid diagram (#3353)#25
inkeep-oss-sync[bot] merged 1 commit into
mainfrom
copybara/sync

Conversation

@inkeep-oss-sync

Copy link
Copy Markdown

Copybara-translated 1 Inkeep OSS change. Rebase-merge this PR so the prepared commit lands directly on public main.

* Add four design directions for the Visimer site

Four complete, working landing pages at /v1../v4, indexed at /variants.
Each carries the same product truth and the same live editor, and differs
only in visual world, so the review is about direction rather than build
quality.

v1 split-flap: the mechanism as material. A departures board only flips the
flaps that must change, which is what the engine does to your source.
v2 editor-first: the working editor fills the first viewport; copy gets one
line.
v3 datamatics: pure black and white, monospace at data density, every claim
stated as a measured quantity.
v4 poster: flat screened inks, ray burst, claims crammed into ruled cells.

Content the current site never states now appears in all four: the 22 of 23
diagram-type coverage, and a gesture-to-diff demonstration of the minimal
edit property.

Also adds PRODUCT.md recording product truth for the site work.

* Add SPA rewrites so the variant routes survive a direct load

vercel.json only rewrote /playground to index.html, so /variants and
/v1../v4 returned 404 on a direct load or refresh. That is the whole point
of a preview link, so the review routes need the same fallback.

* Add v5, where the headline itself is an editable diagram

The h1 is a live Mermaid flowchart set as display type: node boxes hidden,
words as the glyphs, the connector as the only drawn rule. Double-click a
word and both the headline and the source shown directly beneath it
rewrite, which demonstrates the minimal-edit claim on the claim itself.

Three things the masthead needed that a normal canvas does not:

Mermaid ignores the fontSize theme variable for HTML labels and panZoom
caps its fit at 2x, so neither can drive display scale. The SVG's own
viewBox does it instead, which scales glyphs, rule weights and hit regions
together with nothing to keep in sync.

Selection ships as a drop-shadow around the node box. With the box hidden
it haloed the glyphs, so selection here is the affordance type already has:
the words go signal blue and pick up a rule.

The edit popover is a child of the canvas, so a clipped masthead cut it in
half on the first double-click.

Direction is picked once at mount, top-down under 760px, because a phone
fits the horizontal layout by width and shrinks the masthead to caption
size. Re-picking on resize would overwrite whatever the visitor typed.

* Fix clipped masthead text and the stacked popover icons in v5

Two bugs, both from the masthead CSS reaching further than intended.

The edit popover is a sibling of the diagram inside the same canvas, so the
bare `.mw-canvas svg` sizing rule also matched every icon inside the
toolbar and gave each one `position: absolute; inset: 0`. All five icons
piled onto the same spot. Every masthead rule is now scoped to
`.mw-svg-host > svg`, which is the diagram and nothing else.

Mermaid measures labels in a detached node using its own font and weight,
so the box it allocated was about four pixels narrower than this heavier
face needs and the last glyph of "diagram" was cut off. The node boxes are
invisible here, so the label is allowed out of its box rather than being
made to fit.

Verified in a browser: the popover's five buttons now sit at five distinct
x positions, and no label exceeds its foreignObject with overflow hidden.

* Give v5 a mark that makes the same move the masthead does

The V of the wordmark drawn as a two-edge flow with a node on each vertex:
a letter at a glance, a valid little flowchart on inspection. The bottom
vertex carries the signal blue because that is how a selected node reads
everywhere else on the page.

Nodes run about three times the edge weight so they still read as nodes
rather than as rounded stroke terminals when the mark is shown large, and
the silhouette stays solid enough to survive a 16px tab.

The favicon is a separate file swapped in only while v5 is mounted, and
restored on the way out, so the current site keeps its own mark while this
is still a candidate. It inverts with the browser colour scheme so it holds
on a dark tab strip.

Checked at 16 through 128 on light and dark, in a tab lockup, and beside
the existing mark, which loses its detail below about 24px.

* Reword the v5 masthead to "Edit this directly / render native mermaid"

The headline now names the two things the product actually does rather than
describing the interaction, and the connector becomes single-headed because
the copy reads as a sequence rather than a loop.

The longer strings widen the graph, so the fit-to-width scale drops a little
and the masthead fills more of its box. Checked at both breakpoints; the
top-down layout under 760px still stacks and stays legible.

* Draw the node boxes in the v5 masthead and rename it hero.mmd

The masthead now renders as an ordinary mermaid flowchart, boxes and all,
in the same fill, border and connector colours the playground further down
the page uses. Only the type stays ours: the display face at headline
weight, with the node geometry sizing itself around it.

Hiding the boxes had forced two workarounds that are no longer needed.
Labels were allowed out of their boxes because nothing was drawn to
contain them; they now sit inside, with node padding supplying the width
mermaid does not measure for the heavier face. Selection had been
rewritten as an underline because the shipped drop-shadow haloed bare
glyphs; with boxes drawn it is left exactly as the package ships it, which
also matches what selecting a node does in the playground.

Padding is deliberately tight. The masthead fits to width, so every unit
of node padding is paid for in type size.

The source pane is renamed headline.mmd to hero.mmd, and the line claiming
the masthead is "this component with its node boxes hidden" is corrected,
since that is no longer what it is.

* Add a review page comparing six shapes for the v5 masthead

Six candidate diagrams for the hero, each two or three nodes, rendered
through the real hero component and the real mermaid config so the only
thing being compared is the diagram. All are live and editable in place.

The options use mermaid's own vocabulary rather than just different words:
a plain sequence, a bidirectional edge, a decision diamond with a labelled
edge, a verb carried on the connector, a cylinder standing for the file on
disk, and a three-step chain ending on the losslessness guarantee.

Each card reports its measured type scale, which is the real trade-off
between them. The masthead fits to width, so the shortest option renders
its headline at 3.4x and the wordiest at 2.57x.

The hero mermaid config and the v5 chrome are exported rather than copied,
so the preview cannot drift from what /v5 actually renders. Adds SPA
rewrites for the new route, since /v:id(\d+) does not match /v5-options.

* Add the "WYSIWYG editor / renders native mermaid" masthead options

Three variants of the same positioning, flagged as the latest proposal and
placed at the top of the review page. Unlike the earlier six, the left node
names the product category outright, which is the one thing a cold visitor
cannot infer from a demonstration.

G states it plainly across two nodes. H moves "renders" onto the connector,
where mermaid puts verbs. I drops the verb for a bidirectional edge.

Measured, the verb-on-the-edge trick does not buy the type size it looks
like it should: H renders at 2.66x against G's 2.63x, because the edge
label widens the gap by about as much as the shorter node saves. Only I,
which drops the word entirely, gains real size at 3.05x.

* Make the live diagram the headline on the real site

Replaces the text h1 on the existing site with the editable Mermaid
masthead, keeping everything else exactly as it was: same cream and teal
palette, same badge, subhead, calls to action, playground, features,
recipes and footer.

  flowchart LR
    A[WYSIWYG editor] -->|renders| B[native mermaid]

The verb rides the connector, which is where mermaid puts verbs, so the
whole thing reads as one sentence. The headline runs on its own editor, so
editing it leaves the playground below untouched, and a hint line under it
carries the live source.

Two things this needed beyond styling. The hero container widens from
1000px to 1180px, matching the demo section, because the headline is fit to
its container and a narrow one rendered it at 47px against the 76px the
text h1 carried. And the edge label takes the card colour rather than the
theme's, since mermaid backs edge labels with the secondary (gold) tint
regardless of edgeLabelBackground, which read as a highlighter chip.

Also fixes a containment bug the same treatment had in v5: the svg host was
left to size itself, so the diagram positioned against its own natural
height instead of the card and painted straight out of the hero on the
stacked phone layout. The host is now pinned to the card, and the card goes
portrait under 760px so the stacked headline is not fitted by height.

Headline text is kept in the document for assistive tech and crawlers,
since the visible version is drawn as SVG.

* Make the hero canvas full-bleed, with the page as its background

The headline canvas loses its card. No border, no fill, no radius: it runs
the full width of the window on the site's own background, so the only
thing drawn in that band is the diagram itself. The edge label takes the
page colour too, since there is no longer a card for it to match.

It owns its own band rather than sitting behind the whole section. Mermaid
centres the diagram in its canvas, so a canvas spanning the section centres
on the section's midpoint, which on a phone put the diagram straight on top
of the hint and the subhead. Giving it its own height keeps the diagram
where the layout expects it at every width.

An inset on the svg host keeps the diagram off both screen edges while the
canvas stays edge to edge, and the band goes deeper under 760px so the
stacked layout is fitted by width rather than squashed by height.

* Drop the design-review variants now the hero direction is chosen

Removes the five candidate pages, the hero-options comparison page, the
review index and their routes, the v5 favicon, and the SPA rewrites that
existed only to serve those routes. vercel.json is back to byte-identical
with main.

What the exploration produced stays on the real site: the headline is a
live Mermaid flowchart, full-bleed on the page background, editable in
place.

Also corrects PRODUCT.md, whose "known state" still described the old text
headline and the buried editor.

* Stop the full-bleed hero from overflowing where scrollbars take space

The hero canvas is 100vw, which counts the scrollbar on platforms that
reserve room for one, so the page picked up a horizontal scrollbar
everywhere except macOS overlay scrollbars. `overflow-x: clip` on main
trims it without creating a scroll container, so the sticky header keeps
working. Measured at 1440, 1024 and 390 with 15px scrollbars forced: zero
overflow at each, header still sticky.

Also drops an unused hero-section class and an edgeLabelBackground theme
value that mermaid ignores for flowchart edge labels, which site.css was
already having to override.

* Stop the hero heading announcing itself twice

With the canvas inside the h1, the heading exposed the sentence once from
its visually hidden span and then again, out of order, from the diagram's
own node labels:

  heading "WYSIWYG editor renders native mermaid"
    text: WYSIWYG editor renders native mermaid
    document:
      paragraph: renders
      paragraph: WYSIWYG editor
      paragraph: native mermaid

The heading's textContent also picked up the whole stylesheet mermaid
injects into the svg, about 3KB of CSS, which anything reading the h1 as
text would have to wade through.

The heading is now the text and the canvas is its rendering, as siblings.
The canvas is hidden from assistive tech because it duplicates the heading
and its editing is pointer-only, so exposing it adds confusion without
adding a capability. Keyboard access to canvas editing does not exist in
the package today; that is unchanged by this and worth its own issue.

Verified: the heading's accessible name is now exactly the sentence with
nothing nested under it, its textContent is just that sentence, editing
still rewrites the source, the playground below stays untouched, and there
is still no horizontal overflow at 1440, 1024 or 390.

* Put a real headline in the served HTML, and drop PRODUCT.md

The served document body was `<div id="root"></div>`, so anything that does
not execute JavaScript saw no headline at all and the first paint was blank
until a 430KB gzipped bundle had run. That was true of the old text h1 too,
but the new headline is drawn by mermaid at runtime, so it is worth fixing
here rather than inheriting.

#root now ships the headline and subhead as ordinary markup, which React
replaces on mount. Vite emits the stylesheet as a real link and the bundle
as a deferred module, so it paints styled, in Inter on the site's cream,
positioned where the hero lands. It doubles as the fallback for the case
flagged in the PR: if the mermaid render ever fails while the rest of the
page works, this is what shows.

Verified: the built index.html contains the h1; with JavaScript disabled
the production build renders it styled and centred; after mount the boot
markup is gone and exactly one h1 remains, the visually hidden one.

Also removes PRODUCT.md. It was scaffolding for the design exploration and
was the only file of its kind in the monorepo, so it does not belong in a
change to the hero.

* Address review: config race, focus stop in aria-hidden, min-height

Three findings from review, all verified against the package source before
fixing.

Mermaid config race. `mermaid.initialize()` writes a module-global config
and `MermaidCanvasView.render()` called `mermaid.render()` without
re-asserting its own, so the last canvas to mount owned the config for the
whole page. The hero mounts first and lost every time: the first headline
edit re-rendered it with the demo canvas's theme and layout, and dark node
fills if the visitor had used the demo's dark toggle. Fixed in the package
rather than worked around at the call site, since any page with two
canvases hits it. Verified by toggling the demo to dark and then editing
the headline: node fill stays the site mint, where before it followed the
demo. The control confirms the toggle really does move the demo from
rgb(234,243,240) to rgb(38,34,27), so the test exercises the path.

Focus stop inside aria-hidden. The canvas host sets `tabIndex = 0`, so the
aria-hidden headline contained a focusable element, which is axe's
aria-hidden-focus rule and WCAG 4.1.2. A keyboard user got a tab stop that
announced nothing and did nothing, editing here being pointer-only. The
host is now taken out of the tab order at this call site. Verified: zero
focusable elements remain inside the subtree.

Canvas min-height. The React binding defaults its host to `min-height:
240`, which fights the absolute inset positioning: between 761 and 999px
the band is shorter than that, so the canvas outgrew its box and the
diagram drifted off centre toward the hint. My earlier verification ran
1440, 1024 and 390, which straddles that window exactly. Verified at 780,
860, 950 and 999: zero overshoot at each.

* Close the three remaining review suggestions

Breakpoint off-by-one. The stacked layout was chosen with `< 760` while
site.css sizes its band with `@media (max-width: 760px)`, which is
inclusive, so at exactly 760px the band went tall for a stacked diagram
while the source was still left-to-right. Both now agree, via a named
constant so the pairing is visible. Verified at the boundary: 759 and 760
are stacked in the 360px band, 761 is wide in the 210px band, no canvas
overshoot at any of them.

Static heading. Documented why the heading text deliberately does not track
edits to the diagram: rewriting a page heading under an assistive-tech user
as somebody types would churn the accessibility tree and the document
outline for a change only the editing visitor made, to their own local
copy. The live source is echoed in the hint line instead.

Stale comment. It still said the sentence was exposed "once from this span"
after that span became the h1 itself.

GitOrigin-RevId: 34c686f1043375b1016b7cde7e17bd5d767319a5
@inkeep-oss-sync
inkeep-oss-sync Bot merged commit 041e2df into main Aug 9, 2026
@inkeep-oss-sync
inkeep-oss-sync Bot deleted the copybara/sync branch August 9, 2026 19:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant