Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .changeset/11168-action-family-published-inputs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
'@object-ui/components': minor
---

The four `action:*` blocks now publish the `@objectstack/spec` keys their
renderers honour, and stop publishing what the spec refuses (objectui#11168,
slice 1). Each key was decided by measuring it through `SchemaRenderer` and the
action runner, per the objectui#11111 ruling: declare what the block path
honours, refuse or retire what it does not.

Newly published, so the SDUI manifest, the JSX intrinsics and the page
validator accept them instead of reporting `unknown-prop`:

- `action:button` and `action:icon`: `visible`, `disabled`, `params`,
`description`, `openIn`, `method`, `bodyExtra`, `bodyShape`, `operation`,
`patch`, `confirmText`, `successMessage`, `errorMessage`, `refreshAfter`,
`locations`, `toast`, `resultDialog`, `onSuccess` and `objectName`; and
`recordIdField` on `action:button`. `params` is published as the list of
parameters to collect; static execution values stay under
`properties.params`.
- `action:group`: `location` and `visible`.
- `action:menu`: `size` and `visible`.

Retired and narrowed (breaking for an author who wrote them, which the spec
already refuses):

- `action:group` no longer publishes `name`. Nothing reads a group-level
`name`; each member action's own `name` identifies it.
- `actions` on `action:group` and `action:menu` is published as a list of action
objects, not an `object`. Both blocks read the key as a list, so an object
there could not render.
- `action:group.size` publishes `default`, `sm`, `lg` and `icon`, and no longer
`md`. A stored `md` still renders as before.

Still unpublished, pending a decision on objectui#11168: `endpoint` on
`action:button` and `action:icon`, and `undoable` on `action:button`. The
renderers keep forwarding both, so nothing changes at runtime.
18 changes: 18 additions & 0 deletions apps/console/src/__tests__/public-block-binding-reach.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,19 @@ const NO_DATA_REACH: Readonly<Record<string, string>> = {
// titles the panel.
'record:related_list':
'needs the parent record id from RecordContext before it may fetch; declines to fetch without one (objectstack#4413 ledger)',
// objectui#11168 slice 1 published the spec key `objectName` on the two
// action leaves, and on these blocks the key is not a data binding at all:
// it names the object the ACTION acts on. The block draws a button and
// fetches nothing; the key takes effect when the action is dispatched, where
// the server-action route becomes `/api/v1/actions/{objectName}/{action}`
// instead of the page's object. That dispatch read is pinned in
// `packages/components/src/renderers/action/__tests__/action-button-icon-inputs-11168.test.tsx`;
// what this ledger asserts is the other half — that the block still asks the
// data layer for NOTHING under that name.
'action:button':
'objectName names the object the action is dispatched against (the server-action route), not a data binding; the block renders a button and fetches nothing (objectui#11168)',
'action:icon':
'objectName names the object the action is dispatched against (the server-action route), not a data binding; the block renders an icon button and fetches nothing (objectui#11168)',

// `list-view` and `embeddable-form` were the other two entries here for
// exactly one release of this file. Neither registration bridged the
Expand Down Expand Up @@ -178,6 +191,11 @@ const EXPECTED_CANDIDATES = [
// an `objectName`, so it joins this derived population — additive, and the
// probe below is what decides whether the binding actually reaches.
'object-tree',
// objectui#11168 slice 1 published `objectName` on the two action leaves, so
// they join the population too; both are ledgered in NO_DATA_REACH, because
// on an action block the key is a dispatch target rather than a binding.
'action:button',
'action:icon',
];

/**
Expand Down
184 changes: 113 additions & 71 deletions apps/console/src/__tests__/registry-inputs-spec-parity.test.ts

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions content/docs/guide/layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,15 @@ The handler name goes in `actionType`, which `action:button` forwards to the act
runner as the action's type; the runner dispatches to the handler registered under it.
Same spelling as [Record Edit Modes](./record-edit-modes.md).

The rest of the action is authored on the same node. `action:button` and `action:icon`
evaluate `visible` and `disabled` themselves (a boolean, a CEL string, or a
`{ dialect, source }` envelope), and forward the action-definition keys to the runner:
`params`, `confirmText`, `successMessage`, `errorMessage`, `toast`, `bodyExtra`,
`bodyShape`, `operation` / `patch`, `onSuccess`, `objectName` and the others each
registration's `inputs` lists, with a `description` per key. For an `api` action, write
the request URL in `target`: `endpoint` is not published, because the console's `api`
handler never reads it.

## Responsive Behavior

The shell has exactly **one** layout breakpoint, at **768px** — Tailwind's `md`, and
Expand Down
Loading
Loading