Skip to content

fix(app-shell): Studio's rails mark a customization with a short word, no fill, instead of a filled plus that read as an add button - #30468

Merged
objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/project-thread-p3zei2
Nov 5, 2026
Merged

objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/project-thread-p3zei2

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

domain:ui#5 · os-sales · session_01L6bhgXtD8kC2LpK5YoB2sK

Requested by Sales · project thread

Fixes #30070

Clause-②: yes (widening)
Metadata-protocol: none

维护者速读

  • 改了什么:Studio 左栏里定制过的行,原来右侧是一个带底色的小方块图标(新增是绿底加号),现在改成一个彩色短词、没有底色:中文「定制」「新增」,英文「Custom」「Added」。鼠标悬停的提示和读屏名称不变,仍是完整说明(「已定制(CRM)」加定制包那句话)。
  • 为什么改:绿底加号看起来像「添加」按钮,维护者点过一次没反应;裁决 6631229752 选 A:用文字、不要底色、保留提示、点击仍只是选中这一行。
  • 风险与回滚:只改一个展示组件的紧凑分支和一个新词条(en/zh 各一行),不动数据和接口;英文比原来的 18px 图标宽约 22px(Custom 40px),行名会多截一点;回滚即还原本 PR。
  • 先看:ui/packages/app-shell/src/views/studio-design/CustomizationMark.tsx 的 if (compact) 分支、StudioDesignSurface.oneSurface-28572.test.tsx 的「the rail mark never takes the row’s name」用例、ui/packages/i18n/src/namespaces/studio/en.ts 的 engine.customizationMark.customizedShort。
  • 两分钟验证:pnpm --dir ui exec vitest run packages/app-shell/src/views/studio-design/StudioDesignSurface.oneSurface-28572.test.tsx,预期 27 个用例全绿。
  • 需要你做的:无,席位落地。

What changes

  • The compact mark. CustomizationMark's compact branch (every pillar rail row through RailCustomizationMark, and the Interfaces rail's navigation-override mark, which wraps it in its popover button) no longer draws an 18×18 filled block with a lucide glyph. It prints one short word in the kind's colour with no background: customized reads the new engine.customizationMark.customizedShort (定制 / Custom), added reads the existing engine.customizationMark.added (新增 / Added). Its role="img", accessible name (the full label, e.g. 已定制(HotCRM)) and tooltip (that label, then the sentence naming the pair) are unchanged. It carries no handler: a click on it is a click on its row.
  • The non-compact chip (All metadata lists) is unchanged.
  • i18n (the widening). One new studio namespace row in en and zh: engine.customizationMark.customizedShort.
  • Comments. CustomizationMark.tsx and RailCustomizationMark say the mark is a word, no fill, and not a control.
  • Changeset. .changeset/30070-customization-mark-words.md, @object-ui/app-shell and @object-ui/i18n patch.

Branch: the harness-assigned claude/project-thread-p3zei2, not claude/issue-30070-*; the card is #30070.

Tests

StudioDesignSurface.oneSurface-28572.test.tsx's rail-mark case (it pinned textContent '') now pins: the customized mark prints engine.customizationMark.customizedShort, the added mark prints engine.customizationMark.added, both keep the full label as accessible name and tooltip head, neither holds an svg, and neither carries a bg- class. Expectations are read from Studio's table, never retyped.

Acceptance notes

  • The English word is Custom, not Customized. The ruling names the zh words only. Measured on the example CRM's automations rail (row 223 px wide): 定制 and 新增 are 22 px each (the glyph was 18 px), Added is 34 px, Customized was 61 px and cut the selected row to "Convert Lea…", Custom is 40 px. The seat may prefer another word; it is one en row.
  • InterfacesNavRail.tsx was not edited (PR feat(app-shell): Studio opens an off-nav list view on its object's page, lists only views no dropdown reaches, and reads form views as forms #30401 holds it). Its InterfacesNavOverrideMark doc comment still says "the compact customized glyph"; the comment is now stale wording only, behaviour measured below. Left for whoever next touches that file.
  • KIND_CLASS (the filled colours) now serves the non-compact chip only; customizationOf has no compact caller and would print its full label if one appeared.

Verification

Gates and tests ran on cabd8ba8; the head adds an evidence commit and its removal, the tree is byte-identical (git diff cabd8ba8 HEAD is empty). Base b6caa141.

Live rig and screenshots (zh-CN and en-US, 1440 wide)

examples/app-crm objectstack dev --seed-admin --fresh on a private port, the console via vite in ui/apps/console with DEV_PROXY_TARGET, Chromium. POST /api/v1/packages/com.example.crm/ensure-customization made com.example.crm.custom; through that pair, an override of flow crm_convert_lead_wizard and of app crm_app (navigation), and a new flow crm_custom_follow_up_reminder, each saved as a draft and published. Before = CustomizationMark.tsx restored to the base on the running vite, then restored to HEAD (blob equal).

Measured marks (data-testid="customization-mark"): before, every mark 18 px wide with a filled background and an svg; after, background transparent, no svg, widths 定制 22, 新增 22, Custom 40, Added 34. Clicking the Interfaces heading mark still opens the override popover with 恢复软件包原版; clicking the 新增 mark on a rail row selects that row (?surface=flow:crm_custom_follow_up_reminder).

Before, automations, zh / en:
before automations zh
before automations en

After, automations, zh / en:
after automations zh
after automations en

Before / after, interfaces (navigation-override mark beside the heading), zh / en:
before interfaces zh
after interfaces zh
before interfaces en
after interfaces en

After, the override popover still opens from the mark:
after popover

Tests, ablation, typecheck, lint
  • Every test file that names the mark (git grep for customization-mark, CustomizationMark, customizationMark., RailCustomizationMark, if-nav-override-mark under ui/**/*.test.ts*: 9 files) plus packages/i18n/src/__tests__/studio-namespace.test.ts and studio-namespace-lazy.test.tsx: Test Files 11 passed (11), Tests 230 passed (230), lock VERDICT command-exit 0. A first run over all of studio-design/ and metadata-admin/ (556 files) was stopped for time; CI's Test UI runs the full set.
  • Ablation 1 (scripts/ablation-replace.mjs, anchor x1 to x0): the compact word replaced by {null}: 1 failed / 26 passed (expected '' to be 'Custom'). Restored, blob equals HEAD, git diff HEAD empty.
  • Ablation 2: the compact class list given the filled KIND_CLASS back: 1 failed / 26 passed (not to match /(^|\s)bg-/). Restored, blob equals HEAD.
  • pnpm --filter @object-ui/i18n --filter @object-ui/app-shell type-check (both tsc --noEmit and tsc -p tsconfig.test.json): lock VERDICT command-exit 0.
  • pnpm --dir ui run check:spec-symbols: exit 0.
  • eslint on the five changed source files: exit 0, warnings only on lines this PR does not change.
  • pnpm check:new-line-citations (ui): 0 new citations, exit 0.
Derived gates (35/35 exit 0)

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 35 families at cabd8ba8; every one ran and exited 0. --ran reconciliation: 35 derived, 35 run, 0 NOT-MEASURED (a derived zero, every line carries an exit code). pnpm --dir ui exec vitest run scripts/: 170 files passed, 2 skipped; 4985 tests passed, 2 skipped. CI runs the rest.


Generated by Claude Code

🤖 Generated with Claude Code

https://claude.ai/code/session_01L6bhgXtD8kC2LpK5YoB2sK

…ill, instead of a glyph that read as an add button

The compact customization mark now prints 定制 / Customized for a
customized row and 新增 / Added for an added one, in the kind's colour
with no background. Its accessible name and tooltip keep the full text
and the sentence naming the pair. New studio key
engine.customizationMark.customizedShort (en, zh).

Claude-Session: https://claude.ai/code/session_01L6bhgXtD8kC2LpK5YoB2sK
Co-authored-by: Claude <noreply@anthropic.com>
Customized measured 61 px on the 223 px automations rail and cut the
row's name to "Convert Lea"; Custom is 40 px (定制 is 22 px).

Claude-Session: https://claude.ai/code/session_01L6bhgXtD8kC2LpK5YoB2sK
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation tooling labels Nov 5, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#5 · os-sales · session_01L6bhgVwQZbHRRM9CaXeKif

Contract review

Served-tier: TIER_DEFAULT
Head-sha: b3864c849d849fbc93b43071e89b512982d8a0d8
Local-runs: none

Reviewed 2026-11-05T12:43Z. Face: the Clause-②: yes (widening) declaration alone (PR body and changeset). The committed tree touches no packages/spec/src/**, no governed path (check-governed-merges --pr 30468: 0 of 6 paths hit the register) and narrows nothing.

① Derived judgments

  • @object-ui/i18n gains one studio namespace key, engine.customizationMark.customizedShort, in both files the namespace has (en.ts "Custom", zh.ts "定制"). It takes no placeholder. No key is renamed or removed and no existing value changes, so the published key set only grows. ✔
  • CustomizationMark's exported props are unchanged. compact keeps its type; only its rendering (a word in place of a glyph) and its doc comment change. KIND_ICON was module-private. The non-compact chip is byte-identical. ✔
  • Accessible name and tooltip are unchanged (aria-label={label}, title = label then the pair sentence), pinned by the rail-mark case. ✔

② Semver level

  • .changeset/30070-customization-mark-words.md: @object-ui/app-shell patch and @object-ui/i18n patch, declared Clause-②: yes (widening) / Metadata-protocol: none. An additive key at patch matches the lane's precedent (.changeset/30335-datasource-delete-names-bound-objects.md, the same two packages, the same declaration). ✔

③ Boundary flags

  • None on the contract. The dev noted that customizationOf has no compact caller (CustomizationMarkKind is 'customized' | 'added' in customizationMarks.ts:29, so RailCustomizationMark cannot pass it); a future compact caller would print the full label. Latent, not a contract change.
  • Author check: the PR's user.login is objectstack-fleet[bot] (relay pr_create).

Implemented-by: session_01L6bhgXtD8kC2LpK5YoB2sK
Reviewed-by: session_01L6bhgVwQZbHRRM9CaXeKif

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#5 · os-sales · session_01L6bhgVwQZbHRRM9CaXeKif

维护者速读

  • 改了什么: Studio 左栏里定制过的行,右侧原来是一个带底色的小方块图标(新增是绿底加号),现在改成一个彩色短词,没有底色。中文是「定制」「新增」,英文是「Custom」「Added」。鼠标悬停提示和读屏名称不变。
  • 为什么改: [Decision] The rail's green 「+」 looks like an add button but is a status mark: what should a customization mark look like? #30070 裁决 A(6631229752)。绿底加号看起来像「添加」按钮,点了没有反应。
  • 风险与回滚: 只改一个展示组件的紧凑分支,加一个新词条(en/zh 各一行),不动数据和接口。回滚就是撤销本 PR。
  • 需要您做的: 无。本 PR 不在受管面,共 60 行。席位会经合并队列落地。
  • 席位意见: ACCEPT。

席位核对 — ACCEPT · domain:ui#5 · head b3864c849d849fbc93b43071e89b512982d8a0d8

  • 形态: draft,作者 objectstack-fleet[bot](中继 pr_create),无 assignee,无 review request,目标 main,Fixes #30070。共 6 个文件,+39 −21。check-governed-merges --pr 30468:NOT governed;60 行,未超 3000。mergeable_state 读为 clean。
  • 契约面: 不碰 packages/spec/**,不碰 governed 路径。Clause-②: yes (widening) 只来自新 studio 键 engine.customizationMark.customizedShort。TIER_DEFAULT 合同复核 PASS 6658291542,复核的就是这个 head。Metadata-protocol: none 与 diff 一致。
  • 裁决对照: A 要求三点。用文字(customized → customizedShort,added → 已有的 added):做到。不要底色(compact 分支改用 KIND_TEXT_CLASS,只有文字颜色):做到。保留提示,点击仍只选中这一行(aria-label 和 title 不变,标记上没有 handler):做到。
  • 抽查: KIND_ICON 和 lucide import 一并删掉,没有留下死代码。非 compact 的 chip(All metadata 列表)没有变。CustomizationMarkKind 只有 'customized' | 'added'(customizationMarks.ts:29),所以 rail 不可能传 customizationOf。
  • 门禁 check-runs: b3864c84 上 55 个 run:44 success,11 skipped,0 失败。
  • 测试: rail-mark 用例原来钉的是 textContent '',现在钉住:两个词都从 Studio 的词表读取,不在测试里重打;完整 label 仍是读屏名称和提示首行;标记里没有 svg,也没有 bg- class。卡线程报告:受影响 11 个文件 230 条用例全绿,两次消融都转红,还原后转绿。
  • 串行约束: 没碰 InterfacesNavRail.tsx(PR feat(app-shell): Studio opens an off-nav list view on its object's page, lists only views no dropdown reaches, and reads form views as forms #30401 持有)和 StudioDesignSurface.tsx。
  • 接受的偏差:
    • 英文用 Custom,不用 Customized。裁决只定了中文的词。实测在 223px 宽的行上,Customized 占 61px,会把选中行名截成 "Convert Lea…";Custom 占 40px。
    • InterfacesNavRail.tsx 里 InterfacesNavOverrideMark 的文档注释还写着 glyph,只是措辞过期,行为已实测。留给下一个改那个文件的人。
    • 证据提交 cf6a0b46 在下一笔里删掉了,最终树和 cabd8ba8 逐字节相同;squash 合并不会把它带进 main。
  • 范围外去向: 无。
  • 落地条款: Fixes #30070。本席位按普通队列在这个 head 上落地:relay pr_ready + automerge_enable。MERGED 后核对 [Decision] The rail's green 「+」 looks like an add button but is a status mark: what should a customization mark look like? #30070 已关闭、pm:dispatched 已摘。

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 5, 2026 12:59
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 5, 2026 12:59
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 5, 2026
Merged via the queue into main with commit 0c7e95a Nov 5, 2026
56 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-p3zei2 branch November 5, 2026 13:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Decision] The rail's green 「+」 looks like an add button but is a status mark: what should a customization mark look like?

1 participant