From 2fa68cde125401a04c3dc434bdb21bfffa51da71 Mon Sep 17 00:00:00 2001 From: Zrs000 <1900978743@qq.com> Date: Tue, 20 Oct 2026 12:41:41 +0800 Subject: [PATCH] fix(client): complete narrow settings viewport and hover layout --- .../locale/src/client/LanguageRow.module.css | 6 +- .../client/settings/PreferenceRow.module.css | 6 +- .../settings/EnterBehaviorRow.module.css | 6 +- .../src/client/PermissionRow.module.css | 6 +- .../src/client/TaskManagerPage.module.css | 91 ++++++++++++++----- .../ui-settings-general/README.i18n.yaml | 4 +- packages/client/ui-settings-general/README.md | 2 + .../client/ui-settings-general/README.zh.md | 2 + .../src/client/SettingsRoot.module.css | 24 +++-- .../src/client/AppearanceRow.module.css | 6 +- .../src/client/FontSizeRow.module.css | 23 ++++- 11 files changed, 128 insertions(+), 48 deletions(-) diff --git a/packages/client/locale/src/client/LanguageRow.module.css b/packages/client/locale/src/client/LanguageRow.module.css index 1277c5b4e8..dd525c9578 100644 --- a/packages/client/locale/src/client/LanguageRow.module.css +++ b/packages/client/locale/src/client/LanguageRow.module.css @@ -50,8 +50,10 @@ cursor: pointer; } -.selector:hover { - background: var(--dsw-alias-interactive-bg-hover); +@media (hover: hover) { + .selector:hover { + background: var(--dsw-alias-interactive-bg-hover); + } } .chevron { diff --git a/packages/client/ui-chat/src/client/settings/PreferenceRow.module.css b/packages/client/ui-chat/src/client/settings/PreferenceRow.module.css index bebe1971ed..9a33c136f3 100644 --- a/packages/client/ui-chat/src/client/settings/PreferenceRow.module.css +++ b/packages/client/ui-chat/src/client/settings/PreferenceRow.module.css @@ -55,8 +55,10 @@ cursor: pointer; } -.selector:hover { - background: var(--dsw-alias-interactive-bg-hover); +@media (hover: hover) { + .selector:hover { + background: var(--dsw-alias-interactive-bg-hover); + } } .chevron { diff --git a/packages/client/ui-conversation/src/client/settings/EnterBehaviorRow.module.css b/packages/client/ui-conversation/src/client/settings/EnterBehaviorRow.module.css index cf9bb42469..c3bca55448 100644 --- a/packages/client/ui-conversation/src/client/settings/EnterBehaviorRow.module.css +++ b/packages/client/ui-conversation/src/client/settings/EnterBehaviorRow.module.css @@ -55,8 +55,10 @@ cursor: pointer; } -.selector:hover { - background: var(--dsw-alias-interactive-bg-hover); +@media (hover: hover) { + .selector:hover { + background: var(--dsw-alias-interactive-bg-hover); + } } .chevron { diff --git a/packages/client/ui-permission-presets/src/client/PermissionRow.module.css b/packages/client/ui-permission-presets/src/client/PermissionRow.module.css index 825ce5f372..639cafbb5e 100644 --- a/packages/client/ui-permission-presets/src/client/PermissionRow.module.css +++ b/packages/client/ui-permission-presets/src/client/PermissionRow.module.css @@ -55,8 +55,10 @@ cursor: pointer; } -.selector:hover:not(:disabled) { - background: var(--dsw-alias-interactive-bg-hover); +@media (hover: hover) { + .selector:hover:not(:disabled) { + background: var(--dsw-alias-interactive-bg-hover); + } } .selector:disabled { diff --git a/packages/client/ui-schedule/src/client/TaskManagerPage.module.css b/packages/client/ui-schedule/src/client/TaskManagerPage.module.css index 1adaec58e4..dcc310f6b5 100644 --- a/packages/client/ui-schedule/src/client/TaskManagerPage.module.css +++ b/packages/client/ui-schedule/src/client/TaskManagerPage.module.css @@ -133,8 +133,10 @@ cursor: pointer; } -.filterTab:hover { - background: var(--dsw-alias-interactive-bg-hover); +@media (hover: hover) { + .filterTab:hover { + background: var(--dsw-alias-interactive-bg-hover); + } } .filterTabActive { @@ -158,8 +160,10 @@ transition: border-color 0.15s; } -.searchField:hover { - border-color: var(--dsw-alias-border-l2); +@media (hover: hover) { + .searchField:hover { + border-color: var(--dsw-alias-border-l2); + } } .searchField:focus-within { @@ -247,8 +251,10 @@ white-space: normal; } -.row:hover { - background: var(--dsw-alias-interactive-bg-hover); +@media (hover: hover) { + .row:hover { + background: var(--dsw-alias-interactive-bg-hover); + } } .rowGlyph { @@ -314,16 +320,26 @@ color: var(--dsw-alias-label-caption); } -.endedRow:hover .rowTitle, .endedRow.selectedRow .rowTitle { color: inherit; } -.endedRow:hover .rowSummary, +@media (hover: hover) { + .endedRow:hover .rowTitle { + color: inherit; + } +} + .endedRow.selectedRow .rowSummary { color: var(--dsw-alias-label-tertiary); } +@media (hover: hover) { + .endedRow:hover .rowSummary { + color: var(--dsw-alias-label-tertiary); + } +} + /* The mock's `.notice`: the catalog loading and failure text keeps the caption size and the mock's 20px leading instead of the host's inherited 16px, on the mock's surface box with its 12px/14px padding, 9px gap, top alignment, 10px @@ -492,8 +508,10 @@ font-weight: 500; } -.editName:hover { - box-shadow: 0 1px var(--dsw-alias-border-l3); +@media (hover: hover) { + .editName:hover { + box-shadow: 0 1px var(--dsw-alias-border-l3); + } } .editName:focus { @@ -700,8 +718,10 @@ cursor: pointer; } -.retentionInfo:hover { - color: var(--dsw-alias-label-primary); +@media (hover: hover) { + .retentionInfo:hover { + color: var(--dsw-alias-label-primary); + } } .retentionInfo:focus-visible { @@ -844,8 +864,10 @@ transition: background 0.15s; } -.ruleValue:not(:disabled):hover .ruleValueFace { - background: var(--dsw-alias-interactive-bg-hover); +@media (hover: hover) { + .ruleValue:not(:disabled):hover .ruleValueFace { + background: var(--dsw-alias-interactive-bg-hover); + } } /* The trigger's own ring would box the row label as well; the value face @@ -937,8 +959,10 @@ transition: background 0.15s; } -.ruleInput:not(:disabled):hover { - background: var(--dsw-alias-interactive-bg-hover); +@media (hover: hover) { + .ruleInput:not(:disabled):hover { + background: var(--dsw-alias-interactive-bg-hover); + } } /* An ended task keeps its values readable: tertiary rather than dimmed ink. */ @@ -995,8 +1019,10 @@ appearance: none; } -.ruleIntervalInput:not(:disabled):hover { - background: transparent; +@media (hover: hover) { + .ruleIntervalInput:not(:disabled):hover { + background: transparent; + } } .ruleRows .ruleIntervalInput:focus-visible { @@ -1012,11 +1038,20 @@ opacity: 0; } -.ruleIntervalStepper:hover .ruleIntervalArrows, .ruleIntervalStepper:focus-within .ruleIntervalArrows { opacity: 1; } +@media (hover: none) { + .ruleIntervalArrows { opacity: 1; } +} + +@media (hover: hover) { + .ruleIntervalStepper:hover .ruleIntervalArrows { + opacity: 1; + } +} + .ruleIntervalArrow { display: inline-flex; align-items: center; @@ -1031,8 +1066,10 @@ cursor: pointer; } -.ruleIntervalArrow:hover:not(:disabled) { - background: var(--dsw-alias-bg-layer-1); +@media (hover: hover) { + .ruleIntervalArrow:hover:not(:disabled) { + background: var(--dsw-alias-bg-layer-1); + } } .ruleIntervalArrow:disabled { @@ -1115,8 +1152,10 @@ --dsh-scrollbar-track-margin: 12px; } -.instruction:hover { - border-color: var(--dsw-alias-border-l2); +@media (hover: hover) { + .instruction:hover { + border-color: var(--dsw-alias-border-l2); + } } .instruction:focus { @@ -1260,8 +1299,10 @@ cursor: pointer; } -.savedPromptToggle:hover { - background: var(--dsw-alias-interactive-bg-hover); +@media (hover: hover) { + .savedPromptToggle:hover { + background: var(--dsw-alias-interactive-bg-hover); + } } .savedPromptToggle:focus-visible { diff --git a/packages/client/ui-settings-general/README.i18n.yaml b/packages/client/ui-settings-general/README.i18n.yaml index 8561f301f2..4ba8bac6ef 100644 --- a/packages/client/ui-settings-general/README.i18n.yaml +++ b/packages/client/ui-settings-general/README.i18n.yaml @@ -15,8 +15,8 @@ en: ae9928d13ce9a84c zh: 20cd645ebd75934b /deepseek-ai-dsh-client-ui-settings-general/use-this-package: - en: eb695d3dd1bc7155 - zh: 671606eeeb6bd87a + en: 7c9131139808880d + zh: b0b364ac14017999 /deepseek-ai-dsh-client-ui-settings-general/use-this-package/the-general-section: en: 8b8a7c6287bb303b zh: 19535112531aedd5 diff --git a/packages/client/ui-settings-general/README.md b/packages/client/ui-settings-general/README.md index b6f43876bd..d0c1970fe5 100644 --- a/packages/client/ui-settings-general/README.md +++ b/packages/client/ui-settings-general/README.md @@ -31,6 +31,8 @@ Below 768px viewport width the panel fills the viewport and its navigation becom Users reach the shell through the sidebar's bottom Settings control; feature plugins contribute their pages and onboarding steps through the slot ledgers this shell projects. In both the expanded sidebar and collapsed rail, the control exposes the localized Settings label as its accessible name. A pale-yellow **Disconnected** action beside Settings indicates browser offline suspension; its permanent retry glyph marks the retry action, which the Chinese outage copy also names (连接异常,刷新重试). Every recovery attempt shows the shared ongoing loader beside **Reconnecting** with one to three dots advancing every 500ms, and an attempt stays visible for at least 800ms so brief retries do not flicker. Selecting either yellow state starts an immediate retry; press feedback stays within the warning palette. Recovery changes the region to pale-green **Connected** for two seconds from the moment the green pill becomes visible. The pill fades in on appearance, fades out over 150ms on removal, and sizes to its current label. Initial startup and uninterrupted healthy operation remain silent. The shell renders the modal panel, the navigation built from `settings.section` entries, and exactly one mounted onboarding step at a time. +Below 768px, the body-portaled panel fills the CSS layout viewport without additional safe-area padding. It retains its layout height when the keyboard opens and lets the browser pan the page to reveal focused controls. + Above the mobile width, Settings uses the [frame’s shared overlay inset](../ui-layout/README.md#window-chrome-seat) and keeps at least 24px of viewport margin. Its mask leaves the Windows caption unpainted; the full-viewport layer still blocks background clicks, and the full-viewport panel covers the mask. When the page reconnects to a Host running another release, a **Service version changed** dialog draws two lines: **Service** from the Host's previous release (gray) to its current release, joined by a thin solid green arrow because the Host already switched, and **Page** from the release this page booted from to the Host's release (gray), joined by an equally thin dashed gray arrow because only a reload completes it. A line shows versions when its two versions differ and commits otherwise. The page applies no plugin update from that release. **Reload to load the new version** loads it; **Not now**, the close control, a mask click, and Escape keep the page at its own release and stop asking about that Host release. When the Host returns to the page's release, the dialog closes and live updates resume. diff --git a/packages/client/ui-settings-general/README.zh.md b/packages/client/ui-settings-general/README.zh.md index 94c5351d64..362a1f4d5f 100644 --- a/packages/client/ui-settings-general/README.zh.md +++ b/packages/client/ui-settings-general/README.zh.md @@ -31,6 +31,8 @@ kind: "package-reference" 用户通过侧边栏底部的 Settings 控件进入外壳;功能插件通过本外壳所投影的 slot 账本贡献自己的页面与引导步骤。在展开侧边栏和收起轨道中,该控件都会把本地化的 Settings 文案作为其可访问名称。Settings 右侧浅黄色的**连接异常**操作表示浏览器离线暂停;其常驻重试图形与中文文案「连接异常,刷新重试」都指明重试动作。每次恢复尝试都显示共享 ongoing loading 加**重新连接中**,其后一至三个点每 500ms 前进一次,且每次尝试至少可见 800ms,短暂重试不会闪动。选中任一黄色状态都会立即发起重试;按压反馈留在黄色色阶内。恢复后该区域变为浅绿色的**连接成功**,从绿色药丸可见起驻留 2 秒再消失。药丸出现时淡入、移除时以 150ms 淡出,宽度随当前文案自适应。首次启动与未曾中断的健康连接保持静默。外壳渲染模态面板、由 `settings.section` 条目构建的导航,以及每次只挂载一个的引导步骤。 +低于 768px 时,挂载到 body 的面板铺满 CSS 布局视口,不额外留出安全区边距。键盘抬起时保留原有布局高度,由浏览器平移页面以露出获得焦点的控件。 + 在移动端宽度以上,设置面板使用[框架共享的浮层起点](../ui-layout/README.zh.md#window-chrome-seat),视口边距至少为 24px。其遮罩不绘制 Windows 顶栏区域,覆盖整个视口的模态层仍阻挡背景点击;移动端铺满视口的面板覆盖该遮罩。 页面重连到运行另一个 release 的 Host 时,会弹出**服务版本变化**对话框,画出两条线:**服务**从 Host 之前的 release(灰色)指向它当前的 release,用细的绿色实线箭头连接,表示 Host 已经切换;**页面**从页面启动时的 release 指向 Host 的 release(灰色),用同样细的灰色虚线箭头连接,表示要刷新后才完成。每行两端版本号不同时显示版本号,否则显示 commit。页面不应用该 release 的任何插件更新。**刷新以加载新版本**加载它;**暂不刷新**、关闭按钮、点击遮罩和 Escape 都让页面保持自己的 release,并不再为该 Host release 提示。Host 回到页面的 release 时,对话框关闭,热更新恢复。 diff --git a/packages/client/ui-settings-general/src/client/SettingsRoot.module.css b/packages/client/ui-settings-general/src/client/SettingsRoot.module.css index ac0c275dac..569aa99cec 100644 --- a/packages/client/ui-settings-general/src/client/SettingsRoot.module.css +++ b/packages/client/ui-settings-general/src/client/SettingsRoot.module.css @@ -35,8 +35,10 @@ line-height: 22px; } -.trigger:hover { - background: var(--dsw-alias-interactive-bg-hover); +@media (hover: hover) { + .trigger:hover { + background: var(--dsw-alias-interactive-bg-hover); + } } /* Rail trigger: the same 36x36 box and 12px rounding as the other rail @@ -170,8 +172,10 @@ text-align: left; } -.navCell:hover { - background: var(--dsw-specific-sidebar-nav-item-hover); +@media (hover: hover) { + .navCell:hover { + background: var(--dsw-specific-sidebar-nav-item-hover); + } } .navCell.active { @@ -226,8 +230,10 @@ color: var(--dsw-alias-label-primary); } -.close:hover { - background: var(--dsw-alias-interactive-bg-hover); +@media (hover: hover) { + .close:hover { + background: var(--dsw-alias-interactive-bg-hover); + } } /* Options area (figma Options 501:29983): pad (24,0,24,24), scrolls. */ @@ -249,6 +255,12 @@ clip a name; the active cell carries data-modal-autofocus, so opening the panel scrolls it into view. */ @media (max-width: 767px) { + .overlay { + position: absolute; + height: 100%; + background: var(--dsw-alias-bg-layer-2); + } + .panel { grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto auto minmax(0, 1fr); diff --git a/packages/client/ui-theme/src/client/AppearanceRow.module.css b/packages/client/ui-theme/src/client/AppearanceRow.module.css index 2645edc3c2..7178b303dd 100644 --- a/packages/client/ui-theme/src/client/AppearanceRow.module.css +++ b/packages/client/ui-theme/src/client/AppearanceRow.module.css @@ -45,8 +45,10 @@ cursor: pointer; } -.themeCube:hover:not(.selected) { - background: var(--dsw-alias-interactive-bg-hover); +@media (hover: hover) { + .themeCube:hover:not(.selected) { + background: var(--dsw-alias-interactive-bg-hover); + } } /* Selected cube: #F5F6F7 fill + #ADB2B8 border (static token — the bluish-400 diff --git a/packages/client/ui-theme/src/client/FontSizeRow.module.css b/packages/client/ui-theme/src/client/FontSizeRow.module.css index d6a33ad45e..0fc8aa710b 100644 --- a/packages/client/ui-theme/src/client/FontSizeRow.module.css +++ b/packages/client/ui-theme/src/client/FontSizeRow.module.css @@ -87,11 +87,20 @@ opacity: 0; } -.stepper:hover .arrows, .stepper:focus-within .arrows { opacity: 1; } +@media (hover: none) { + .arrows { opacity: 1; } +} + +@media (hover: hover) { + .stepper:hover .arrows { + opacity: 1; + } +} + /* Arrow buttons: small chips carrying a translucent wash of the layer-1 surface (white in light, the elevated layer in dark) over the module fill; hover raises the full layer-1 chip. */ @@ -109,8 +118,10 @@ cursor: pointer; } -.arrow:hover:not(:disabled) { - background: var(--dsw-alias-bg-layer-1); +@media (hover: hover) { + .arrow:hover:not(:disabled) { + background: var(--dsw-alias-bg-layer-1); + } } .arrow:disabled { @@ -133,8 +144,10 @@ cursor: pointer; } -.expander:hover { - background: var(--dsw-alias-interactive-bg-hover); +@media (hover: hover) { + .expander:hover { + background: var(--dsw-alias-interactive-bg-hover); + } } .expander svg {