fix(control-ui): prevent iOS input zoom · openclaw/openclaw@c722ae6
BunsDev
·
2026-05-14
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -14,6 +14,7 @@ Docs: https://docs.openclaw.ai
|
14 | 14 | - Control UI/chat: reconcile terminal and reconnect run cleanup with cached session activity, stale compaction/fallback indicators, and a compact composer run-status chip so completed or interrupted turns do not leave Stop active. Fixes #76874 and #64220; refs #71630. Thanks @BunsDev. |
15 | 15 | - Maintainer tooling: clarify which pnpm test/check commands are safe locally versus inside Codex worktrees, routing linked-worktree gates through node wrappers and Crabbox/Testbox. |
16 | 16 | - iOS/chat: resize PhotosPicker image attachments to capped JPEGs before staging and sending, stripping source metadata and keeping oversized camera photos under the chat upload budget. Fixes #68524. Thanks @BunsDev. |
| 17 | +- Control UI: keep shared form, config, and usage text-entry controls at 16px on touch-primary devices while preserving chat composer input sizing, so iOS Safari no longer auto-zooms focused fields. Fixes #64651; carries forward #64673. Thanks @NianJiuZst and @BunsDev. |
17 | 18 | - Codex harness: classify native app-server token-refresh logout and relogin failures as authentication refresh errors, so users get re-authentication guidance instead of a raw runtime failure. |
18 | 19 | - Agents/trajectory: make the trajectory flush cleanup timeout configurable with `OPENCLAW_TRAJECTORY_FLUSH_TIMEOUT_MS`, preserving the 10s default while slower stores drain. Refs #75839. Thanks @BunsDev. |
19 | 20 | - Codex startup: treat selectable configured OpenAI agent models as Codex runtime requirements during plugin auto-enable, startup planning, and doctor install repair, so Anthropic-primary configs can still switch to OpenAI/Codex cleanly. |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -5,6 +5,10 @@ function readLayoutCss(): string {
|
5 | 5 | return readStyleSheet("ui/src/styles/chat/layout.css"); |
6 | 6 | } |
7 | 7 | |
| 8 | +function readBaseCss(): string { |
| 9 | +return readStyleSheet("ui/src/styles/base.css"); |
| 10 | +} |
| 11 | + |
8 | 12 | describe("chat layout styles", () => { |
9 | 13 | it("styles queued-message steering controls and pending indicators", () => { |
10 | 14 | const css = readLayoutCss(); |
@@ -25,7 +29,11 @@ describe("chat layout styles", () => {
|
25 | 29 | |
26 | 30 | it("keeps composer text scale-driven while preserving mobile input zoom safety", () => { |
27 | 31 | const css = readLayoutCss(); |
| 32 | +const baseCss = readBaseCss(); |
28 | 33 | |
| 34 | +expect(baseCss).toContain( |
| 35 | +"--control-ui-input-text-size: max(16px, calc(14px * var(--control-ui-text-scale)));", |
| 36 | +); |
29 | 37 | expect(css).toContain("font-size: var(--control-ui-input-text-size);"); |
30 | 38 | expect(css).toContain(".agent-chat__composer-combobox > textarea"); |
31 | 39 | expect(css).toContain(".chat-compose .chat-compose__field textarea"); |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -942,6 +942,14 @@
|
942 | 942 | box-shadow var(--duration-fast) ease; |
943 | 943 | } |
944 | 944 | |
| 945 | +@media (hover: none) and (pointer: coarse) { |
| 946 | + .field input, |
| 947 | + .field textarea, |
| 948 | + .field select { |
| 949 | +font-size: 16px; |
| 950 | + } |
| 951 | +} |
| 952 | + |
945 | 953 | .field input:focus, |
946 | 954 | .field textarea:focus, |
947 | 955 | .field select:focus { |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -17,6 +17,14 @@ describe("agent fallback chip styles", () => {
|
17 | 17 | expect(css).toContain("outline-offset: 2px;"); |
18 | 18 | expect(css).toContain(".agent-chip-input .chip-remove:disabled"); |
19 | 19 | }); |
| 20 | + |
| 21 | +it("keeps touch-primary field controls large enough to avoid iOS focus zoom", () => { |
| 22 | +const css = readComponentsCss(); |
| 23 | + |
| 24 | +expect(css).toMatch( |
| 25 | +/@media \(hover: none\) and \(pointer: coarse\) \{[\s\S]*\.field input,[\s\S]*\.field textarea,[\s\S]*\.field select \{[\s\S]*font-size: 16px;/, |
| 26 | +); |
| 27 | +}); |
20 | 28 | }); |
21 | 29 | |
22 | 30 | describe("sessions filter styles", () => { |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -1392,6 +1392,20 @@
|
1392 | 1392 | border-color: var(--border); |
1393 | 1393 | } |
1394 | 1394 | |
| 1395 | +@media (hover: none) and (pointer: coarse) { |
| 1396 | + .config-search__input, |
| 1397 | + .settings-theme-import__input, |
| 1398 | + .config-raw-field textarea, |
| 1399 | + .cfg-input, |
| 1400 | + .cfg-input--sm, |
| 1401 | + .cfg-textarea, |
| 1402 | + .cfg-textarea--sm, |
| 1403 | + .cfg-number__input, |
| 1404 | + .cfg-select { |
| 1405 | +font-size: 16px; |
| 1406 | + } |
| 1407 | +} |
| 1408 | + |
1395 | 1409 | /* Segmented Control */ |
1396 | 1410 | .cfg-segmented { |
1397 | 1411 | display: inline-flex; |
|
| Original file line number | Diff line number | Diff line change |
|---|
|
| 1 | +import { describe, expect, it } from "vitest"; |
| 2 | +import { readStyleSheet } from "../../../test/helpers/ui-style-fixtures.js"; |
| 3 | + |
| 4 | +function readConfigCss(): string { |
| 5 | +return readStyleSheet("ui/src/styles/config.css"); |
| 6 | +} |
| 7 | + |
| 8 | +describe("config styles", () => { |
| 9 | +it("keeps touch-primary config text controls large enough to avoid iOS focus zoom", () => { |
| 10 | +const css = readConfigCss(); |
| 11 | + |
| 12 | +expect(css).toMatch( |
| 13 | +/@media \(hover: none\) and \(pointer: coarse\) \{[\s\S]*\.config-search__input,[\s\S]*\.settings-theme-import__input,[\s\S]*\.config-raw-field textarea,[\s\S]*\.cfg-input,[\s\S]*\.cfg-input--sm,[\s\S]*\.cfg-textarea,[\s\S]*\.cfg-textarea--sm,[\s\S]*\.cfg-number__input,[\s\S]*\.cfg-select \{[\s\S]*font-size: 16px;/, |
| 14 | +); |
| 15 | +}); |
| 16 | +}); |
| Original file line number | Diff line number | Diff line change |
|---|
@@ -356,6 +356,16 @@
|
356 | 356 | font-size: 12px; |
357 | 357 | } |
358 | 358 | |
| 359 | +@media (hover: none) and (pointer: coarse) { |
| 360 | + .usage-date-input, |
| 361 | + .usage-select, |
| 362 | + .usage-query-input, |
| 363 | + .usage-filters-inline select, |
| 364 | + .usage-filters-inline input[type="text"] { |
| 365 | +font-size: 16px; |
| 366 | + } |
| 367 | +} |
| 368 | + |
359 | 369 | .usage-query-input::placeholder { |
360 | 370 | color: var(--muted); |
361 | 371 | opacity: 0.7; |
|
| Original file line number | Diff line number | Diff line change |
|---|
|
| 1 | +import { describe, expect, it } from "vitest"; |
| 2 | +import { readStyleSheet } from "../../../test/helpers/ui-style-fixtures.js"; |
| 3 | + |
| 4 | +function readUsageCss(): string { |
| 5 | +return readStyleSheet("ui/src/styles/usage.css"); |
| 6 | +} |
| 7 | + |
| 8 | +describe("usage styles", () => { |
| 9 | +it("keeps touch-primary usage text controls large enough to avoid iOS focus zoom", () => { |
| 10 | +const css = readUsageCss(); |
| 11 | + |
| 12 | +expect(css).toMatch( |
| 13 | +/@media \(hover: none\) and \(pointer: coarse\) \{[\s\S]*\.usage-date-input,[\s\S]*\.usage-select,[\s\S]*\.usage-query-input,[\s\S]*\.usage-filters-inline select,[\s\S]*\.usage-filters-inline input\[type="text"\] \{[\s\S]*font-size: 16px;/, |
| 14 | +); |
| 15 | +}); |
| 16 | +}); |
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。