Skip to content

Commit 34c4df7

Browse files
zhuangjianguoclaude
andcommitted
docs(actions): document that body is script-only and how a modal target resolves
Keeps the two action docs in sync with the parse-time rule added in this PR (and with the console-side target resolution in objectui#2826): - ui/actions: a second "trap" callout next to the existing dead-button one — a `body` on a non-script action is rejected, with `type: 'script'` + `params` named as the shape for "collect input, then run logic". - protocol/objectui/actions: `body` on a non-script type is now a parse-time error, not just "not meaningful"; the Modal Actions section states the page → object → server-handler resolution order and that `params` are collected before the target opens. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KYuc9N6YRbvoDMbCvJiX9f
1 parent 85ea69f commit 34c4df7

2 files changed

Lines changed: 15 additions & 2 deletions

File tree

content/docs/protocol/objectui/actions.mdx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ The `type` field selects how an action is dispatched. The complete enum is **`sc
5555

5656
### Script Actions
5757

58-
Run logic with no server round trip via `body` (an L1 CEL expression or L2 sandboxed JS). `body` is only meaningful when `type` is `script`.
58+
Run logic with no server round trip via `body` (an L1 CEL expression or L2 sandboxed JS). `body` is only meaningful when `type` is `script`, and declaring one on any other type is a parse-time error — those types dispatch on `target`, so the body would never be invoked.
5959

6060
```yaml
6161
name: greet_user
@@ -142,7 +142,7 @@ target: customer_quick_edit
142142

143143
### Modal Actions
144144

145-
Open a modal/page by name:
145+
Open a modal/page by name. `target` is resolved as a **page** first, then as an object (which opens that object's create/edit form); when it names neither, the action falls through to its server-side handler.
146146

147147
```yaml
148148
name: edit_customer
@@ -151,6 +151,8 @@ type: modal
151151
target: customer_edit_modal
152152
```
153153

154+
A modal action may also declare `params` — the renderer collects them in a dialog before opening the target. It may **not** declare a `body`: see [Script Actions](#script-actions) above, and use `type: script` when the goal is to collect input and then run logic.
155+
154156
## Action Configuration
155157

156158
### Action Properties

content/docs/ui/actions.mdx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,17 @@ rejected at authoring time.) Also note the handler's `engine` facade is
126126
caller-specific rules yourself.
127127
</Callout>
128128

129+
<Callout type="warn">
130+
**`body` belongs to `script` only.** Every other type dispatches on `target`
131+
— the page to open, the URL, the flow, the endpoint — so a `body` on a
132+
`modal`/`url`/`flow`/`api`/`form` action would never be invoked. Writing one
133+
(typically `type: 'modal'` with `params` and a `body`, expecting the body to
134+
run when the modal is submitted) is rejected at authoring time rather than
135+
shipping a button that opens a modal and silently writes nothing. To collect
136+
input *and* run logic, use `type: 'script'` with `params` — the same dialog
137+
is collected, then the body runs with those values as its `input`.
138+
</Callout>
139+
129140
## Bind it to the UI
130141

131142
`locations` is the primary binding — the action appears wherever it declares:

0 commit comments

Comments
 (0)