Follow-up to #2578 (closed). #2578 shipped the adaptive detail/view surface (field-heavy → full page, light → drawer) + multi-column + span. It intentionally left the create / edit / subtable surfaces and their return flows undesigned. This issue picks that up.
North star (inherited from #2578): all metadata is AI-authored, so surface + return must be a platform default, not per-object config — zero AI authoring. Presentation is not metadata.
The gap (state after #2578)
| Flow |
Current behavior |
Status |
| Detail (row-click view) |
route — page for field-heavy, drawer for light (shipped) |
✅ done |
| List → New (create) |
opens a modal (large), not a route |
⚠️ inconsistent with detail |
| Detail → Edit |
not wired to a route (modal) |
⚠️ undesigned |
| Subtable → New / Edit child |
untouched |
❌ missing |
| Return from any of the above |
not designed / not verified |
❌ missing |
Core decision: full-screen modal vs full-screen route?
For a field-heavy record both give a big canvas; they differ on return and deep-linkability:
- Modal (overlay): close (X / Esc / Cancel / Save) → back exactly where you were; list scroll + filters preserved; no route wiring. Not deep-linkable; browser-back doesn't apply.
- Route (navigation): URL changes → browser back + deep-link + refresh-safe. Needs explicit return wiring (origin state); nested (subtable) creates need a return stack.
Recommended model (hybrid) — from the discussion
- Detail (view) = route. Deep-linkable / shareable; field-heavy → page. ✅ already shipped.
- Create + Edit = full-screen modal (
modalSize: 'full' when field-heavy). Trivial return (close → list/detail, context preserved); a transient task rarely needs a deep link; no return-stack wiring. (Leaning this way; alternative = also route.)
- Subtable (child) create / edit = modal / drawer over the parent detail route. Close → parent detail intact, subtable refetches. Never a separate route — that loses the parent context and needs a return stack.
The three return flows
1. List → New record
- Modal (recommended): 取消 / X / 保存 → close → list at original position (scroll + filter kept). Save → optionally stay on the list or jump to the new record's detail.
- Route alt (
/new): needs a "← back to list" affordance + browser back; save → navigate to the new record's detail. (The origin-state infra already exists — it powers the detail page's "← 所有记录".)
2. Subtable → New / Edit child (the important one)
- You are on a parent record detail (a route); the return target must be that parent detail + the subtable refreshed.
- Modal over the parent detail → close = back to parent, subtable refetch. Strongly recommended.
- Separate route → loses parent context, needs a return stack, re-fetches the parent. Avoid.
3. Detail → Edit record
- Detail is already a route
/record/:id. Two clean options:
- (a) In-place edit mode — same route, view ↔ edit toggle; save / cancel → view.
- (b) Full-screen modal edit → save / cancel → close back to detail.
- Either works; the invariant is: save / cancel returns to the view state, never leaves the user somewhere else.
Decisions to make before implementing
- Create / Edit surface: full-screen modal (recommended) or route?
- Detail → Edit: in-place edit mode or a separate modal / route?
- Subtable: confirm "modal over parent detail, never a route".
Scope / acceptance (once decided)
- Create / Edit surface wired per the decision, with its return flow (make create consistent with the shipped detail behavior).
- Subtable create / edit as a modal-over-parent, with parent-detail refresh on close.
- Browser-verify each return: list → new → back; subtable → new → back to parent + refresh; detail → edit → back to view.
- Zero AI authoring — surface + return are runtime defaults.
Refs #2578 · code shipped in framework#2595 + objectstack-ai/objectui#2237 + framework#2599
Follow-up to #2578 (closed). #2578 shipped the adaptive detail/view surface (field-heavy → full page, light → drawer) + multi-column +
span. It intentionally left the create / edit / subtable surfaces and their return flows undesigned. This issue picks that up.North star (inherited from #2578): all metadata is AI-authored, so surface + return must be a platform default, not per-object config — zero AI authoring. Presentation is not metadata.
The gap (state after #2578)
Core decision: full-screen modal vs full-screen route?
For a field-heavy record both give a big canvas; they differ on return and deep-linkability:
Recommended model (hybrid) — from the discussion
modalSize: 'full'when field-heavy). Trivial return (close → list/detail, context preserved); a transient task rarely needs a deep link; no return-stack wiring. (Leaning this way; alternative = also route.)The three return flows
1. List → New record
/new): needs a "← back to list" affordance + browser back; save → navigate to the new record's detail. (The origin-state infra already exists — it powers the detail page's "← 所有记录".)2. Subtable → New / Edit child (the important one)
3. Detail → Edit record
/record/:id. Two clean options:Decisions to make before implementing
Scope / acceptance (once decided)
Refs #2578 · code shipped in framework#2595 + objectstack-ai/objectui#2237 + framework#2599