From e49883dc263247d9815b97636533e4a1909f0521 Mon Sep 17 00:00:00 2001 From: devkyato Date: Mon, 20 Jul 2026 10:56:55 +0800 Subject: [PATCH] Improve mobile editor usability --- index.html | 2 ++ style.css | 35 +++++++++++++++++++++++++++++------ tests/browser-smoke.mjs | 10 ++++++++++ 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/index.html b/index.html index 7d0fe59..9c26a91 100644 --- a/index.html +++ b/index.html @@ -77,6 +77,7 @@
+
diff --git a/style.css b/style.css index 52ae5a5..fbe7ac1 100644 --- a/style.css +++ b/style.css @@ -165,6 +165,7 @@ button.active { color: var(--accent-strong); background: var(--accent-soft); bor .document-title:hover, .document-title:focus { border-color: var(--border); } .toolbar-separator { width: 1px; height: 24px; margin: 0 2px; background: var(--border); } .toolbar-spacer { flex: 1; min-width: 4px; } +.toolbar-actions { display: flex; align-items: center; gap: 4px; min-width: 0; } .tool-group { display: flex; align-items: center; gap: 1px; } .toolbar button { font-size: 12px; } .toolbar .dropdown { position: relative; } @@ -588,7 +589,7 @@ kbd { padding: 3px 7px; color: var(--text); background: var(--panel-active); bor @media (max-width: 840px) { :root { --toolbar-height: 84px; } #app { grid-template-columns: 1fr; grid-template-rows: var(--toolbar-height) 82px minmax(0, 1fr) 25px; } - .toolbar { align-content: center; flex-wrap: wrap; overflow: hidden; } + .toolbar { align-content: center; flex-wrap: wrap; overflow: visible; } .document-title { width: 155px; } .toolbar-spacer { display: none; } .shape-panel { grid-column: 1; grid-row: 2; border-right: 0; border-bottom: 1px solid var(--border); overflow-x: auto; overflow-y: hidden; } @@ -603,13 +604,35 @@ kbd { padding: 3px 7px; color: var(--text); background: var(--panel-active); bor } @media (max-width: 540px) { - :root { --toolbar-height: 116px; } - .toolbar { align-items: flex-start; padding: 5px; } + :root { --toolbar-height: 118px; } + .toolbar { + display: grid; + grid-template-columns: auto minmax(0, 1fr) auto; + grid-template-rows: 32px 36px 32px; + align-items: center; + gap: 3px 5px; + padding: 5px; + } .toolbar button { font-size: 11px; } - .document-title { flex: 1; min-width: 140px; } - .brand-mark span:last-child, .theme-toggle span { display: none; } + .brand-mark { grid-column: 1; grid-row: 1; } + .document-title { grid-column: 2; grid-row: 1; width: 100%; min-width: 0; } + .toolbar > .tool-group:not(.tool-pills) { grid-column: 3; grid-row: 1; } + .tool-pills { grid-column: 1 / -1; grid-row: 2; width: 100%; } + .tool-pills button { flex: 1 1 0; min-width: 0; min-height: 32px; padding-inline: 4px; } + .toolbar-actions { + display: grid; + grid-column: 1 / -1; + grid-row: 3; + grid-template-columns: 1fr 1fr .72fr 32px 32px 32px; + gap: 2px; + width: 100%; + } + .toolbar-actions > * { min-width: 0; } + .toolbar-actions .dropdown-toggle { width: 100%; min-height: 30px; padding-inline: 3px; white-space: nowrap; } + .toolbar-actions > .dropdown:nth-child(-n + 2) .dropdown-menu { right: auto; left: 0; } + .brand-mark span:last-child, #theme-label, .toolbar-actions .menu-caret { display: none; } .dropdown-menu { max-width: calc(100vw - 12px); } - .properties-panel { top: 123px; } + .properties-panel { top: 125px; } #canvas-size-status { display: none; } .settings-layout { grid-template-columns: 1fr; min-height: 0; } .settings-tabs { flex-direction: row; overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--border-soft); } diff --git a/tests/browser-smoke.mjs b/tests/browser-smoke.mjs index f52d1c4..595bd36 100644 --- a/tests/browser-smoke.mjs +++ b/tests/browser-smoke.mjs @@ -359,6 +359,16 @@ try { check(); }))()`); assert(xmlImport.status.includes("Imported XML") && xmlImport.nodes === 10 && xmlImport.edges === 7, `XML round-trip failed: ${JSON.stringify(xmlImport)}`); + + await client.send("Emulation.setDeviceMetricsOverride", { width: 390, height: 844, deviceScaleFactor: 1, mobile: true }); + const mobileToolbar = await client.evaluate(`new Promise((resolve) => requestAnimationFrame(() => { + const controls = [...document.querySelectorAll('.toolbar [data-mode], #arrange-menu, #view-menu, #project-menu, #theme-toggle, .toolbar button[title="Settings"], .toolbar button[title="Keyboard shortcuts"]')]; + resolve(controls.map((control) => { + const rect = control.getBoundingClientRect(); + return { label: control.getAttribute('aria-label') || control.textContent.trim(), left: rect.left, right: rect.right, top: rect.top, bottom: rect.bottom, visible: getComputedStyle(control).display !== 'none' }; + })); + }))`); + assert(mobileToolbar.every((control) => control.visible && control.left >= 0 && control.right <= 390 && control.top >= 0 && control.bottom <= 118), `Mobile toolbar controls are clipped: ${JSON.stringify(mobileToolbar)}`); assert(client.errors.length === 0, `Browser errors: ${client.errors.join("; ")}`); console.log("Browser smoke test passed: FlyonUI settings, commands, themes, locking, menus, modals, rendering, connectors, persistence, XML/JSON projects, and SVG/PNG export.");