DECKYMUSIC
开发文档Docs › Steam Deck UI 规范Steam Deck UI rules

Steam Deck 大屏 UI 规则

本文件是 /music 大屏路由的共享 UI 契约。QQ 与网易云页面可以有不同产品结构,但必须共用这里的视觉、焦点、按键和宿主安全规则。

目标

  • 纯手柄可用:无鼠标、无触屏也能完成找歌、播放、控制、退出。
  • 像 Steam 游戏模式页面:遵循官方库 / 商店的 10-foot UI 范式,不照搬手机 App。
  • 不拖垮宿主:Steam UI 与插件前端在同一 Chromium 上下文,插件错误只能降级插件自身。

顶栏与布局

区域 规则
SteamOS 全局 chrome 右上角搜索、通知、Wi-Fi、电量、时间、头像属于系统;插件不绘制、不聚焦、不修改。
插件内容首行 provider Logo、顶层 Tab、L1/R1 提示和当前播放状态徽章放在内容区首行。
顶层导航 使用横向 Tabs;L1/R1 循环切换 provider 页面。
个人资产页 遵循官方库页面:全宽二级 Tab 行 + 全宽列表 / 网格;不要常驻左侧栏。
内容区 主内容占满宽度;推荐页可用横向条带 / 网格,搜索页可用列表 + 热搜侧栏。

去常驻播放条

P3 目标 UI 不保留底部固定 MiniPlayer。

原因:SteamOS 软键盘弹出时会压缩整个 CEF WebView 高度。任何 position: fixed; bottom: 0 或 flex 底部常驻栏都会被顶到键盘上方,挤压搜索结果并破坏官方 UI 习惯。

替代机制:

  1. Tab 状态徽章:顶层 Tab 行最右侧显示旋转小封面、歌名跑马灯、播放态;纯展示,不进焦点树。
  2. Start 盲操:任何页面、任何焦点位置都可播放 / 暂停;队列空或后端不可用时不显示可执行提示。
  3. Y 队列浮层:普通页面按 Y 打开右侧临时模态面板;浮层关闭后恢复原焦点。
  4. 沉浸播放页:完整进度、音量、上一首 / 下一首、歌词和评论都收归 Now Playing 或 provider 专属电台页。

视觉规则

项 规则
背景 近黑背景,允许封面模糊光晕;不要大面积品牌色铺底。
卡片 封面图本身就是卡片;直角或 2-4px 小圆角;不要手机式大圆角容器。
焦点态 2-3px 细白描边贴近元素边缘,允许轻微外发光和缩放。
列表选中 水平灰色渐变高亮条;必要时用 Steam 蓝左侧指示条。
品牌色 Steam 蓝 #1a9fff 是主交互色;QQ 绿 / NCM 红只做 Logo、徽标、红心等点缀。
字体和层级 标题粗体,正文常规;小节标题可用全大写小字号灰色。
Footer Legend 底部图例条由系统渲染。插件只提供当前焦点可执行动作的文案,不自绘样式。

队列浮层与页面共用近黑背景、4px 小圆角、歌曲信息层级。轻遮罩保留页面上下文; 只在该模态实例内覆盖 Decky 默认对话框外观,不修改 Steam 全局样式。 当前曲的蓝色标记与白色手柄焦点分开表达;电台当前曲只读,禁止无操作的 A/X 图例。 标题与关闭入口固定,列表区域独立滚动;完整队列可导航,DOM 只保留可见窗口及 overscan。

歌词定位与跟随

  • 进入“正在播放”或从热评返回歌词时,按当前播放时间选择歌词行,在首次可见绘制前直接定位。
  • 歌词仍在加载、没有当前行或容器尚无有效高度时,不标记为已完成首次定位;歌词就绪后再定位。
  • 已显示歌词的后续换句保持平滑跟随;不恢复离开 Tab 时的旧滚动位置。
  • 手动浏览的 4 秒静默期内不抢滚动,之后随换句恢复跟随。只滚动歌词容器,不使用会拖动外层页面的 scrollIntoView。
  • 不为此常驻隐藏页面或增加轮询。无初始滚动动画必须用连续画面和位置采样验收,静态截图只记录视觉状态。

焦点模型

主内容焦点树:Tabs 下的搜索、列表、网格、歌词、沉浸页控制
        |
        | Y / X / A 触发
        v
模态浮层焦点树:队列、上下文菜单、确认框

硬规则:

  • 所有可交互元素必须能被 Focusable 选中。
  • 禁止 hover-only、touch-only、不可见点击热区。
  • 网格和多列布局使用 MAINTAIN_X,避免上下移动时列错位。
  • 搜索框聚焦后按 A 必须唤起 Steam 软键盘。
  • 长列表必须分页、虚拟化或限制渲染量;不能一次性把大量节点塞进 DOM。
  • 滑块聚焦后十字键左右用于微调;离开滑块必须有明确路径。
  • 模态浮层关闭后恢复触发前焦点;原节点卸载时回退到当前页面第一个主要交互元素。

按键契约

按键 行为
D-Pad / 左摇杆 焦点导航;在歌词区可手动滚动;在滑块上微调。
A 确认:播放、进入详情、提交搜索、刷新二维码。
B 返回或关闭;关闭模态浮层;取消歌词 / 评论手动滚动。
X 上下文菜单;在 NCM 歌词页切换歌词 / 热评;在电台页可覆盖为垃圾桶 / 下一首。
Y 普通页面打开播放队列;在电台页可覆盖为红心等局部快捷键。
Start 全局播放 / 暂停;不依赖当前焦点。
View 保留,不作为 P3 必需路径;只有验证到真实收益后再绑定。
L1 / R1 顶层页面切换。
L2 / R2 长列表翻页;当 L1/R1 已用于顶层页时,可用于二级 Tab。
Steam / QAM 系统保留键,插件不绑定。
  • 通过 Focusable 的 actionDescriptionMap、onOKActionDescription 等属性声明文案。
  • 图例随焦点变化;根级 Focusable 可提供全局默认,子元素同按键文案会覆盖父级。
  • 左侧 STEAM 菜单、白圈图标、排列和位置由系统控制,插件不得自绘仿冒。
  • 不可用动作必须隐藏或置灰。X / Y 在特殊模式下被覆盖时,提示文案必须同步改成真实语义。

宿主安全

这些规则继承 docs/DESIGN.md 的 UI 崩溃隔离要求:

  • 所有 RPC、事件处理、计时器回调都要捕获错误,不把异常抛到全局。
  • 后端死亡、断网、畸形数据只能渲染错误态,不能冻结 Steam UI。
  • 图片用 CDN 缩略图;失败显示占位图。
  • 不 monkey-patch Steam 全局对象,不写全局命名空间。
  • 组件卸载时清理监听器、计时器、路由和模态浮层。

验收

每个 provider 页面都必须能用实体按键完成:

  1. 进入 /music。
  2. 切换顶层页面和二级 Tab。
  3. 搜索或打开推荐内容。
  4. 选歌播放。
  5. 暂停 / 继续。
  6. 打开并关闭队列浮层。
  7. 打开并关闭上下文菜单。
  8. 在歌词 / 评论区域手动浏览并恢复自动跟随。
  9. 在后端异常、断网或畸形数据时显示可恢复错误态。

在 GitHub 上查看 / 编辑此文档View or edit this page on GitHub ↗