Appearance
功能规格说明:移动端适配
创建日期:2026-10-13(2026-10-30 从 ui/remote-control.md 拆出)
本文只讲触控设备上的这一页:整屏怎么装得下、聚焦文本控件时不被浏览器放大、字号与图标按钮按手指给足的那一档。页面本身(连接、首屏、降级入口)见 remote-web.md,主屏安装与锁屏通知见 remote-pwa.md。
用户场景与测试 (必填)
用户故事:触控设备上的尺寸与字号(优先级:P1)
作为用手机打开这一页的人,我希望文字不用捏合就看得清、按钮不用瞄准就点得中,以便它真的能当手机界面用。
为什么是这个优先级:这一页是五端里唯一一种宿主对应两种设备的一页——同一张 /remote/ 既被手机打开、也被 PC 浏览器打开。沿用插件那一档密度,正文在手机上就明显偏小,而这一页既没有 ESC 键也没有终端,捏合与瞄准是仅有的补偿手段。它不决定功能能不能用,但决定这一页在手机上是不是能用。
独立测试:在手机上打开一次:顶栏与输入区同屏可见、页面本身不产生纵向滚动,两端都不被系统 UI 遮挡;聚焦任一输入框时整页不放大、且页面仍可双指缩放;正文与辅助信息不必捏合即可读;顶栏右侧与输入区左下角的图标按钮不必瞄准即可点中,且相邻两个不会互相误触;同一地址在 PC 浏览器里打开时字号与设计稿一致(文本类控件也不例外)、图标按钮也仍是设计稿尺寸,且本机 IDE 与桌面端的同一份 UI 视觉不变。
验收场景:
假设 页面在手机上打开(浏览器标签页里,或「添加到主屏幕」之后的独立窗口里),则 它必须整屏装得下:顶栏与输入区在同一屏内同时可见、页面自身不产生纵向滚动,顶部与横屏两端也都不被系统 UI 压住——浏览器工具栏的伸缩(地址栏与底部工具栏的收起 / 展开)与全面屏的安全区(状态栏、灵动岛、横屏时的圆角区)都不得把这两个区域推出可视范围或盖在它们上面;底部则不再额外让位:输入区底边就落在可视区底边上(只留输入区自身的常规内边距),不按底部安全区再往上抬一条。依据:这是唯一跑在浏览器里的宿主,它的高度由浏览器的可视区决定,而不是由承载它的窗口决定;本地四端嵌在没有动态工具栏、也没有安全区的窗口里,这条约束在它们身上恒成立(页面高度与窗口高度逐像素相等)。因此这是 Web 页独有的要求,按宿主收口,不改动其余四端的布局。顶部与底部之所以不对称:页面声明了
black-translucent,内容画到状态栏底下,顶部不让位就是「顶栏按钮被系统图标压住、点不动」(真机实测);底部反过来——独立窗口形态下浏览器给出的视口高度本身已经扣掉了底部安全区,再让一条会在输入区下方多出一倍宽的同色空带(真机实测「底部有空白」),而最下面那一条是系统手势保留区、页面本来就画不进去,输入区贴到可视区底边已经在它之上。假设 用户在 iPhone 的浏览器里(含「添加到主屏幕」后打开的窗口)聚焦页面上的任一文本类输入控件,则 页面不得被浏览器自动放大(聚焦前后整页的视觉缩放比不变,
visualViewport.scale保持 1),且用户仍然可以自行双指缩放页面——不得以关掉用户缩放为代价换来前一条。依据:iOS Safari 对字号偏小的文本控件会在聚焦时把整页放大到它认为可读的那一档,且此后不自动还原;字号抬到它认定的可读档以上才不会触发。两条路并不等价:不让页面被缩放(maximum-scale=1)确实能挡住自动放大,但会把用户的手动缩放一并关掉;把文本控件抬到可读档才能两条都要到。他 2026-10-14 先按前者上过真机,用下来判「这一页的字本来就偏小、现在连放大都没得用」不可接受,于是改回后者——页面上的每一个文本类控件都必须给到这个档,不止消息输入区。这条下限与第 3 条同一条判据(触控设备):触控设备上文本类控件一律抬到可读档,PC 浏览器保持设计稿密度(输入框回落各组件自己的基线)。依据(2026-10-16 改):触发这条的是 iOS 的字号阈值机制;Android 的同族机制并不相同——Chrome 聚焦输入框时的放大是视野补偿(页面被缩小过才把输入框放大并居中),它的文本膨胀只作用于未按设备宽度布局的页面,而本页声明width=device-width, initial-scale=1.0,两条都不成立。也就是说这条只对「触控 + iOS」是必需的、理论上可以只给 iOS,但样式里没有可靠的 iOS 判据(能区分 Safari 的写法随版本失效,无公认解法),而「主输入是手指」是稳定判据、本页档位组已经在用;反过来「只给 iOS」会让 Android 上的控件掉回组件基线,与已抬过一档的正文并排比现状更不协调。初版写的是「不按设备开关、宁可一律给足」,他 2026-10-16 在 PC 上打开这一页时报「输入控件看着偏大」——同一屏正文还是插件那一档——据此收进触控媒体查询。该要求只作用于远控页:其余四端不跑在移动端浏览器里,不受这条约束,也不该为它改动共享样式。假设 用户用触控设备(手机或平板)打开远控页,则 页面上的文字按手机档渲染,而不是沿用插件(IDE)那一档:消息正文与输入区一类阅读主体抬到移动端可读的尺寸,工具与代码块、辅助信息、弹窗与审批卡、会话列表的行标题随之整体抬一档(不是只把某一个控件调大——只调一处会让它在整页里显得孤立地大)。判据是设备能力,不是页面身份:同一张远控页在 PC 浏览器里也会被打开(它本就能,也常被这么用),那里要保持设计稿的密度;而「主输入是手指、没有悬停」(
pointer: coarse/hover: none)正好是手机与平板的共同点,把两端分开——这也是业界的判据(claude.ai 的共享样式里就有多处@media (pointer:coarse), (hover:none))。不用宽度断点代替:宽度是连续量——窄的手机视口、小平板、PC 窗口什么宽度都有——「多大算手机」没有自然分界,必须任选一个阈值,而阈值两侧都是误判:PC 上把窗口拉窄会被判成手机(那里原本是设计稿的密度),平板又会被判成桌面。横屏手机是宽度方案会漏掉的又一种,但他 2026-10-14 判「这一页竖着才装得下更多信息,横屏概率很低」,所以这条只作补充、不是选触控的主因。依据:同一份 webview 服务五端,字号此前是全站硬编码、只有两档(插件的高密度档 / 桌面的中密度档,后者是host-desktop.css里 60 余处[data-host="desktop"]覆写);远控页落在插件那一档,正文与辅助信息在手机上都比设计稿小一档,既偏小,又因为上一条不能再靠捏合弥补。业界对「一套代码、两端字号不同」的主流解法是把同一套组件按宿主/设备选一个密度档(另一个极端是给移动端另写一套 UI 或原生客户端,Claude Code 手机端走的是那条路);本页是前者的特例——五端里只有它一种宿主对应两种设备,所以它在自己这一档里还要再按设备分一层。具体取值归设计与本档的样式文件(本规格只钉住「触控设备上的文本类控件不得低于 iOS 的可读阈值」这条下限,见第 2 条,以及「边界情况」里那条范围)。假设 用户用触控设备(手机或平板)打开远控页,则 页面上图标按钮的点击目标与间距按手指给足,不沿用插件(IDE)那一档按鼠标指针定的尺寸:顶栏右侧的图标按钮族(新建对话 / 会话 / 更多;「切换电脑」不在这一族——它已从顶栏收进「更多」菜单,菜单项是整行可点的条,见
remote-machine.md「机器列表与切换」场景 5)、输入区左下角的图标按钮族(「+」添加、「/」快捷指令),提问 / 审批弹窗右上角那一族(折叠选项、关闭),消息队列每条右边那一族(编辑 / 立即发送 / 删除),以及会话列表页那一族(每行右侧的「⋯」、页面顶部的「返回」)——页面上相邻图标最密、最容易被误触的几处——每个按钮的点击热区按移动端的最小可点目标给足(Apple HIG 与 Material 各自的规范量级)、相邻两个之间的间距不小于一个手指接触面的容错量,图标字形随之抬大一档(仍然是「按钮带内边距、字形居中」的原有关系,只是整体放大一档)。热区与间距必须同时给足:只把热区撑大而不动间距,相邻两个按钮的可点区域就会相贴甚至重叠,误触更容易发生——用户 2026-10-15 报的正是这一点(「图标有点小,手指点起来很容易碰到其他图标」);2026-10-19 他又对弹窗那两枚报了同一句「还是有点小」,那是首版按「顶栏 + 输入区」两族划范围时留下的第三族;2026-10-29 他对消息队列每条右边那一族(编辑 / 立即发送 / 删除)又报了同一句(「消息队列里面的立即发送那些按钮,不是移动端应该有的尺寸」),那是第四族。判据与第 3 条同源:pointer: coarse/hover: none(主输入是手指、没有悬停),不是页面身份、也不用宽度断点——同一张远控页在 PC 浏览器里打开时保持设计稿密度,其余四端(IDE 与桌面)的同一份 UI 一个像素都不动。让位的对象按承载方式分([data-remote-page]作用域的同一档):顶栏与输入区那两族底下是固定高度的轨道,所以轨道跟着抬高到能装下放大后的按钮;弹窗那两枚是绝对定位在卡片右上角、没有轨道可抬,让位的是标题行——标题行的最小高度要抬到装得下按钮(否则放大后的按钮会往下压住第一道内容),标题本身也要给按钮组让出右侧位置(关闭键恒在 = 一枚按钮 + 间距;带折叠键时 = 两枚 + 两个间距)。消息队列那一族底下是行轨道:行高即按钮高,不额外留上下内衬(首版按「按钮 + 上下各一圈内衬」抬得更高,用户 2026-10-29 随即报「一个队列里的消息上下的空隙特别大」,那圈内衬收回),同一面板的折叠标题行(整行可点、带 chevron)一并抬到同一档;它还多一处比尺寸更靠前的问题——桌面档靠:hover才把按钮组显形(opacity: 0),触控设备没有悬停,这一档必须常显(opacity: 1),否则按钮放大到足够大也根本没有被按到的机会。会话列表页那一族同样按承载方式分:「⋯」放大后落在行里、不抬行高——行的本体高度(两行文字 + 内边距)本来就在按钮之上,为它单独抬行只会白占一屏;「返回」没有固定宽高、靠内边距撑起,所以给它一条最小高度保证热区;承载这两者的页头是固定高度的轨道,跟着抬高、左右内边距也加大,让按钮与屏幕边缘之间的间距给足。输入区右下角的权限档与发送按钮不在本场景内,它们的目标本就更大、也不与谁紧挨着(权限档收成图标档时是例外:它就是本场景这一族的尺寸,判据与收法见ui/model-selection.md的「底栏放不下时模型与权限收成图标档」——手机档一行放不下文字档时模型与权限同时收成图标)。连接状态条右侧的关闭键同属这一档,但它在状态条自己的故事里钉住(remote-channel.md场景 10):两处判据同源,谁改都别把另一处落下。依据:现状那套尺寸是按鼠标指针定的;手指的接触面远大于指针热区,Apple HIG 与 Material 的最小可点目标都比指针热区宽得多,按指针定的中心距在手指下必然误触。代价照实说:顶栏与输入区因此各高一些、弹窗标题行高一些、消息队列展开时每条高一些、会话列表页头也高一些,整屏约束(第 1 条)仍须成立——长高的量不能把消息区挤到「顶栏与输入区无法同屏」。
边界情况
Web 页的高度与安全区由浏览器说了算:本地四端(IDE / 桌面的宿主)都被嵌在一个自己就是整屏的窗口里——页面高度与窗口高度逐像素相等,没有会伸缩的浏览器工具栏,也没有被系统 UI 盖住的边缘。Web 页不是:它跑在浏览器里,可视区随工具栏收起 / 展开而变,页面若按「工具栏收起后」的高度铺满,贴底的输入区就会落到折叠线以下(用户看不到输入框 = 交互失效);页面又刻意画到屏幕边缘以吃满全面屏,于是状态栏 / 灵动岛、Home 指示条、横屏圆角区都压在内容之上,让开它们同样是页面自己的责任——但只让顶部与横屏两端:独立窗口形态下视口高度已经把底部安全区扣过一次,再让一条只是多出一条同色空带(2026-10-15 真机定性,见场景 1)。这两条只对这一个宿主成立 ⇒ 按宿主收口,不落在共享布局上。 字号档的判据是设备能力,不是页面身份:远控页是五端里唯一会被两种形态打开的一页——手机浏览器与 PC 浏览器打开的是同一张 /remote/,所以「这是哪一页」不足以决定字号(这既是它的特点,也是它必须两端都好用的原因)。判据取输入能力:pointer: coarse / hover: none 表示「主输入是手指、没有悬停」,正是手机与平板的共同点,也是业界(claude.ai 共享样式里多处 @media (pointer:coarse), (hover:none))的做法。宽度断点做不到这件事:宽度是连续量,「多大算手机」没有自然分界点,只能任选一个阈值,而两侧都会误判——PC 上把窗口拉窄会被判成手机、小平板又会被判成桌面;横屏手机同样是它漏掉的一种,但那属于补充(他 2026-10-14 判这一页横屏概率很低,见场景 3),不是选触控的主因。它同时也说明为什么这条差异不该写进共享样式:共享样式被五端同时加载,判据必须收在远控页这一层作用域里([data-remote-page],见上一条)。「文本类控件不得低于 iOS 可读阈值」那条下限也归这一档(2026-10-16 改,见场景 2):它防的 iOS 自动放大是字号阈值型的,而 Android 的同族机制(聚焦时的视野补偿、未按设备宽度布局的页面上的文本膨胀)在本页都不成立 ⇒ 这条严格说只对 iOS 必需;但样式里没有可靠的 iOS 判据(能区分 Safari 的写法随版本失效),而「主输入是手指」正是本档已在用的稳定判据,且在触控设备上与已抬过一档的正文同档。初版按「无条件给足」写,代价是 PC 上输入框比正文明显偏大(他 2026-10-16 报)。
未落地与待决
- **手机档的具体取值:本规格只钉住三条硬约束(触控设备上的阅读主体可读、文本类控件不得低于 iOS 的可读阈值、图标按钮的点击热区与相邻间距按移动端规范给足),以及「只作用于远控页」这条边界;具体数值落在一个独立的样式文件里(与桌面档同一批角色选择器、比它再大一档),尚未经设计师过一遍——正文与字形到底取哪一档,取决于设计稿的刻度。真机观感(尤其「一屏还能看见几条消息」这个信息密度、以及顶栏长高后整屏是否仍装得下,见场景 1)与 PC 浏览器上的观感(那里只该保持设计稿密度、输入控件也不例外)只能靠人工确认。见场景 1 / 2 / 3 / 4。
- **图标按钮的点击目标(2026-10-15 落地,2026-10-19 扩到第三族,2026-10-29 扩到第四族,2026-10-30 补记第五族,真机未验):按场景 4 把图标按钮在触控设备上放大一档(按钮热区、图标字形、相邻间距同时放大,落点在
remote-page.css的手机档媒体查询内),并随之抬高装不下它们的固定高度(顶栏、输入区按钮行)。无头实测过两档:触控档逐项达标、PC 档逐项与改动前相同——具体数值以那段媒体查询与e2e/remote-page-controls.e2e.ts为准,本规格不锁数值。2026-10-19 用户报「提问弹窗右上角那两个图标还是有点小」⇒ 首批漏掉的第三族(提问 / 审批弹窗的折叠选项 + 关闭)按同一档补齐;它单独成条的理由是承载方式不同——这两枚绝对定位在卡片右上角、下面没有固定高度的轨道,要让位的是标题行(最小高度抬到装得下按钮,并给按钮组留出右侧位置),否则放大后的按钮会往下压住第一道内容。2026-10-29 用户报「消息队列里面的立即发送那些按钮,不是移动端应该有的尺寸」⇒ 第四族(队列每条右边的编辑 / 立即发送 / 删除)按同一档补齐:间距同时放大(行与行之间的两枚也算「相邻」),承载它的行轨道抬到与按钮同高(行高即按钮高;首版多留了上下内衬,用户当天报「上下空隙特别大」后收回);它还多一处尺寸之外的问题:桌面档靠.queued-item:hover才把按钮组显形(opacity: 0),触控设备没有悬停,这一档必须常显,否则放大了也没机会被按到——两档各一条 e2e,量之前必须先把指针移出面板,否则.queued-item:hover会给手机档那条一个假绿。第五族是 2026-10-30 补记的:会话列表页那两处(每行右侧的「⋯」、页面顶部的「返回」)随整页会话列表一起就落在这档样式里,但当时没写进本规格——是核「spec 与手机档规则逐条对账」时找出来的口子。「⋯」放大后不抬行高(该行本体本就比按钮高),「返回」靠最小高度保证热区,页头这条固定高度的轨道跟着抬高、左右内边距也加大;间距口径不受影响(行内「⋯」的左邻是文本而非图标按钮,页头本就留了与图标同档的间距)。仍未做的:真机确认点准率(第五族同样未验),以及顶栏长高后「顶栏与输入区同屏」是否仍成立——无头浏览器有视口、但没有会伸缩的浏览器工具栏与安全区(那是场景 1 在本机复现不出来的同一件事)。