From f07ed4e4962f87589538a05f16d2c7a4e6378762 Mon Sep 17 00:00:00 2001 From: Masaaki Hirotsu Date: Fri, 15 May 2026 13:09:12 +0900 Subject: [PATCH 1/4] refactor(render-html): tighten initial fit padding Reduce the symmetric padding used by computeFit from 40px to 20px so the initial fit-to-screen scale is meaningfully larger on medium and large diagrams. The viewport already accounts for minimap, viewer controls, drawer and heading insets via getAvailableViewport, so a smaller fit padding avoids stacking margin on top of those overlays while keeping the diagram comfortably visible. --- crates/relune-render-html/src/js/pan_zoom.js | 2 +- crates/relune-render-html/ts/pan_zoom_state.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/relune-render-html/src/js/pan_zoom.js b/crates/relune-render-html/src/js/pan_zoom.js index 7f492d4..301af66 100644 --- a/crates/relune-render-html/src/js/pan_zoom.js +++ b/crates/relune-render-html/src/js/pan_zoom.js @@ -93,7 +93,7 @@ if (diagram.width <= 0 || diagram.height <= 0 || available.width <= 0 || available.height <= 0) { return null; } - const padding = 40; + const padding = 20; const scale = clamp( Math.min( (available.width - padding * 2) / diagram.width, diff --git a/crates/relune-render-html/ts/pan_zoom_state.ts b/crates/relune-render-html/ts/pan_zoom_state.ts index 77dc176..464f95d 100644 --- a/crates/relune-render-html/ts/pan_zoom_state.ts +++ b/crates/relune-render-html/ts/pan_zoom_state.ts @@ -69,7 +69,7 @@ export function computeFit( return null; } - const padding = 40; + const padding = 20; const scale = clamp( Math.min( (available.width - padding * 2) / diagram.width, From 5cf01cb35deda4372bba20366195759ce692fb68 Mon Sep 17 00:00:00 2001 From: Masaaki Hirotsu Date: Fri, 15 May 2026 13:22:37 +0900 Subject: [PATCH 2/4] feat(render-html): add minimap visibility toggle Add a viewer-controls button and an "M" keyboard shortcut that toggle the minimap shell's hidden state. The toggle exposes a new runtime.minimap API, emits relune:minimap-toggled, and is persisted in the URL hash via the mh parameter so shared links retain the chosen minimap visibility. Toggling also re-fits the diagram so the freed viewport area is used immediately, addressing the "diagram looks too small" feedback when the minimap overlay is not needed. --- ...udit__fixture_render_audit__cyclic_fk.snap | 2 +- ...udit__fixture_render_audit__ecommerce.snap | 2 +- ...dit__fixture_render_audit__join_heavy.snap | 2 +- ...t__fixture_render_audit__multi_schema.snap | 2 +- ...it__fixture_render_audit__simple_blog.snap | 2 +- crates/relune-render-html/src/components.rs | 1 + crates/relune-render-html/src/css.rs | 8 +++ crates/relune-render-html/src/html.rs | 4 ++ crates/relune-render-html/src/js/minimap.js | 65 ++++++++++++++++++- crates/relune-render-html/src/js/shortcuts.js | 11 ++++ crates/relune-render-html/src/js/url_state.js | 9 +++ crates/relune-render-html/ts/minimap.ts | 40 +++++++++++- crates/relune-render-html/ts/shortcuts.ts | 13 ++++ crates/relune-render-html/ts/url_state.ts | 12 ++++ crates/relune-render-html/ts/viewer_api.ts | 15 ++++- 15 files changed, 179 insertions(+), 9 deletions(-) diff --git a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__cyclic_fk.snap b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__cyclic_fk.snap index c994e82..2a34068 100644 --- a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__cyclic_fk.snap +++ b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__cyclic_fk.snap @@ -53,7 +53,7 @@ expression: "fixture_audit_snapshot(\"cyclic_fk.sql\")" }, "surfaces": { "html": { - "bytes": 453018, + "bytes": 456629, "contains_embedded_svg": true, "contains_metadata": true, "contains_viewport": true diff --git a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__ecommerce.snap b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__ecommerce.snap index 2af19a0..a72a0db 100644 --- a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__ecommerce.snap +++ b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__ecommerce.snap @@ -49,7 +49,7 @@ expression: "fixture_audit_snapshot(\"ecommerce.sql\")" }, "surfaces": { "html": { - "bytes": 426912, + "bytes": 430523, "contains_embedded_svg": true, "contains_metadata": true, "contains_viewport": true diff --git a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__join_heavy.snap b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__join_heavy.snap index 881951d..2c12979 100644 --- a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__join_heavy.snap +++ b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__join_heavy.snap @@ -53,7 +53,7 @@ expression: "fixture_audit_snapshot(\"join_heavy.sql\")" }, "surfaces": { "html": { - "bytes": 608344, + "bytes": 611955, "contains_embedded_svg": true, "contains_metadata": true, "contains_viewport": true diff --git a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__multi_schema.snap b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__multi_schema.snap index a2ec6a8..630c334 100644 --- a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__multi_schema.snap +++ b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__multi_schema.snap @@ -47,7 +47,7 @@ expression: "fixture_audit_snapshot(\"multi_schema.sql\")" }, "surfaces": { "html": { - "bytes": 419939, + "bytes": 423550, "contains_embedded_svg": true, "contains_metadata": true, "contains_viewport": true diff --git a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__simple_blog.snap b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__simple_blog.snap index 18f5523..81f9ec5 100644 --- a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__simple_blog.snap +++ b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__simple_blog.snap @@ -47,7 +47,7 @@ expression: "fixture_audit_snapshot(\"simple_blog.sql\")" }, "surfaces": { "html": { - "bytes": 380109, + "bytes": 383720, "contains_embedded_svg": true, "contains_metadata": true, "contains_viewport": true diff --git a/crates/relune-render-html/src/components.rs b/crates/relune-render-html/src/components.rs index 2168c87..05e0623 100644 --- a/crates/relune-render-html/src/components.rs +++ b/crates/relune-render-html/src/components.rs @@ -87,6 +87,7 @@ pub(crate) fn build_viewer_controls_html() -> String { 100% +
diff --git a/crates/relune-render-html/src/css.rs b/crates/relune-render-html/src/css.rs index a7508eb..b67bf81 100644 --- a/crates/relune-render-html/src/css.rs +++ b/crates/relune-render-html/src/css.rs @@ -982,6 +982,14 @@ pub(crate) fn build_css( background: color-mix(in srgb, var(--panel-bg) 82%, var(--accent-soft)); } + .viewer-control-button[aria-pressed=false] { + opacity: 0.55; + } + + .viewer-control-button[aria-pressed=false]:hover { + opacity: 1; + } + .minimap-shell { position: fixed; right: 12px; diff --git a/crates/relune-render-html/src/html.rs b/crates/relune-render-html/src/html.rs index 4c7c72c..8cf61f1 100644 --- a/crates/relune-render-html/src/html.rs +++ b/crates/relune-render-html/src/html.rs @@ -585,6 +585,10 @@ mod tests { assert!(html.contains(r#"id="zoom-out""#)); assert!(html.contains(r#"id="zoom-level""#)); assert!(html.contains(r#"id="zoom-fit""#)); + assert!(html.contains(r#"id="minimap-toggle""#)); + assert!(html.contains(r#"aria-pressed="true""#)); + assert!(html.contains(r#"aria-label="Toggle minimap""#)); + assert!(html.contains(r#"aria-controls="minimap-shell""#)); assert!(html.contains(r#"id="minimap""#)); // Verify SVG icons replaced text labels assert!(html.contains(" { // ts/viewer_api.ts var VIEWER_RUNTIME_KEY = /* @__PURE__ */ Symbol.for("relune.viewer.runtime"); + var VIEWER_READY_MODULES_KEY = /* @__PURE__ */ Symbol.for("relune.viewer.ready_modules"); + var VIEWER_WAITERS_KEY = /* @__PURE__ */ Symbol.for("relune.viewer.waiters"); function getViewerRuntime() { const viewerWindow = window; if (viewerWindow[VIEWER_RUNTIME_KEY] === void 0) { @@ -9,9 +11,71 @@ } return viewerWindow[VIEWER_RUNTIME_KEY]; } + function readyModules() { + const viewerWindow = window; + if (viewerWindow[VIEWER_READY_MODULES_KEY] === void 0) { + viewerWindow[VIEWER_READY_MODULES_KEY] = /* @__PURE__ */ new Set(); + } + return viewerWindow[VIEWER_READY_MODULES_KEY]; + } + function runtimeWaiters() { + const viewerWindow = window; + if (viewerWindow[VIEWER_WAITERS_KEY] === void 0) { + viewerWindow[VIEWER_WAITERS_KEY] = []; + } + return viewerWindow[VIEWER_WAITERS_KEY]; + } + function markViewerModuleReady(module) { + readyModules().add(module); + flushViewerWaiters(); + } + function flushViewerWaiters() { + const ready = readyModules(); + const remaining = []; + for (const waiter of runtimeWaiters()) { + if (Array.from(waiter.modules).every((module) => ready.has(module))) { + waiter.callback(); + } else { + remaining.push(waiter); + } + } + const viewerWindow = window; + viewerWindow[VIEWER_WAITERS_KEY] = remaining; + } + function emitViewerEvent(name, detail) { + document.dispatchEvent(new CustomEvent(name, { detail })); + } // ts/minimap.ts { + const runtime = getViewerRuntime(); + const minimapShell = document.getElementById("minimap-shell"); + const minimapToggleBtn = document.getElementById("minimap-toggle"); + if (minimapShell instanceof HTMLElement) { + const isHidden = () => minimapShell.hasAttribute("hidden"); + const setHidden = (hidden) => { + const changed = isHidden() !== hidden; + if (hidden) { + minimapShell.setAttribute("hidden", ""); + } else { + minimapShell.removeAttribute("hidden"); + } + if (minimapToggleBtn instanceof HTMLButtonElement) { + minimapToggleBtn.setAttribute("aria-pressed", String(!hidden)); + } + if (changed) { + emitViewerEvent("relune:minimap-toggled", { hidden }); + } + }; + runtime.minimap = { isHidden, setHidden }; + markViewerModuleReady("minimap"); + if (minimapToggleBtn instanceof HTMLButtonElement) { + minimapToggleBtn.addEventListener("click", () => { + setHidden(!isHidden()); + runtime.viewport?.fit(); + }); + } + } const host = document.getElementById("minimap"); const svgRoot = document.querySelector(".canvas svg"); if (!(host instanceof SVGSVGElement) || svgRoot === null) { @@ -37,7 +101,6 @@ runtime.viewport?.center(contentX, contentY); }; updateFrame2 = updateFrame, focusPoint2 = focusPoint; - const runtime = getViewerRuntime(); const hostSvg = host; hostSvg.innerHTML = ""; const frame = document.createElementNS("http://www.w3.org/2000/svg", "rect"); diff --git a/crates/relune-render-html/src/js/shortcuts.js b/crates/relune-render-html/src/js/shortcuts.js index f065efc..6910d00 100644 --- a/crates/relune-render-html/src/js/shortcuts.js +++ b/crates/relune-render-html/src/js/shortcuts.js @@ -46,6 +46,17 @@ event.preventDefault(); document.getElementById("group-panel-collapse")?.dispatchEvent(new MouseEvent("click")); break; + case "m": + case "M": + if (event.ctrlKey || event.metaKey || event.altKey) { + break; + } + event.preventDefault(); + if (runtime.minimap !== void 0) { + runtime.minimap.setHidden(!runtime.minimap.isHidden()); + runtime.viewport?.fit(); + } + break; case "+": case "=": event.preventDefault(); diff --git a/crates/relune-render-html/src/js/url_state.js b/crates/relune-render-html/src/js/url_state.js index eef404f..2da88bd 100644 --- a/crates/relune-render-html/src/js/url_state.js +++ b/crates/relune-render-html/src/js/url_state.js @@ -124,6 +124,9 @@ if (collapsed.length > 0) { params.set(PARAM_COLLAPSED, collapsed.join(",")); } + if (runtime.minimap?.isHidden() === true) { + params.set(PARAM_MINIMAP_HIDDEN, "1"); + } return params; }, writeHash = function() { const str = buildHashParams().toString(); @@ -142,6 +145,7 @@ pendingPush = false; }, restoreFromHash = function() { const params = readHash(); + runtime.minimap?.setHidden(params.get(PARAM_MINIMAP_HIDDEN) === "1"); if (params.toString() === "") { return; } @@ -211,6 +215,9 @@ if (document.getElementById("canvas")?.querySelector("svg") !== null) { modules.push("collapse"); } + if (document.getElementById("minimap-shell") !== null) { + modules.push("minimap"); + } return modules; }; readHash2 = readHash, maxViewportPanMagnitude2 = maxViewportPanMagnitude, hasValidViewportState2 = hasValidViewportState, matchesMetadataSearch2 = matchesMetadataSearch, hasMetadataSearchMatch2 = hasMetadataSearchMatch, scheduleWrite2 = scheduleWrite, scheduleDiscreteWrite2 = scheduleDiscreteWrite, buildHashParams2 = buildHashParams, writeHash2 = writeHash, restoreFromHash2 = restoreFromHash, expectedViewerModules2 = expectedViewerModules; @@ -231,6 +238,7 @@ const PARAM_FILTER_MODE = "fm"; const PARAM_HIDDEN_GROUPS = "hg"; const PARAM_COLLAPSED = "c"; + const PARAM_MINIMAP_HIDDEN = "mh"; const FACET_PARAMS = [ { param: PARAM_FILTER_SCHEMA, facetId: "schema" }, { param: PARAM_FILTER_KIND, facetId: "kind" }, @@ -251,6 +259,7 @@ document.addEventListener("relune:filters-changed", scheduleDiscreteWrite); document.addEventListener("relune:groups-changed", scheduleDiscreteWrite); document.addEventListener("relune:collapse-changed", scheduleDiscreteWrite); + document.addEventListener("relune:minimap-toggled", scheduleDiscreteWrite); window.addEventListener("popstate", () => { restoringFromPopstate = true; restoreFromHash(); diff --git a/crates/relune-render-html/ts/minimap.ts b/crates/relune-render-html/ts/minimap.ts index 73ce765..dfaa5dd 100644 --- a/crates/relune-render-html/ts/minimap.ts +++ b/crates/relune-render-html/ts/minimap.ts @@ -1,4 +1,10 @@ -import { getViewerRuntime, type DiagramBounds, type ViewportState } from './viewer_api'; +import { + emitViewerEvent, + getViewerRuntime, + markViewerModuleReady, + type DiagramBounds, + type ViewportState, +} from './viewer_api'; interface MinimapNode { id: string; @@ -9,12 +15,42 @@ interface MinimapNode { } { + const runtime = getViewerRuntime(); + const minimapShell = document.getElementById('minimap-shell'); + const minimapToggleBtn = document.getElementById('minimap-toggle'); + + if (minimapShell instanceof HTMLElement) { + const isHidden = (): boolean => minimapShell.hasAttribute('hidden'); + const setHidden = (hidden: boolean): void => { + const changed = isHidden() !== hidden; + if (hidden) { + minimapShell.setAttribute('hidden', ''); + } else { + minimapShell.removeAttribute('hidden'); + } + if (minimapToggleBtn instanceof HTMLButtonElement) { + minimapToggleBtn.setAttribute('aria-pressed', String(!hidden)); + } + if (changed) { + emitViewerEvent('relune:minimap-toggled', { hidden }); + } + }; + runtime.minimap = { isHidden, setHidden }; + markViewerModuleReady('minimap'); + + if (minimapToggleBtn instanceof HTMLButtonElement) { + minimapToggleBtn.addEventListener('click', () => { + setHidden(!isHidden()); + runtime.viewport?.fit(); + }); + } + } + const host = document.getElementById('minimap'); const svgRoot = document.querySelector('.canvas svg'); if (!(host instanceof SVGSVGElement) || svgRoot === null) { // Minimap host or source SVG not available. } else { - const runtime = getViewerRuntime(); const hostSvg = host; hostSvg.innerHTML = ''; diff --git a/crates/relune-render-html/ts/shortcuts.ts b/crates/relune-render-html/ts/shortcuts.ts index 7fd7ab8..322fda2 100644 --- a/crates/relune-render-html/ts/shortcuts.ts +++ b/crates/relune-render-html/ts/shortcuts.ts @@ -31,6 +31,19 @@ import { getViewerRuntime, isEditableTarget } from './viewer_api'; event.preventDefault(); document.getElementById('group-panel-collapse')?.dispatchEvent(new MouseEvent('click')); break; + case 'm': + case 'M': + // Skip when a modifier is held (Cmd+M, Ctrl+M, Alt+M) so we don't + // shadow OS- or browser-owned shortcuts. + if (event.ctrlKey || event.metaKey || event.altKey) { + break; + } + event.preventDefault(); + if (runtime.minimap !== undefined) { + runtime.minimap.setHidden(!runtime.minimap.isHidden()); + runtime.viewport?.fit(); + } + break; case '+': case '=': event.preventDefault(); diff --git a/crates/relune-render-html/ts/url_state.ts b/crates/relune-render-html/ts/url_state.ts index 4c44e3a..1259275 100644 --- a/crates/relune-render-html/ts/url_state.ts +++ b/crates/relune-render-html/ts/url_state.ts @@ -20,6 +20,7 @@ import { getViewerRuntime, waitForViewerModules, type ViewerModule } from './vie const PARAM_FILTER_MODE = 'fm'; const PARAM_HIDDEN_GROUPS = 'hg'; const PARAM_COLLAPSED = 'c'; + const PARAM_MINIMAP_HIDDEN = 'mh'; type FacetUrlParam = { param: string; facetId: string }; const FACET_PARAMS: FacetUrlParam[] = [ @@ -147,6 +148,10 @@ import { getViewerRuntime, waitForViewerModules, type ViewerModule } from './vie params.set(PARAM_COLLAPSED, collapsed.join(',')); } + if (runtime.minimap?.isHidden() === true) { + params.set(PARAM_MINIMAP_HIDDEN, '1'); + } + return params; } @@ -174,6 +179,9 @@ import { getViewerRuntime, waitForViewerModules, type ViewerModule } from './vie function restoreFromHash(): void { const params = readHash(); + // Sync minimap visibility unconditionally so popstate back to a clean hash + // restores the visible default instead of leaving it stuck hidden. + runtime.minimap?.setHidden(params.get(PARAM_MINIMAP_HIDDEN) === '1'); if (params.toString() === '') { return; } @@ -259,6 +267,9 @@ import { getViewerRuntime, waitForViewerModules, type ViewerModule } from './vie if (document.getElementById('canvas')?.querySelector('svg') !== null) { modules.push('collapse'); } + if (document.getElementById('minimap-shell') !== null) { + modules.push('minimap'); + } return modules; } @@ -273,6 +284,7 @@ import { getViewerRuntime, waitForViewerModules, type ViewerModule } from './vie document.addEventListener('relune:filters-changed', scheduleDiscreteWrite); document.addEventListener('relune:groups-changed', scheduleDiscreteWrite); document.addEventListener('relune:collapse-changed', scheduleDiscreteWrite); + document.addEventListener('relune:minimap-toggled', scheduleDiscreteWrite); // --------------------------------------------------------------------------- // popstate: re-apply state when the user navigates back/forward or edits hash diff --git a/crates/relune-render-html/ts/viewer_api.ts b/crates/relune-render-html/ts/viewer_api.ts index 99a62cc..29a9c43 100644 --- a/crates/relune-render-html/ts/viewer_api.ts +++ b/crates/relune-render-html/ts/viewer_api.ts @@ -63,6 +63,11 @@ export interface ViewerCollapseApi { setCollapsed(tableIds: string[]): void; } +export interface ViewerMinimapApi { + isHidden(): boolean; + setHidden(hidden: boolean): void; +} + export interface ViewerRuntime { viewport?: ViewerViewportApi; filters?: ViewerFiltersApi; @@ -70,9 +75,17 @@ export interface ViewerRuntime { selection?: ViewerSelectionApi; groups?: ViewerGroupsApi; collapse?: ViewerCollapseApi; + minimap?: ViewerMinimapApi; } -export type ViewerModule = 'viewport' | 'filters' | 'search' | 'selection' | 'groups' | 'collapse'; +export type ViewerModule = + | 'viewport' + | 'filters' + | 'search' + | 'selection' + | 'groups' + | 'collapse' + | 'minimap'; type RuntimeWaiter = { modules: Set; From 08f1ab00258c61304ac2b8efd3c87ff505353621 Mon Sep 17 00:00:00 2001 From: Masaaki Hirotsu Date: Sat, 16 May 2026 10:13:14 +0900 Subject: [PATCH 3/4] feat(render-html): hide minimap by default to enlarge initial fit The minimap shell reserves ~180px of vertical bottom inset in getAvailableViewport, which left the initial fit scale uncomfortably small on common laptop viewports (e.g. 33% on 14" MacBook for the custom playground fixture). Start the viewer with the minimap hidden; users can reveal it via the toolbar toggle or the `M` shortcut, and the button's title/aria-label flips to "Show minimap (M)" / "Hide minimap (M)" so the interaction is discoverable. Persist visibility via `mv=1` in the hash (replacing the previous `mh=1` since the default flipped). --- ..._render_audit__fixture_render_audit__cyclic_fk.snap | 2 +- ..._render_audit__fixture_render_audit__ecommerce.snap | 2 +- ...render_audit__fixture_render_audit__join_heavy.snap | 2 +- ...nder_audit__fixture_render_audit__multi_schema.snap | 2 +- ...ender_audit__fixture_render_audit__simple_blog.snap | 2 +- crates/relune-render-html/src/components.rs | 4 ++-- crates/relune-render-html/src/html.rs | 7 +++++-- crates/relune-render-html/src/js/minimap.js | 3 +++ crates/relune-render-html/src/js/url_state.js | 8 ++++---- crates/relune-render-html/ts/minimap.ts | 3 +++ crates/relune-render-html/ts/url_state.ts | 10 +++++----- 11 files changed, 27 insertions(+), 18 deletions(-) diff --git a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__cyclic_fk.snap b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__cyclic_fk.snap index 2a34068..45aee3f 100644 --- a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__cyclic_fk.snap +++ b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__cyclic_fk.snap @@ -53,7 +53,7 @@ expression: "fixture_audit_snapshot(\"cyclic_fk.sql\")" }, "surfaces": { "html": { - "bytes": 456629, + "bytes": 456831, "contains_embedded_svg": true, "contains_metadata": true, "contains_viewport": true diff --git a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__ecommerce.snap b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__ecommerce.snap index a72a0db..79c135c 100644 --- a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__ecommerce.snap +++ b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__ecommerce.snap @@ -49,7 +49,7 @@ expression: "fixture_audit_snapshot(\"ecommerce.sql\")" }, "surfaces": { "html": { - "bytes": 430523, + "bytes": 430725, "contains_embedded_svg": true, "contains_metadata": true, "contains_viewport": true diff --git a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__join_heavy.snap b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__join_heavy.snap index 2c12979..7fb1894 100644 --- a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__join_heavy.snap +++ b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__join_heavy.snap @@ -53,7 +53,7 @@ expression: "fixture_audit_snapshot(\"join_heavy.sql\")" }, "surfaces": { "html": { - "bytes": 611955, + "bytes": 612157, "contains_embedded_svg": true, "contains_metadata": true, "contains_viewport": true diff --git a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__multi_schema.snap b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__multi_schema.snap index 630c334..a8f7b3f 100644 --- a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__multi_schema.snap +++ b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__multi_schema.snap @@ -47,7 +47,7 @@ expression: "fixture_audit_snapshot(\"multi_schema.sql\")" }, "surfaces": { "html": { - "bytes": 423550, + "bytes": 423752, "contains_embedded_svg": true, "contains_metadata": true, "contains_viewport": true diff --git a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__simple_blog.snap b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__simple_blog.snap index 81f9ec5..3f22846 100644 --- a/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__simple_blog.snap +++ b/crates/relune-app/tests/snapshots/fixture_render_audit__fixture_render_audit__simple_blog.snap @@ -47,7 +47,7 @@ expression: "fixture_audit_snapshot(\"simple_blog.sql\")" }, "surfaces": { "html": { - "bytes": 383720, + "bytes": 383922, "contains_embedded_svg": true, "contains_metadata": true, "contains_viewport": true diff --git a/crates/relune-render-html/src/components.rs b/crates/relune-render-html/src/components.rs index 05e0623..5c908a9 100644 --- a/crates/relune-render-html/src/components.rs +++ b/crates/relune-render-html/src/components.rs @@ -87,9 +87,9 @@ pub(crate) fn build_viewer_controls_html() -> String { 100% - +
-
+