From 5538b35116bf5392cabe2cd68bdbc3cf3d09cc9a Mon Sep 17 00:00:00 2001 From: Cathryn Lavery <50469282+cathrynlavery@users.noreply.github.com> Date: Thu, 20 Aug 2026 12:42:26 -0700 Subject: [PATCH] fix(gallery): preserve mobile preview height (#135) * fix(gallery): preserve mobile preview height * test(gallery): report routing failures directly --- .claude-plugin/plugin.json | 2 +- .codex-plugin/plugin.json | 2 +- .factory-plugin/plugin.json | 2 +- scripts/lint-render.py | 66 +++++++++++++++++++++++++ skills/diagram-design/assets/index.html | 13 +++++ 5 files changed, 82 insertions(+), 3 deletions(-) diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 3f41ba9..f048e26 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "diagram-design", "description": "Create branded architecture, IT current-state, flowchart, sequence, state machine, ER/data model, timeline, swimlane, quadrant, radar/spider, polar chart (polar/radial lollipop), loop/flywheel, nested, tree, org chart, layer stack, Venn, pyramid/funnel, treemap, bar, line, Gantt and scatter charts, high-level, process, medallion, data flow, DP integration, DP security matrix, sankey, fishbone, Wardley map, kanban, user journey, deployment, dependency graph, UML class, story map, or database schema diagrams as standalone HTML/SVG/PNG. Redraw .drawio/.drawio.png/.drawio.svg or Mermaid .mmd sources at a chosen size/detail; onboard brand tokens from a website; add semantic patterns, callouts, accessible motion, or sketchy/hand-drawn styling.", - "version": "2.6.0", + "version": "2.6.1", "author": { "name": "Cathryn Lavery", "url": "https://github.com/cathrynlavery" diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 8ef7cbf..678303d 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "diagram-design", "description": "Create branded architecture, IT current-state, flowchart, sequence, state machine, ER/data model, timeline, swimlane, quadrant, radar/spider, polar chart (polar/radial lollipop), loop/flywheel, nested, tree, org chart, layer stack, Venn, pyramid/funnel, treemap, bar, line, Gantt and scatter charts, high-level, process, medallion, data flow, DP integration, DP security matrix, sankey, fishbone, Wardley map, kanban, user journey, deployment, dependency graph, UML class, story map, or database schema diagrams as standalone HTML/SVG/PNG. Redraw .drawio/.drawio.png/.drawio.svg or Mermaid .mmd sources at a chosen size/detail; onboard brand tokens from a website; add semantic patterns, callouts, accessible motion, or sketchy/hand-drawn styling.", - "version": "2.6.0", + "version": "2.6.1", "author": { "name": "Cathryn Lavery", "url": "https://github.com/cathrynlavery" diff --git a/.factory-plugin/plugin.json b/.factory-plugin/plugin.json index 3f41ba9..f048e26 100644 --- a/.factory-plugin/plugin.json +++ b/.factory-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "diagram-design", "description": "Create branded architecture, IT current-state, flowchart, sequence, state machine, ER/data model, timeline, swimlane, quadrant, radar/spider, polar chart (polar/radial lollipop), loop/flywheel, nested, tree, org chart, layer stack, Venn, pyramid/funnel, treemap, bar, line, Gantt and scatter charts, high-level, process, medallion, data flow, DP integration, DP security matrix, sankey, fishbone, Wardley map, kanban, user journey, deployment, dependency graph, UML class, story map, or database schema diagrams as standalone HTML/SVG/PNG. Redraw .drawio/.drawio.png/.drawio.svg or Mermaid .mmd sources at a chosen size/detail; onboard brand tokens from a website; add semantic patterns, callouts, accessible motion, or sketchy/hand-drawn styling.", - "version": "2.6.0", + "version": "2.6.1", "author": { "name": "Cathryn Lavery", "url": "https://github.com/cathrynlavery" diff --git a/scripts/lint-render.py b/scripts/lint-render.py index c244c2d..c8f7713 100755 --- a/scripts/lint-render.py +++ b/scripts/lint-render.py @@ -667,6 +667,49 @@ def network_isolation_failures(context): return [] +def gallery_mobile_failures(context, gallery_path=None): + """Keep the wrapped gallery controls from collapsing its mobile preview.""" + gallery_path = gallery_path or ASSET_DIR / "index.html" + failures = [] + page = context.new_page() + page.set_viewport_size({"width": 390, "height": 844}) + try: + page.goto(gallery_path.as_uri(), wait_until="load") + page.locator('[data-type="polar"]').click() + routed_source = page.locator("#preview").get_attribute("src") + if routed_source != "example-polar.html": + failures.append( + "gallery-mobile-routing: Polar routed to " + f"{routed_source!r}, expected 'example-polar.html'" + ) + facts = page.evaluate( + """ + () => { + const doc = document.documentElement; + const preview = document.querySelector('#preview'); + const rect = preview.getBoundingClientRect(); + return { + previewHeight: rect.height, + pageOverflow: doc.scrollWidth - doc.clientWidth, + }; + } + """ + ) + if facts["previewHeight"] < 400: + failures.append( + "gallery-mobile-preview: iframe height " + f"{facts['previewHeight']:.1f}px is below the 400px minimum" + ) + if facts["pageOverflow"] > TOLERANCE: + failures.append( + "gallery-mobile-overflow: page extends " + f"{facts['pageOverflow']:.1f}px past the mobile viewport" + ) + finally: + page.close() + return failures + + def self_test(context): page = context.new_page() failures = [] @@ -736,6 +779,29 @@ def self_test(context): checks += 1 failures += network_isolation_failures(context) + checks += 1 + failures += gallery_mobile_failures(context) + + # A broken route should be a targeted failure, not a delayed Playwright + # timeout or traceback that escapes the self-test report. + checks += 1 + with tempfile.TemporaryDirectory() as directory: + broken_gallery = Path(directory) / "index.html" + gallery_source = (ASSET_DIR / "index.html").read_text(encoding="utf-8") + route_line = "const src = `example-${state.type}${state.variant}.html`;" + if gallery_source.count(route_line) != 1: + failures.append("gallery-mobile-routing-fixture: route source changed unexpectedly") + else: + broken_gallery.write_text( + gallery_source.replace(route_line, 'const src = "wrong-example.html";'), + encoding="utf-8", + ) + route_failures = gallery_mobile_failures(context, broken_gallery) + if not any( + failure.startswith("gallery-mobile-routing:") for failure in route_failures + ): + failures.append("gallery-mobile-routing: broken route was not reported") + if failures: print("self-test FAILED:") for failure in failures: diff --git a/skills/diagram-design/assets/index.html b/skills/diagram-design/assets/index.html index afdb58d..d36182f 100644 --- a/skills/diagram-design/assets/index.html +++ b/skills/diagram-design/assets/index.html @@ -162,6 +162,19 @@ background: var(--paper); display: block; } + + @media (max-width: 640px) { + #type-tabs { + flex-wrap: nowrap; + overflow-x: auto; + overscroll-behavior-inline: contain; + padding-bottom: 0.25rem; + scrollbar-width: thin; + } + #type-tabs .tab { + flex: 0 0 auto; + } + }