Skip to content

Design: record create/edit/subtable surface + return-flow model (follow-up to #2578) #2604

Description

@os-zhuang

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

  1. Create / Edit surface: full-screen modal (recommended) or route?
  2. Detail → Edit: in-place edit mode or a separate modal / route?
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions