You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fills hand-written doc + authoring-skill gaps for capabilities that shipped but
were undocumented:
- actions.mdx: add `errorMessage`/`undoable` to the field table and feedback
list; add an "Evaluation context" subsection (predicates are bare CEL against
the record; `record.<field>` resolves identically on every surface; narrower
scope than record-alert's os.*); warn against `${…}`/`{…}`-wrapped predicates.
- flow.mdx: document the `screen` node's object-form mode (`objectName`/`mode`/
`recordId`/`defaults`/`idVariable`) and the atomic parent+child save / id
rebind that powers multi-step object-form wizards.
- skills/objectstack-ui: document `disabled` (CEL, greys vs `visible` hides),
`errorMessage`, `undoable`, and the bare-CEL `record.*` predicate convention,
with a worked Reassign example.
Docs/skill only; no shipped-package changes.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: content/docs/protocol/objectui/actions.mdx
+35-1Lines changed: 35 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -180,6 +180,8 @@ interface Action {
180
180
// UX
181
181
confirmText?: string; // Confirmation message before execution
182
182
successMessage?: string; // Toast shown after success
183
+
errorMessage?: string; // Toast shown on failure (overrides the raw error)
184
+
undoable?: boolean; // Offer an Undo affordance after a single-record update succeeds
183
185
refreshAfter?: boolean; // Reload the view after execution (default false)
184
186
resultDialog?: ResultDialog; // One-shot reveal of API response values
185
187
shortcut?: string; // Keyboard shortcut, e.g. "Ctrl+S"
@@ -247,6 +249,23 @@ target: /api/orders/ship
247
249
disabled: "record.status != 'paid'"
248
250
```
249
251
252
+
<Callout type="warn">
253
+
Predicates are **bare CEL** — `record.status == 'paid'`, not `${record.status == 'paid'}` and not `{record.status} == 'paid'` (in CEL, `{…}` is a map literal). A `${…}`-wrapped or brace-wrapped predicate is not evaluated as a boolean.
254
+
</Callout>
255
+
256
+
#### Evaluation context
257
+
258
+
Action predicates evaluate against the **record the action is attached to**. Both `record.<field>` and the bare field name resolve to the current record's value:
259
+
260
+
```yaml
261
+
disabled: "record.status == 'converted'" # preferred — works on every surface
262
+
disabled: "status == 'converted'" # bare field — also resolves to the record
263
+
```
264
+
265
+
Prefer the `record.<field>` form: it reads unambiguously and resolves identically on **every** surface an action renders (`record_header`, `record_more`, `list_item`, related lists). The bare-field form is supported for brevity but is easy to confuse with a local variable.
266
+
267
+
This is a narrower scope than [record-alert](/docs/protocol/objectui/record-alert) conditions (which also expose `os.user` / `os.org` / `os.env`) — action predicates see the record only.
268
+
250
269
## Confirmation & Feedback
251
270
252
271
Actions express confirmation and feedback through dedicated string fields — there is no nested confirm-dialog object with `requireTyping`/`confirmLabel`.
@@ -265,10 +284,25 @@ refreshAfter: true
265
284
```
266
285
267
286
- `confirmText`— message shown in a confirm dialog before the action runs.
268
-
- `successMessage`— toast shown after a successful run.
287
+
- `successMessage`— toast shown after a successful run. When omitted the UI shows a generic "Action completed" toast, so set this for any action whose outcome isn't self-evident.
288
+
- `errorMessage`— toast shown when the action fails; overrides the raw server error with author-controlled copy.
289
+
- `undoable`— for a single-record update action, offer an **Undo** affordance in the success toast (and via `Ctrl+Z`). The runtime captures the record's prior values before the write and restores them on undo. Only meaningful for reversible single-record mutations.
269
290
- `refreshAfter`— reload the current view after success.
270
291
- `mode`— a semantic hint (`create` / `edit` / `delete` / `custom`) the UI uses to pick confirm copy and default variants.
271
292
293
+
```yaml
294
+
# A reversible owner reassignment: custom success/error copy + Undo
295
+
name: reassign_lead
296
+
label: Reassign Lead
297
+
type: api
298
+
target: lead
299
+
params:
300
+
- { field: assigned_to, required: true }
301
+
undoable: true
302
+
successMessage: Lead reassigned.
303
+
errorMessage: Couldn't reassign this lead — try again.
304
+
```
305
+
272
306
### Result Dialog (one-shot reveals)
273
307
274
308
For API actions that return a value the user must copy **now** (a freshly minted secret, TOTP URI, or backup codes), `resultDialog` renders the response in an acknowledge-only dialog instead of a toast:
Copy file name to clipboardExpand all lines: skills/objectstack-ui/SKILL.md
+28-4Lines changed: 28 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1088,11 +1088,35 @@ Register them under `defineStack({ actions: [...] })`.
1088
1088
|`list_toolbar`| Bulk action on selected rows (`input.selectedIds`) |
1089
1089
|`global`| Global action launcher (utility bar) |
1090
1090
1091
-
### Visibility & Confirmation
1091
+
### Visibility, Disable & Feedback
1092
1092
1093
-
Use `visible` (CEL predicate, prefer the `P\`...\`` tagged template) to
1094
-
gate the action against the current record. Set `confirmText` for any
1095
-
destructive or irreversible operation.
1093
+
-`visible` — CEL predicate (prefer the `P\`...\`` tagged template); when false the action is **hidden**.
1094
+
-`disabled` — `boolean`**or** a CEL predicate; when true the action **shows but greys out**. Use this (not `visible`) when the action should stay discoverable but locked in the current state.
1095
+
-`confirmText` — set for any destructive or irreversible operation.
1096
+
-`successMessage` / `errorMessage` — author-controlled toast copy on success / failure. Always set `successMessage` for non-obvious outcomes; without it the UI shows a generic "Action completed" toast.
1097
+
-`undoable: true` — on a single-record update, offers an **Undo** in the success toast (and `Ctrl+Z`); the runtime snapshots prior values and restores them.
1098
+
1099
+
Predicates are **bare CEL** — `record.status == "converted"`, evaluated against
1100
+
the current record. `record.<field>` resolves identically on every surface
1101
+
(`record_header`, `list_item`, …); prefer it over the bare-field form. Never
1102
+
wrap a predicate in `${…}` or `{…}` braces (see `objectstack-formula`).
1103
+
1104
+
```typescript
1105
+
exportconst ReassignLeadAction:Action= {
1106
+
name: 'reassign_lead',
1107
+
label: 'Reassign Lead',
1108
+
objectName: 'lead',
1109
+
type: 'api',
1110
+
target: 'lead',
1111
+
locations: ['record_header', 'list_item'],
1112
+
// Greys out (stays visible) once the lead is converted:
0 commit comments