Skip to content

Commit e8b78bb

Browse files
os-zhuangclaude
andauthored
docs: retire legacy UI-hint keys (ADR-0085 semantic roles) (#2529)
Sweep hand-written docs and skills for teachings of the object UI-hint keys ADR-0085 removed/renamed, and rewrite them to the current semantic-role protocol (nameField / highlightFields / stageField / fieldGroups + Field.group, per-page customization via an assigned Page): - content/docs/guides/data-modeling.mdx: fieldGroups example + property table taught the removed ObjectFieldGroup.visibleOn and the deprecated defaultExpanded flag; now teach the collapse enum ('none'|'expanded'|'collapsed') and drop group-level visibleOn. - content/docs/guides/public-forms.mdx: section 10 taught the removed (never-implemented) ObjectSchema.defaultDetailForm binding and the retired views.formViews/views.form resolution chain; rewritten to explain record detail is derived from the semantic roles, with an assigned Page as the per-page customization path. Frontmatter description updated accordingly. - skills/objectstack-data/SKILL.md: fieldGroups example modernized (collapse instead of defaultExpanded; group visibleOn removed) and the group-property bullet now teaches the collapse enum. - skills/objectstack-ui/SKILL.md: detail.relatedLayout ('stack'|'tabs') teaching removed with the whole detail:{...} block; now teaches the default single Related tab + custom record Page (record:related_list) for first-class child-table navigation. - skills/objectstack-formula/SKILL.md: dropped the ObjectFieldGroup.visibleOn row from the CEL-surface inventory (the key was removed per ADR-0085 / ADR-0049 enforce-or-remove). ADRs, changelogs/changesets, audits, and auto-generated references (content/docs/references/**, skills/objectstack-ui/references/ react-blocks.md) are deliberately untouched. Verified: check:doc-authoring clean; docs:build green. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent c0e40e5 commit e8b78bb

5 files changed

Lines changed: 46 additions & 49 deletions

File tree

content/docs/guides/data-modeling.mdx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -549,8 +549,8 @@ export const Account = ObjectSchema.create({
549549

550550
fieldGroups: [
551551
{ key: 'contact_info', label: 'Contact Information', icon: 'user' },
552-
{ key: 'billing', label: 'Billing', defaultExpanded: false },
553-
{ key: 'system', label: 'System', visibleOn: '$user.isAdmin' },
552+
{ key: 'billing', label: 'Billing', collapse: 'collapsed' },
553+
{ key: 'system', label: 'System' },
554554
],
555555

556556
fields: {
@@ -573,16 +573,18 @@ export const Account = ObjectSchema.create({
573573
| `label` | `string` | Human-readable group header |
574574
| `icon` | `string?` | Lucide/Material icon name for the group header |
575575
| `description` | `string?` | Optional description under the header |
576-
| `defaultExpanded` | `boolean` (default `true`) | Whether the group is expanded initially |
577-
| `visibleOn` | `string?` | Expression controlling group-level visibility |
576+
| `collapse` | `'none' \| 'expanded' \| 'collapsed'` (default `'none'`) | Collapse behaviour on every surface: `'none'` = always open (no toggle), `'expanded'` = collapsible and starts open, `'collapsed'` = collapsible and starts closed (ADR-0085; replaces the deprecated `defaultExpanded` flag, which is still accepted as an alias) |
578577

579578
### Supported Migrations (MVP)
580579

581580
✅ Add / rename / delete / reorder groups — edit the `fieldGroups` array.
582581
✅ Assign an existing field to a group — set `Field.group`.
583582

584583
⏳ Deferred (future iterations): explicit per-field in-group ordering, nested
585-
groups, permission-scoped group visibility beyond `visibleOn`.
584+
groups, group-level visibility predicates. Groups render identically on forms,
585+
modals, and detail pages; when a single page needs a bespoke layout beyond
586+
groups, assign it a custom Page schema instead of adding per-surface hints
587+
here (ADR-0085).
586588

587589
---
588590

content/docs/guides/public-forms.mdx

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: Forms (Public + Internal)
3-
description: Render any FormView either publicly (anonymous, /f/:slug) or internally (authed operators, /forms/:name). The same metadata drives both, with URL prefill, configurable post-submit behavior, defaultDetailForm record binding, and declarative open-form actions.
3+
description: Render any FormView either publicly (anonymous, /f/:slug) or internally (authed operators, /forms/:name). The same metadata drives both, with URL prefill, configurable post-submit behavior, and declarative open-form actions.
44
---
55

66
# Forms
@@ -359,29 +359,26 @@ export default Action.create({
359359

360360
Compared to `{ type: 'url', target: '/console/forms/quick_create' }`, the `'form'` variant is portable across runtimes — Studio/console/native shells can route it through their own form renderer instead of a raw navigation.
361361

362-
## 10. `defaultDetailForm` — bind a FormView to record detail
363-
364-
Set `defaultDetailForm` on an object schema to pin the FormView used by the record-detail / edit screen. This is the Airtable Interface-form binding pattern.
365-
366-
```ts
367-
// hotcrm/src/objects/lead.object.ts
368-
import { ObjectSchema } from '@objectstack/spec/data';
369-
370-
export default ObjectSchema.create({
371-
name: 'lead',
372-
label: 'Lead',
373-
defaultDetailForm: 'quick_create', // → views.formViews.quick_create
374-
fields: { /**/ },
375-
});
376-
```
377-
378-
Resolution order at runtime:
379-
380-
1. `views.formViews[defaultDetailForm]` if set
381-
2. `views.form` (the unnamed default form view)
382-
3. Auto-generated grid layout from object fields
383-
384-
The same FormView can therefore drive **three** experiences — public collection, internal quick-create, and record-detail editing — without duplicating layout metadata.
362+
## 10. Record detail is driven by semantic roles, not a form binding
363+
364+
There is **no** object-level key that pins a FormView to the record-detail /
365+
edit screen (the once-documented `defaultDetailForm` was never implemented and
366+
has been removed from `ObjectSchema`). Record-detail rendering is derived from
367+
the object's **cross-surface semantic roles** (ADR-0085):
368+
369+
- `nameField` — which field is the record's display name.
370+
- `highlightFields` — the most important fields (detail highlight strip,
371+
default list columns, cards).
372+
- `stageField` — the linear-lifecycle field behind the detail progress
373+
stepper (`false` suppresses detection).
374+
- `fieldGroups` + `Field.group` — semantic grouping, rendered identically on
375+
forms, modals, and detail pages.
376+
377+
When a record page needs a bespoke layout beyond what the roles derive, assign
378+
the object a **custom Page schema** — that is the supported per-page
379+
customization path. FormViews remain the metadata for the two form
380+
experiences this guide covers: public collection (`/f/:slug`) and internal
381+
entry (`/forms/:name`).
385382

386383
## 11. Security checklist (public mode)
387384

skills/objectstack-data/SKILL.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ Organize fields into logical groups (e.g., "Contact Information", "Billing",
111111
`ObjectFieldGroup.key`. In-group display order equals the traversal order
112112
of `fields`.
113113
- Group keys must be `snake_case`; group labels are human-readable.
114+
- Optional per-group: `icon`, `description`, and `collapse`
115+
(`'none'` always open · `'expanded'` collapsible, starts open ·
116+
`'collapsed'` collapsible, starts closed — replaces the deprecated
117+
`defaultExpanded` flag, ADR-0085). Groups render identically on forms,
118+
modals, and detail pages; for a bespoke single-page layout assign a
119+
custom Page instead.
114120

115121
```typescript
116122
import { ObjectSchema } from '@objectstack/spec';
@@ -121,8 +127,8 @@ export default ObjectSchema.create({
121127

122128
fieldGroups: [
123129
{ key: 'contact_info', label: 'Contact Information', icon: 'user' },
124-
{ key: 'billing', label: 'Billing', defaultExpanded: false },
125-
{ key: 'system', label: 'System', visibleOn: P`os.user.isAdmin == true` },
130+
{ key: 'billing', label: 'Billing', collapse: 'collapsed' },
131+
{ key: 'system', label: 'System' },
126132
],
127133

128134
fields: {

skills/objectstack-formula/SKILL.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,6 @@ to the envelope.
304304
| `Field` | `visibleOn` | cel |
305305
| `Field` | `defaultValue` (M9.9b) | cel |
306306
| `ConditionalValidation` | `when` | cel |
307-
| `ObjectFieldGroup` | `visibleOn` | cel |
308307
| `View` | `visibleOn` | cel |
309308
| `View.criteria` | filter expression | cel |
310309
| `Action` | `disabled` | cel (or boolean) |

skills/objectstack-ui/SKILL.md

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -151,23 +151,16 @@ columns (see objectstack-data → Relationships → Detail-page related lists).
151151
Authored record pages can still place an explicit `record:related_list` (or
152152
inline-editable `record:line_items`) when they need bespoke placement.
153153

154-
**Related-list layout — `detail.relatedLayout` (`'stack'` | `'tabs'`).** By
155-
default every related list stacks under a single **Related** tab on the record
156-
detail page (`relatedLayout: 'stack'`). To promote each related table to its own
157-
**peer tab** — sitting alongside *Details* / *Activity* instead of nested under
158-
*Related* — set `relatedLayout: 'tabs'` in the object's `detail` block:
159-
160-
```typescript
161-
detail: { relatedLayout: 'tabs' } // Details · Tasks · Risks · Milestones …
162-
```
163-
164-
Pure config — no custom record page needed; the synthesized detail page emits
165-
one peer tab per related entry (label falls back to the object name, the
166-
relationship's icon carries through), with Activity/History ordered after them.
167-
Omit it (or `'stack'`) for the default single-Related-tab behavior — zero
168-
regression. Use `tabs` when a record has several substantial child tables that
169-
each deserve first-class navigation; keep `stack` when related lists are
170-
secondary to the main record body.
154+
**Related-list layout.** Every related list stacks under a single **Related**
155+
tab on the synthesized record detail page — that is the only built-in layout.
156+
The old `detail.relatedLayout` (`'stack'` | `'tabs'`) toggle — like the whole
157+
object-level `detail: {...}` block — was **removed** (ADR-0085): an object
158+
declares no per-surface layout hints. When a record's child tables deserve
159+
first-class navigation (their own tabs, bespoke placement), assign the object a
160+
**custom record Page** and lay it out explicitly with `record:related_list`
161+
(or inline-editable `record:line_items`) blocks. For lighter tweaks stay at the
162+
relationship layer: `relatedList: false` to suppress a noisy child,
163+
`relatedListTitle` / `relatedListColumns` to override title / columns.
171164

172165
### Field Conditional Rules in Forms
173166

0 commit comments

Comments
 (0)