Skip to content

fix(examples): showcase home page "Create Task" button now carries element:button's inline action - #6737

Merged
os-project-manager merged 1 commit into
mainfrom
claude/issue-6597-showcase-button-action
Aug 8, 2026
Merged

fix(examples): showcase home page "Create Task" button now carries element:button's inline action#6737
os-project-manager merged 1 commit into
mainfrom
claude/issue-6597-showcase-button-action

Conversation

@os-project-manager

@os-project-manager os-project-manager commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Fixes #6597

What changed

One line — the primary CTA of showcase_component_gallery (the showcase home page) in examples/app-showcase/src/ui/pages/index.ts:

- { type: 'element:button', properties: { label: 'Create Task', actionName: 'showcase_new_task' } },
+ { type: 'element:button', properties: { label: 'Create Task', icon: 'plus',
+     action: { name: 'showcase_new_task', type: 'modal', target: 'showcase_task', refreshAfter: true } } },

Per the triage ruling: fix the corpus, not the contract. No change to packages/spec, no change to the renderer, no change to lint. The declaration side (action) and the renderer have agreed all along — this one piece of corpus was the wrong side.

I also added a comment explaining the trap itself. The corpus is read by humans and copied by AI authors, so "why action and not actionName" is worth more sitting next to the line than sitting in an issue.

Precondition: is showcase_new_task a registered action?

Yes. examples/app-showcase/src/ui/actions/index.ts:177 defines NewTaskAction: type: 'modal', objectName: showcase_task, locations: ['global_nav'], refreshAfter: true, target: 'showcase_component_gallery'.

But there is a fact here that decides what belongs inside action, and it needs stating plainly: element:button carries an inline action (InlineActionSchema) — it is not a by-name reference into the action registry. By-name reference is action:button. The ActionRunner's modal branch reads action.modal || action.target || action.params?.schema; name is only an identifier and triggers no registry lookup at all. So the type/target written inline are the dispatch — they have to be spelled out in full.

Which is why I ran both spellings in a real browser instead of copying the registry entry blind:

Spelling Measured result
target: 'showcase_component_gallery' (copy the registry) Dialog opens, titled "Component Gallery", containing this very home page, with 0 form controls
target: 'showcase_task' (this PR) Dialog opens on the Task create form, 7 controls (Title* / Project* / Assignee / Status* / Priority / Due Date); submitting really creates a record

Copying the registry does "do something" — but a button labelled "Create Task" that wraps the home page inside a dialog creates no task, and this page's own docblock is explicit that it is "a clean welcome landing … and a primary action". A type: 'modal' action with a string target is resolved by objectui's useActionModal.resolveModalTarget page-first, then object; showcase_task is not the name of any page, so it lands on the object and opens the create form. That is what the label says it does.

The registry entry's own target pointing at showcase_component_gallery (the global_nav command-palette "New Task" wraps the home page in a dialog for the same reason) is out of scope here and filed separately as #6739 — deliberately not fixed in this PR.

Acceptance evidence: the click was actually run

The card noted this was only ever measured statically, never clicked. It has now been clicked — a real headless-chromium browser driving the showcase booted with os dev --ui, signed in, at /_console/apps/com.example.showcase/page/showcase_component_gallery.

Before (a no-op, matching the issue):

[before] button visible: true | enabled: true
[before] after click  — dialogs: 0
[before] network requests fired by the click: []
[before] toasts: []
[before] VERDICT dialogsBefore=0 dialogsAfter=0 urlChanged=false

The button renders, is clickable, disabled is false — and the click fires not a single request: no dialog, no navigation, no error.

After:

[final] dialog opened; controls: 7
[final] network requests fired by the click: ["GET /api/v1/meta/page/showcase_task"]
[final] project suggestions: 5 "Mobile App…"
[final] dialogs after submit: 0
[final] toasts: ["Action completed successfully"]

The dialog is the Task create form (Title* / Project* / Assignee / Status* / Priority / Due Date + Cancel / Create). Filling only Title and pressing Create triggers validation as expected ("Project is required" plus the toast "Please check the highlighted fields: Project"); filling the rest and submitting closes the dialog with a success toast.

Server-side confirmation (not just the UI):

showcase_task total: 12          # 10 seeded rows, plus one per acceptance run
 created: UvIhd9YX0yaEainn | Dogfood 6597 task 1786195341594 | project: 9ic7y91bi9fN-AKW | status: backlog
 created: uf3LN21Th4gRbGtB | Dogfood 6597 task 1786194880686 | project: 9ic7y91bi9fN-AKW | status: backlog

os validate before/after

Real run over the showcase corpus, pnpm --filter @objectstack/example-showcase validate:

component-props-unknown-key (this page) all ⚠
Before 1 47
After 0 46

The warning that was there before:

⚠ page "showcase_component_gallery" · element:button: `actionName` is not a prop
  `element:button` declares (ComponentPropsMap, @objectstack/spec/ui), so nothing verifies it …

After the change the whole corpus has zero is not a prop hits, and the total warning count drops by exactly one (the other 46 are untouched). This is one of the two entries on #5068's list blocking its error upgrade; the other one (the action.params shape) is tracked by #5777 and is not part of this issue.

Tests and gates

  • pnpm --filter @objectstack/example-showcase typecheck → pass
  • pnpm --filter @objectstack/example-showcase test15 files / 154 tests passed
  • pnpm --filter './examples/*' run typecheck → all Done
  • pnpm lint → EXIT=0
  • All 31 check:* gates enumerated one by one from .github/workflows/lint.yml → all EXIT=0 (including check:nul-bytes)
  • check:type-check-coverage / check:driver-conformance / check:stall-guard / check:skill-frame-sync / check:skill-compatibility / check:i18n / check:i18n-coverage / check:app-nav-i18n → all EXIT=0

Changeset

None; labelled skip-changeset. @objectstack/example-showcase is private: true and is not in the fixed list of .changeset/config.json — the package publishes nothing, so this PR carries no user-visible release.


Generated by Claude Code

`showcase_component_gallery` 的主 CTA 之前授权的是 `actionName: 'showcase_new_task'`
—— `ElementButtonPropsSchema` 从未声明这个键。schema 是 strip 模式,parse 直接把它
剥掉;renderer 只读 `props.action`,`handleClick` 第一行就是 `if (!action) return`。
结果是按钮正常渲染、正常可点,点击完全空转:不发请求、不开弹窗、不导航。

`element:button` 携带的是**内联** action(InlineActionSchema),它本来就不是"按名
引用已注册动作"——那是 `action:button`。所以修的是语料这一处,不是契约。

`type: 'modal'` + 字符串 `target` 由 objectui 的 `useActionModal.resolveModalTarget`
先按 page、再按 object 解析;`showcase_task` 不是任何 page 的名字,于是落到对象上,
打开 Task 的新建表单 —— 这才是一个写着 "Create Task" 的按钮该做的事。

Fixes #6597

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F8q5J1MQyocgtNspb15fSn
@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 8, 2026 1:50pm

Request Review

@github-actions github-actions Bot added the size/s label Aug 8, 2026
@os-project-manager
os-project-manager marked this pull request as ready for review August 8, 2026 13:50
@os-project-manager os-project-manager added skip-changeset PR has no user-facing published change; bypasses the changeset gate and removed size/s labels Aug 8, 2026 — with Claude
@os-project-manager os-project-manager changed the title fix(examples): showcase 首页 "Create Task" 按钮改用 element:button 的内联 action fix(examples): showcase home page "Create Task" button now carries element:button's inline action Aug 8, 2026
@os-project-manager
os-project-manager added this pull request to the merge queue Aug 8, 2026
Merged via the queue into main with commit 087af44 Aug 8, 2026
31 checks passed
@os-project-manager
os-project-manager deleted the claude/issue-6597-showcase-button-action branch August 8, 2026 14:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

showcase 的 component-gallery 在 element:button 上授权 actionName,renderer 只读 action —— "Create Task" 按钮点了没反应

2 participants