Skip to content

Commit e38851b

Browse files
committed
feat(ui): add control ui text scale
1 parent c3e5d85 commit e38851b

22 files changed

Lines changed: 275 additions & 15 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ Docs: https://docs.openclaw.ai
9696

9797
### Changes
9898

99+
- Control UI: add a browser-local Text size setting in Appearance and Quick Settings, scaling chat and dense UI text while keeping inputs above the mobile Safari focus-zoom threshold. Fixes #8547. Thanks @BunsDev.
99100
- Docs: add a dedicated ds4 provider page with local DeepSeek V4 Flash config, on-demand startup, context sizing, and live verification steps.
100101
- Maintainers: add a Clawdtributor skill for Discrawl-backed contributor PR triage, live status checks, and compact review formatting.
101102
- Telegram: support Mini App `web_app` buttons in generic message presentation payloads, allowing `openclaw message send --presentation` to render Telegram Web App inline buttons for private chats. (#81356) Thanks @jzakirov.

docs/web/control-ui.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ Docs translations are generated for the same non-English locale set, but the doc
8989

9090
The Appearance panel keeps the built-in Claw, Knot, and Dash themes, plus one browser-local tweakcn import slot. To import a theme, open [tweakcn editor](https://tweakcn.com/editor/theme), choose or create a theme, click **Share**, and paste the copied theme link into Appearance. The importer also accepts `https://tweakcn.com/r/themes/<id>` registry URLs, editor URLs like `https://tweakcn.com/editor/theme?theme=amethyst-haze`, relative `/themes/<id>` paths, raw theme IDs, and default theme names such as `amethyst-haze`.
9191

92+
Appearance also includes a browser-local Text size setting. The setting is stored with the rest of Control UI preferences, applies to chat text, composer text, tool cards, and chat sidebars, and keeps text inputs at least 16px so mobile Safari does not auto-zoom on focus.
93+
9294
Imported themes are stored only in the current browser profile. They are not written to gateway config and do not sync across devices. Replacing the imported theme updates the one local slot; clearing it switches the active theme back to Claw if the imported theme was selected.
9395

9496
## What it can do (today)

ui/src/styles/base.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@
8585
"JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, monospace;
8686
--font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
8787
--font-display: var(--font-body);
88+
--control-ui-text-scale: 1;
89+
--control-ui-text-xs: calc(11px * var(--control-ui-text-scale));
90+
--control-ui-text-sm: calc(12px * var(--control-ui-text-scale));
91+
--control-ui-text-md: calc(14px * var(--control-ui-text-scale));
92+
--control-ui-text-lg: calc(16px * var(--control-ui-text-scale));
93+
--control-ui-input-text-size: max(16px, calc(14px * var(--control-ui-text-scale)));
94+
--chat-text-size: var(--control-ui-text-md);
8895

8996
/* Shadows - Subtle, layered depth */
9097
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.25);

ui/src/styles/chat/layout.css

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@
517517
resize: none;
518518
white-space: pre-wrap;
519519
font-family: var(--font-body);
520-
font-size: 14px;
520+
font-size: var(--control-ui-input-text-size);
521521
line-height: 1.45;
522522
}
523523

@@ -597,7 +597,7 @@
597597
border: none;
598598
background: transparent;
599599
color: var(--text);
600-
font-size: 0.92rem;
600+
font-size: var(--control-ui-input-text-size);
601601
font-family: inherit;
602602
line-height: 1.4;
603603
outline: none;
@@ -615,7 +615,7 @@
615615
.agent-chat__stt-interim {
616616
padding: 10px 14px 0;
617617
color: var(--muted);
618-
font-size: 0.82rem;
618+
font-size: var(--control-ui-text-sm);
619619
line-height: 1.35;
620620
overflow-wrap: anywhere;
621621
}

ui/src/styles/chat/layout.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,12 @@ describe("chat layout styles", () => {
2222
expect(css).toContain("font-size: 20px;");
2323
expect(css).toContain("place-items: center;");
2424
});
25+
26+
it("keeps composer text scale-driven while preserving mobile input zoom safety", () => {
27+
const css = readLayoutCss();
28+
29+
expect(css).toContain("font-size: var(--control-ui-input-text-size);");
30+
expect(css).toContain(".agent-chat__composer-combobox > textarea");
31+
expect(css).toContain(".chat-compose .chat-compose__field textarea");
32+
});
2533
});

ui/src/styles/chat/sidebar.css

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868

6969
.sidebar-title {
7070
font-weight: 600;
71-
font-size: 14px;
71+
font-size: var(--control-ui-text-md);
7272
}
7373

7474
.sidebar-content {
@@ -78,7 +78,7 @@
7878
}
7979

8080
.sidebar-markdown {
81-
font-size: 14px;
81+
font-size: var(--control-ui-text-md);
8282
line-height: 1.6;
8383
color: var(--text);
8484
}
@@ -123,7 +123,7 @@
123123

124124
.sidebar-markdown-shell__hint {
125125
color: var(--muted);
126-
font-size: 12px;
126+
font-size: var(--control-ui-text-sm);
127127
line-height: 1.45;
128128
}
129129

@@ -158,7 +158,7 @@
158158
}
159159

160160
.sidebar-markdown-reader.sidebar-markdown {
161-
font-size: 14.5px;
161+
font-size: calc(14.5px * var(--control-ui-text-scale));
162162
line-height: 1.72;
163163
}
164164

ui/src/styles/chat/text.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
border: 1px dashed rgba(255, 255, 255, 0.18);
1010
background: rgba(255, 255, 255, 0.04);
1111
color: var(--muted);
12-
font-size: 12px;
12+
font-size: var(--control-ui-text-sm);
1313
line-height: 1.4;
1414
}
1515

@@ -19,7 +19,7 @@
1919
}
2020

2121
.chat-text {
22-
font-size: 14px;
22+
font-size: var(--chat-text-size);
2323
line-height: 1.5;
2424
word-wrap: break-word;
2525
overflow-wrap: break-word;

ui/src/styles/chat/text.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { describe, expect, it } from "vitest";
2+
import { readStyleSheet } from "../../../../test/helpers/ui-style-fixtures.js";
3+
4+
function readTextCss(): string {
5+
return readStyleSheet("ui/src/styles/chat/text.css");
6+
}
7+
8+
describe("chat text styles", () => {
9+
it("uses browser-local text scale variables for message text", () => {
10+
const css = readTextCss();
11+
12+
expect(css).toContain("font-size: var(--chat-text-size);");
13+
expect(css).toContain("font-size: var(--control-ui-text-sm);");
14+
});
15+
});

ui/src/styles/chat/tool-cards.css

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
align-items: center;
6565
gap: 6px;
6666
font-weight: 600;
67-
font-size: 14px;
67+
font-size: var(--control-ui-text-md);
6868
line-height: 1.2;
6969
min-width: 0;
7070
}
@@ -157,12 +157,12 @@
157157
}
158158

159159
.chat-tool-card__status-text {
160-
font-size: 11px;
160+
font-size: var(--control-ui-text-xs);
161161
margin-top: 10px;
162162
}
163163

164164
.chat-tool-card__detail {
165-
font-size: 12px;
165+
font-size: var(--control-ui-text-sm);
166166
color: var(--muted);
167167
margin-top: 6px;
168168
}

ui/src/styles/config.css

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,62 @@
801801
color: var(--accent);
802802
}
803803

804+
.settings-text-scale {
805+
display: grid;
806+
gap: 8px;
807+
}
808+
809+
.settings-text-scale__options {
810+
display: grid;
811+
grid-template-columns: repeat(auto-fit, minmax(92px, 1fr));
812+
gap: 8px;
813+
}
814+
815+
.settings-text-scale__btn {
816+
display: grid;
817+
gap: 4px;
818+
justify-items: start;
819+
min-height: 58px;
820+
padding: 10px 12px;
821+
border: 1px solid var(--border);
822+
border-radius: var(--radius-md);
823+
background: var(--card);
824+
color: var(--text);
825+
cursor: pointer;
826+
text-align: left;
827+
transition:
828+
border-color var(--duration-fast) ease,
829+
background var(--duration-fast) ease,
830+
transform var(--duration-fast) ease;
831+
}
832+
833+
.settings-text-scale__btn:hover {
834+
border-color: var(--border-strong);
835+
background: var(--bg-elevated);
836+
transform: translateY(-1px);
837+
}
838+
839+
.settings-text-scale__btn.active {
840+
border-color: var(--accent);
841+
background: var(--accent-subtle);
842+
}
843+
844+
.settings-text-scale__sample {
845+
font-weight: 650;
846+
font-size: 13px;
847+
line-height: 1.2;
848+
}
849+
850+
.settings-text-scale__label {
851+
color: var(--muted);
852+
font-size: 11px;
853+
line-height: 1.2;
854+
}
855+
856+
.settings-text-scale__btn.active .settings-text-scale__label {
857+
color: var(--accent);
858+
}
859+
804860
.settings-info-grid {
805861
display: grid;
806862
gap: 10px;

0 commit comments

Comments
 (0)