Files
Starlight_Lancher/.agents/skills/oil-frontend/references/viewport-and-dialog-contract.md

7.6 KiB
Raw Blame History

页面尺寸与弹窗规则

当任务涉及页面或弹窗尺寸、分栏、滚动、承载方式或响应式布局时读取;依附触发器的浮层由下拉菜单与浮层规则负责。

目录

核心模型

先确定四个问题:

  1. 首屏必须让用户看到什么;
  2. 内容如何决定尺寸并受视口约束;
  3. 哪个区域拥有滚动;
  4. 主操作固定在哪里。

空间设计按以下顺序进行:

删除非必要信息 → 使用水平空间 → 压缩重复间距 → 指定滚动区 → 才允许增加页面长度

单屏信息预算

首屏优先显示:

  • 当前对象身份;
  • 当前任务或关键预览;
  • 影响决策的状态;
  • 主要操作;
  • 完成任务必需的输入。

以下内容可以滚动或进入详情:

  • 历史记录;
  • 完整分析和证据;
  • 低频设置;
  • 帮助说明;
  • 次要关联信息。

不要为了“单屏”缩小到难以阅读。目标是减少无意义滚动,让用户在首屏完成主要判断和操作。

水平与垂直布局

宽屏优先并列展示可以同时参考的信息:

  • 媒体预览 + 配置;
  • 资源身份 + 详情;
  • 主工作区 + 辅助检查;
  • 表格 + 行级预览。

只有存在阅读顺序依赖时才纵向堆叠。不要把短字段、操作区和预览全部纵向排列,制造不必要页面高度。

分栏需满足:

  • 主区宽度高于辅区;
  • 文本保持可读行长;
  • 两栏分别只在确有独立浏览需求时滚动;
  • 窄屏按任务顺序折叠为单列;
  • 主操作在布局变化后仍保持稳定位置。

内容驱动尺寸

默认让内容、Flex/Grid 和父容器边界决定尺寸,不为当前页面实例写“刚好适配截图”的固定宽高。

优先使用:

  • 内容固有尺寸;
  • 可伸缩轨道和剩余空间分配;
  • 最小值、最大值和比例约束;
  • 明确的父容器边界;
  • 必要时的纵横比。

紧凑控件按内容占用空间;搜索、正文、主工作区等明确需要扩展的区域才吸收剩余空间。不要让分页、状态、数量或短选择器因父级布局自动拉满。

高度默认由内容撑开。需要限制时设置最大高度并指定滚动区不通过固定高度制造空白。Flex/Grid 子项应允许在父级边界内收缩,避免长内容撑破页面。

只有以下情况才使用固定尺寸:

  • 稳定点击区域或控件规格;
  • 图标、头像、缩略图等共享视觉规格;
  • 媒体比例;
  • 虚拟化或几何计算依赖;
  • 防止关键布局跳动;
  • 视口安全边距。

固定尺寸必须说明保护的行为,并优先由共享组件、统一设计变量或布局规则负责。删除固定尺寸不会破坏行为时,改回内容驱动。

滚动由谁负责

每个表面默认只指定一个主滚动容器:

  • 应用外壳固定时,让主内容区滚动;
  • 普通页面由主内容区滚动;
  • 弹窗由 Body 滚动;
  • 表格仅在自身容器中横向滚动;
  • 独立面板只有在用户确实需要分别浏览时才拥有内部滚动,并必须具有明确任务边界和尺寸边界。

所有滚动容器必须具有明确尺寸边界。Grid 或 Flex 子项需要 min-height: 0 / min-width: 0,避免内容撑破父容器。

禁止:

  • body、页面内容和弹窗同时滚动;
  • 弹窗整体滚动导致标题和操作消失;
  • 无尺寸上限的内容把弹窗推出视口;
  • 页面整体出现水平滚动条;
  • 为解决溢出直接添加 overflow: auto
  • 多层嵌套滚动却没有独立任务边界。

弹窗结构

存在正文和操作的弹窗必须使用共享 Header / Body / Footer 三段式结构。

共享弹窗需要满足:

  • 弹窗根容器使用“内容上限 + 动态视口边界”,不能依靠固定高度填满屏幕;
  • Header 固定顶部,拥有标题、必要身份和关闭入口;
  • Body 使用剩余空间并作为唯一纵向滚动区;
  • Footer 固定底部,完整跨越弹窗内容宽度;
  • Header 和 Footer 使用稳定边界及组件内间距;
  • 使用弹窗的页面不得自行覆盖弹窗内部布局。

该差异应成为含义明确的共享组件变体,不使用页面专属样式类修补。

操作栏

弹窗存在保存、完成、确认或取消动作时:

  • 所有完成当前弹窗任务的操作放入 Footer
  • 主操作位于右侧并保持最高强调;
  • 取消或返回紧邻主操作,使用次级样式;
  • 危险确认与普通操作明确分隔;
  • 提示、计数或校验摘要可放 Footer 左侧;
  • Footer 不随 Body 滚动;
  • 内容区按钮只处理局部内容,不承担完成整个弹窗的任务。

纯阅读详情没有提交动作时可以只保留关闭入口,不为形式完整强加 Footer。

承载方式:弹窗、抽屉与完整页面

先检查项目已有的表面组件和同类任务页面;既有用法符合当前任务和本规范时才沿用,否则依据以下因素修复或替换共享承载方式。

弹窗适合:

  • 自包含的短任务:确认、简短表单、预览 + 配置;
  • 任务有明确的完成边界,完成后回到原页面位置和对象。
  • 宽度由内容复杂度决定:确认使用窄弹窗,常规表单使用中等宽度,预览 + 配置使用宽弹窗或双栏;不通过继续扩大弹窗承载已经符合完整页面条件的任务。

抽屉适合:

  • 用户需要保持底层列表、表格或画布的位置和当前对象可见;
  • 任务是对当前选中对象的补充查看或编辑,例如行详情、筛选面板、辅助配置;
  • 内容以单向浏览或单侧编辑为主,不需要多区域并行。

完整页面或工作区适合:

  • 多步骤、复杂创作、大量媒体或多层导航;
  • 任务本身就是用户的主要目的地,而不是某个页面的附属动作;
  • 内容需要两个以上主要滚动区,或用户需要频繁在多个区域间切换。

其他约束:

  • 不在一个模态弹窗上继续叠加第二个模态弹窗;菜单、下拉和 tooltip 不计入模态层级。需要第二层完整任务时升级为抽屉或页面。
  • 项目没有抽屉组件时,不为单次需求引入新表面;确有需要时先建共享组件再在页面使用。
  • 承载方式确定后,关闭或返回必须回到原位置和原对象。

响应式

  • 使用动态视口高度,避免移动端地址栏造成溢出。
  • 保留视口安全边距。
  • 双栏在宽度不足时改单列。
  • 移动端 Footer 可堆叠或让主操作占满宽度,但仍固定在弹窗底部。
  • 检查长名称、校验错误和移动端输入面板出现后是否溢出或遮挡操作。

审查问题

  • 首屏是否能完成主要判断或动作?
  • 是否在纵向堆叠本可并列的信息?
  • 哪些区域按内容尺寸,哪些区域吸收剩余空间?
  • 每个固定宽高保护了什么行为?
  • 谁拥有页面的纵向滚动?
  • 是否出现意外的第二层滚动?
  • 弹窗 Header 和 Footer 是否始终可见?
  • Footer 是否为弹窗直接结构,而非某个内容列的子元素?
  • 操作按钮是否稳定出现在底部栏?
  • 内容变长后是否只滚动 Body
  • 宽表格是否只在自身容器横向滚动?
  • 当前任务是否已经复杂到应该使用独立页面?