尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Sim 前端工程规范:让列表与菜单“自己排序“——Sim 的 List Menu Ordering 设计规则与源码实现

发布时间:2026/9/10 9:20:23

资讯中心
01
ARTICLE

Sim 前端工程规范:让列表与菜单“自己排序“——Sim 的 List Menu Ordering 设计规则与源码实现

Sim 前端工程规范:让列表与菜单“自己排序“——Sim 的 List  Menu Ordering 设计规则与源码实现
Sim 前端工程规范让列表与菜单自己排序——Sim 的 List Menu Ordering 设计规则与源码实现【免费下载链接】simSim is the collaborative workspace to build, deploy, and monitor AI agents and workflows. Used by 100,000 builders.项目地址: https://gitcode.com/GitHub_Trending/sim16/sim本篇讲解 SimSim Studio仓库内一条被正式写入工程规则的前端设计规范——List Menu Ordering列表与菜单排序。这条规则回答一个具体而高频的 UI 问题当同一组条目在工作区第二次、第三次出现下拉框、右键菜单、命令面板、设置导航时应该按什么顺序排列、在哪里加分隔线。读完本文你将掌握 Sim 团队如何把顺序作为列表最廉价的交互抓手来治理如何用单一共享常量RESOURCE_MENU_ORDER保证多个界面不漂移以及如何写出两侧保证非空的DropdownMenuSeparator守卫条件并能对照 规则文档 与 resource-registry.tsx 等源码逐条验证。一、核心原则列表应该按用户已经读过的顺序自我排序规则的出发点在 sim-list-ordering.md 开篇下拉框、上下文菜单、Tab 条、命令面板、设置导航本质上都是用户已经见过的同一组条目的第二次呈现——用户在侧边栏、工具栏、表头行里先见过它们。如果第二次呈现重新排序用户每次都要从头重读一遍。文档特别强调这不只是风格偏好顺序是列表最廉价的交互抓手affordance也是唯一做对了零成本的东西。规则的表述非常干脆在写一个条目列表之前先找到用户第一次看到这些条目的界面那个界面拥有顺序你的列表镜像它。文档给出了一张列表 → 镜像来源的映射表必须完整继承列表镜像来源资源菜单附加、提及、资源 Tab 的工作区侧边栏自上而下行/根节点右键菜单该界面的工具栏从左到右 → 从上到下设置 Tab 条、最近删除 Tab设置导航自上而下New … 菜单这些对象创建后出现的顺序两个补充约定从左到右转换为从上到下工具栏读作Filter · Sort · Export · Delete菜单就应读作 Filter、Sort、Export、Delete——不按字母排序、不按实现分组除非工具栏本身就把它放最后否则不做破坏性操作永远放最后的处理。平台专属条目靠后桌面端专属的Browser和Terminal条目放在共享集合之后trail 而非 interleave保证所有平台上公共前缀完全一致。二、分组分隔线rule的判定标准只有一条顺序由上面的规则治理分隔线由另一条规则治理一条DropdownMenuSeparator有资格存在当且仅当下一个分组不再作用于用户点击的那个东西。这是唯一的问题且在每个菜单里都用同样的方式问一次分组前面是否要加 rule作用于被点击条目本身open、rename、duplicate、export、copy、edit、pin、run否——这是菜单的主体作用于别的东西——页面的过滤/视图或新建的兄弟条目是销毁或脱离该条目delete、leave、close、hide、remove是由此得出几个可直接执行的推论大多数行菜单只有一个转场因此只带一条 rule紧跟在Delete之前同时会过滤页面或插入兄弟条目的菜单带两条任何菜单都不会超过两条因为菜单作用对象不存在第三种。不要按动词分带band by verb。Navigation、status、edit、copy 是对动词是什么的分类而不是对它作用在什么上的分类——用户在任何地方都没见过这种分类法。应用里所有工具栏都是无分隔符的扁平gap-1chip 行按动词分带的菜单会让同一个动作因可见兄弟条目不同而落入不同分组。只有被disabled的分组不加额外 rule——disabled不构成分组。破坏性分组几乎总是垫底唯一例外是 logs 行菜单那里Retry与Cancel Run作用于运行本身是失败场景下的主操作所以放在最上面、rule 在其下方。顺序仍遵循镜像界面的规则分隔线只负责把该分组占据的那一端围起来。文档给出的对比示例原文照录// ✗ Bad — four semantic bands the user meets nowhere else Open in new tab │─── Rename, Lock │─── Duplicate, Export │─── Delete // ✓ Good — one rule, where the menu stops acting on the workflow Open in new tab, Rename, Lock, Duplicate, Export │─── Delete实际案例logs 行菜单带两条 rule——Retry, Cancel Run │ Copy Run ID, Copy Link, Open Workflow, Open Snapshot │ Filter by Workflow, Clear Filters分别对应该次运行 → 这条日志 → 该页面三级作用对象。表格的行菜单与列菜单也带两条Insert row above/Insert column left之前的 rule正是菜单停止作用于被点击单元格、开始创建兄弟条目的边界。三、把顺序只编码一次RESOURCE_MENU_ORDER常量在多个界面重复的顺序就是会漂移的顺序。Sim 的做法是导出一个常量并按它排序而不是为每个菜单手维护一份匹配的字母表。代码库中的标准实例是 resource-registry.tsx其中定义了全部资源族的纵向顺序镜像工作区侧边栏以及配套的排序函数/** * Top-down order for every menu that lists resource families, mirroring the * workspace sidebar so a user reads the same sequence in both places. ... */ export const RESOURCE_MENU_ORDER: readonly MothershipResourceType[] [ integration, task, table, file, filefolder, knowledgebase, log, workflow, folder, browser, terminal, generic, ] /** Sorts anything keyed by resource type into RESOURCE_MENU_ORDER. */ export function byResourceMenuOrderT extends { type: MothershipResourceType }( a: T, b: T, ): number { return RESOURCE_MENU_ORDER.indexOf(a.type) - RESOURCE_MENU_ORDER.indexOf(b.type) }注意常量注释里的细节它们补充了规则文档未展开的实现语义browser/terminal作为桌面端专属面板排在工作区资源之后与它们在应用中的呈现位置一致——这正是平台专属条目靠后原则在常量中的落点folder/filefolder从不作为独立条目渲染它们喂给各自资源族的目录树但仍被排进常量保证将来某个菜单真的呈现它们时也落在正确位置。该常量通过 index.ts 统一导出被多个消费方引用提及预览的 plus-menu-dropdown.tsx、附加资源下拉的 add-resource-dropdown.tsx以及资源 TabuseAvailableResources/ResourceMenuSections所在目录。也就是说资源菜单的三种第二次呈现——附加、提及、Tab 的——共用同一份顺序定义从结构上消除了彼此漂移的可能。这套顺序不是纸面约定有测试背书resource-mention-items.test.ts 中的byResourceMenuOrder用例断言排序后task → workflow → log → browser即 workflow 被排到 log 之前且不影响周边顺序同文件还验证了桌面 Tab 提及Browser/Terminal 资源条目在前、实时 Tab 条目垫后与预览截断buildMentionPreview按族设上限、保持族顺序连续等行为覆盖了规则文档中平台条目不 interleaving与预览不破坏族内连续性的要求。四、单趟渲染顺序常量最常见的失效方式规则文档指出标准顺序被静默击败的最常见方式是按渲染种类分阶段输出先把某一类的条目全部渲染完再渲染另一类——结果所有带子菜单的族无条件排在所有扁平族之上无论顺序常量怎么写。// ✗ Bad — two phases; the trees always pin to the top ResourceTreeSections sections{treeSections} / {groups.filter((g) !FOLDERED.has(g.type)).map(renderFlat)} // ✓ Good — one ordered pass; each entry picks its own rendering {entries.sort(byResourceMenuOrder).map((entry) sectionByType.has(entry.type) ? renderTree(entry) : renderFlat(entry) )}正确的做法是按顺序常量排好序后单趟遍历每个条目自己选择渲染方式。文档同时列出了同一陷阱的三种变体先渲染 pinned 的、再渲染其余的、先 enabled 再 disabled、先分组条目再散落条目——它们的共同点都是用一个与顺序无关的维度做切分把用户读到的顺序顶掉。五、允许偏离标准顺序的三种情况只有用户可感知的原因才允许偏离镜像顺序搜索/过滤结果按匹配质量排序——排序胜过位置正是这类界面的意义所在用户可控的顺序拖拽重排、手动sortOrder凌驾于任何标准顺序之上最近使用列表如 Recent chats按时间排序因为时间本身就是用户在别处读它的顺序。文档明确列举了三种不是理由的说法按提供它们的 hook 分组、字母序因为这样省事、数组就是这样构建的。六、唯一例外模拟原生菜单的分组带编辑器右键菜单editor-context-menu.tsx、终端右键菜单terminal-context-menu.tsx以及浏览器页面菜单browser-session.tsx各自镜像用户已经熟悉的操作系统菜单——剪贴板分带Cut · Copy · Paste │ Select all是机器上每一个文本框都教给用户的约定。这些菜单保留原生分带。文档强调这是与排序规则同一个原则镜像用户已经在读的那个界面。判据是Sim 之外是否有一个真实的菜单教过用户这个分组而自有的资源、行、动作菜单没有这种先例它们镜像的工具栏是扁平的因此只取单条 rule。七、分隔线守卫两侧都必须保证非空这是文档中工程密度最高的一条写分隔线守卫时必须使用两侧条目的精确渲染条件逐字组合绝不使用更松的近似。// ✗ Bad — showLeave alone, while the Leave item needs showLeave onLeave. // A caller passing showLeave from a permission check with a conditional // onLeave renders a trailing rule under the last item. {hasActionsAbove (showLeave || showDelete) DropdownMenuSeparator /} // ✓ Good — each term is the items own condition, verbatim const hasDestructiveSection (showLeave onLeave) || showDelete {hasActionsAboveDestructive hasDestructiveSection DropdownMenuSeparator /}失败场景很具体调用方从权限检查得到showLeave true但onLeave是条件传入的——于是 Leave 条目不渲染而分隔线渲染了菜单底部出现一条悬空 rule。文档说明这正是某次 logs 行菜单底部悬空 rule 事故的成因两条无条件分隔线压在条件条目之上。与之配套的是**不要加 prop 来移动 rule**的反模式记录共享的工作流上下文菜单曾为此长出groupNonDestructiveActions与separateNavigationAction两个 prop两者合计只为一个调用方挪了一条分隔线六个分支里四个不可达且separateNavigationAction在整个仓库中没有任何可观察效果最终双双删除。结论是想要不同分组的菜单应该要标准分组。八、评审流程一个二问检查规则的落点在 code review。文档给出固定的评审问题当某个 diff 新增或修改了一个条目列表时问——用户在哪里已经见过这组条目这个 diff 与那个地方一致吗如果答案是另一个文件里有一套不同顺序那么这个 diff 需要的不是第二份字面量而是一个共享常量。小结这条规则的可执行要点可以压缩为四句列表的顺序归属于用户第一次看到该集合的界面侧边栏/工具栏/设置导航第二次呈现只做镜像从左到右转为从上到下平台专属条目Browser、Terminal靠后分隔线只按作用对象是否改变判定作用于点击条目本身不加作用于别的东西加销毁/脱离加按动词分带一律拒绝最多两条 rule顺序只编码一次RESOURCE_MENU_ORDERbyResourceMenuOrder渲染必须单趟按序进行不能按渲染种类分阶段分隔线守卫必须逐字引用两侧条目的真实渲染条件不为挪一条 rule 增加专用 prop偏离标准顺序的理由必须用户可感知。对 Agent 协作尤其值得注意该文件位于 .claude/rules/ 目录文件头的paths字段apps/sim/app/**/*.tsx、apps/sim/ee/**/*.tsx、apps/sim/components/**/*.tsx声明了它的适用范围——AI 编程工具在改动这些路径下的界面代码时会被要求遵循本规则。配合 resource-mention-items.test.ts 这类断言顺序行为的测试Sim 把菜单该长什么样从风格品味变成了可审查、可回归的工程约束。【免费下载链接】simSim is the collaborative workspace to build, deploy, and monitor AI agents and workflows. Used by 100,000 builders.项目地址: https://gitcode.com/GitHub_Trending/sim16/sim创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。