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
12 changes: 9 additions & 3 deletions content/docs/guide/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,12 +253,18 @@ ObjectUI includes a powerful expression engine for dynamic UIs:

```json
{
"type": "badge",
"text": "${orders.length} Orders",
"variant": "${orders.length > 10 ? 'success' : 'warning'}"
"type": "statistic",
"label": "Orders",
"value": "${orders.length}",
"description": "${orders.length > 10 ? 'Above target' : 'On track'}"
}
```

`statistic` rather than `badge`: an expression is evaluated only on a key the node's own
type carries, and `expressionBindableTextKeysFor` gives `statistic` the rows `label`,
`value` and `description` while giving `badge` none. A badge's text is its `label`, and it
has to arrive already resolved.

See the [Expressions Guide](/docs/guide/expressions) for complete details.

## Data Flow
Expand Down
4 changes: 2 additions & 2 deletions content/docs/guide/layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -508,11 +508,11 @@ Omit `sidebar` and the content fills the width under the top bar.
```json
{
"type": "page",
"title": "${record.name}",
"title": "Acme Corporation",
"breadcrumbs": [
{ "label": "Home", "href": "/" },
{ "label": "Customers", "href": "/customers" },
{ "label": "${record.name}" }
{ "label": "Acme Corporation" }
],
"actions": [
{
Expand Down
47 changes: 36 additions & 11 deletions content/docs/guide/schema-rendering.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,19 @@ Object UI includes a powerful expression system for dynamic behavior:

```json
{
"type": "badge",
"text": "${status === 'active' ? 'Active' : 'Inactive'}",
"variant": "${status === 'active' ? 'success' : 'default'}"
"type": "card",
"title": "${status === 'active' ? 'Active' : 'Inactive'}",
"description": "${status === 'active' ? 'This record is in use.' : 'This record is archived.'}"
}
```

`card` here rather than `badge`, because an expression is evaluated only on a key the
node's own type carries. `expressionBindableTextKeysFor` — the lookup `SchemaRenderer`
consumes out of `@objectstack/spec` — gives `card` the rows `title` and `description`,
and gives `badge` no rows at all, so a `${…}` written on a badge reaches the DOM as the
characters you typed. Resolve a badge's text before you hand the schema over, and author
it on `label`: `text` is not a `BadgeSchema` key.

### Visibility Control

```json
Expand All @@ -203,15 +210,26 @@ Object UI includes a powerful expression system for dynamic behavior:
```json
{
"type": "alert",
"message": "Welcome!",
"variant": "${
user.isNew ? 'info' :
user.tasks.length === 0 ? 'warning' :
'success'
}"
"variant": "default",
"title": "Welcome!",
"body": {
"type": "text",
"content": "${
user.isNew ? 'Start with the quick tour.' :
user.tasks.length === 0 ? 'You are all caught up.' :
'You have tasks waiting.'
}"
}
}
```

The branch sits on the nested `text` node's `content`, which `SchemaRenderer` evaluates
on every node type — the escape hatch for a component that carries no expression rows of
its own, and `alert` is one of those. Its severity could not be chosen by expression in
any case: `AlertSchema.variant` is the closed set `default` | `destructive`, so `info`,
`warning` and `success` are not values it accepts. Pick the variant in the host and
author it as a literal.

## Event Handling

Components can emit events that you handle in React:
Expand Down Expand Up @@ -411,12 +429,19 @@ Always type your schemas for better IDE support and fewer runtime errors.
```json
{
"type": "alert",
"variant": "error",
"variant": "destructive",
"visibleOn": "${error}",
"message": "${error.message}"
"title": "Something went wrong",
"body": { "type": "text", "content": "${error.message}" }
}
```

`visibleOn` is a condition key and is evaluated on every node type. The message text is a
nested `text` node because `alert` carries no expression rows — and `message` is not an
`AlertSchema` key at all: the alert's own text keys are `title` and `description`, and the
renderer falls back from `description` to `body`. `destructive` is the variant this state
wants; `error` is not in the closed set.

## Next Steps

- [Component Registry](./component-registry.md) - Learn about component registration
Expand Down