Fullscreen overlay for mermaid diagrams #8
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fullscreen-mermaid-diagrams"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Closes #7
Changes
app/javascript/controllers/mermaid_controller.js: inject fullscreen button per diagram,openFullscreen()clones SVG into overlay and strips mermaid's hardcoded dimensionsapp/assets/stylesheets/application.css: styles for.mermaid-fullscreen-btn(hover-reveal),.mermaid-overlay(solid gruvbox bg),.mermaid-overlay-content svg(viewport-scaled)Test Plan
Review Checklist
Related Notes
ldraney/mdview #7-- Mermaid diagrams too small on 4K displaysPR #8 Review
DOMAIN REVIEW
Tech stack: Rails 8 + Stimulus + Importmap + CSS (Gruvbox dark theme). Two files changed:
app/assets/stylesheets/application.css(CSS) andapp/javascript/controllers/mermaid_controller.js(Stimulus controller). 115 additions, 0 deletions.Stimulus / JavaScript
Escape listener leak on overlay.remove() -- The
onEscapehandler is cleaned up when Escape is pressed, but NOT when the overlay is dismissed via the close button or backdrop click. Both of those paths calloverlay.remove()withoutdocument.removeEventListener("keydown", onEscape). This leaves an orphaned global keydown listener that will throw (or silently fail) on next Escape press sinceoverlayis already detached. Fix: extract adismiss()closure that both removes the overlay and removes the listener, then use it in all three dismiss paths.innerHTML for SVG injection (line 35) --
content.innerHTML = diagramContainer.querySelector("svg").outerHTMLworks but is the brute-force path. Since the source is mermaid-generated SVG (not user input), this is not a security issue here, butcloneNode(true)would be cleaner and avoid a serialize-then-parse round-trip. Minor point -- not a blocker.No guard if SVG is missing --
diagramContainer.querySelector("svg")on line 35 will throw a null-reference error if the mermaid render failed and no SVG exists in the container. A null check before accessing.outerHTMLwould be defensive.Button innerHTML is a long inline SVG string (line 21) -- Readable enough for a single icon, but if more icons are added later this pattern will degrade. Acceptable for now.
CSS
Consistent use of design tokens -- Good. The overlay styles use
var(--color-bg),var(--color-muted),var(--color-text),var(--color-border),var(--radius), andvar(--spacing-sm). Theme-aligned.Hardcoded values --
width: 32px; height: 32pxon.mermaid-fullscreen-btn,padding: 2remon.mermaid-overlay,top: 1rem; right: 1.5remandfont-size: 2remon.mermaid-overlay-close. These are not pulled from design tokens. Not blocking since the existing codebase uses similar mixed approaches (e.g.,border-radius: 3pxon inline code), but worth noting for consistency.z-index: 9999 / 10000 -- Works but magic numbers. No z-index scale exists in the codebase currently, so this is consistent with the project's maturity level.
Accessibility -- Good: both buttons have
aria-labelattributes. The hover-reveal pattern (opacity: 0on the button until parent hover) means the button is invisible but still focusable via keyboard. Sinceopacity: 0does not prevent focus, a keyboard user tabbing through the page will land on an invisible button. Consider adding:focus-withinto the.mermaid-diagramselector to reveal the button on keyboard focus too:Focus trap -- The fullscreen overlay does not trap focus. A screen reader or keyboard user could tab behind the overlay to page content. For a dismiss-on-Escape overlay this is low severity but worth noting.
BLOCKERS
None. This is a pure UI enhancement (CSS + client-side JS). No auth paths, no user input processing, no server-side changes, no credentials.
Regarding the "no tests" blocker criterion: this project has no test infrastructure at all (no
test/orspec/directory, no JS test runner configured, no system test setup in Gemfile). The PR is a client-side visual interaction (hover button + fullscreen overlay) that is inherently difficult to unit test without a browser test harness. The test plan in the PR body covers manual verification. Requiring automated tests here when the project has zero test infrastructure would be scope creep beyond this PR. Not a blocker for this PR, but the project should stand up at least system-level tests (Capybara/Selenium or Playwright) before the codebase grows further.NITS
Event listener leak (item 1 above) -- This is the most important fix. Not a blocker because it is a minor memory/behavior leak, not a security or data issue, but it should be addressed.
Null guard on SVG query (item 3) -- Defensive coding. One-liner fix.
Keyboard accessibility for the expand button (item 8) -- Add
:focus-withinrule so keyboard users can see the button.Focus trap on overlay (item 9) -- Low priority, but good practice.
cloneNode over innerHTML (item 2) -- Cleaner but not required.
SOP COMPLIANCE
fullscreen-mermaid-diagrams. Convention is{issue-number}-{kebab-case-purpose}, so it should be7-fullscreen-mermaid-diagrams. Missing the issue number prefix.ldraney/mdview #7which is the issue, not a plan. Noted as N/A since caller confirmed no plan slug.PROCESS OBSERVATIONS
VERDICT: APPROVED
The code is clean, well-structured, uses the existing design token system appropriately, and has good accessibility basics (aria-labels). The event listener leak (nit 1) and branch naming (SOP) are worth fixing but neither rises to blocker level for a UI-only enhancement in a project at this maturity stage.