Savvi Studio

UI Widget Presets And Composition

This document defines the migration path away from one-off UI screens and toward module-driven, preset-based entity views.

Goals

  • Eliminate bespoke page structures for entity domains.
  • Declare list/detail views in modules instead of encoding UI structure in each page component.
  • Reuse a shared preset library of widgets across teams, sponsors, tasks, organizations, and plan-years.

Core Module

The module core.ui.widgets provides the semantic model for reusable UI building blocks.

Core Types

  • ui.widgets.widget: a renderable widget instance (schema:WebPageElement)
  • ui.widgets.widget-preset: declarative widget blueprint (schema:DefinedTerm)
  • ui.widgets.widget-library: named preset collection (schema:DefinedTermSet)
  • ui.widgets.widget-composition: ordered set of widgets (schema:ItemList)
  • ui.widgets.widget-slot-binding: slot-to-preset binding (schema:PropertyValue)
  • ui.widgets.entity-list-view: canonical list view (schema:CollectionPage)
  • ui.widgets.entity-detail-view: canonical detail view (schema:WebPage)

Templates

  • widget-preset
  • entity-list-view-preset
  • entity-detail-view-preset
  • widget-slot-binding

Runtime Presets

The runtime mapping is centralized in packages/hooks-entities/entity-ui-presets.ts.

Each preset defines:

  • entity type key
  • title and create CTA text
  • canonical list/detail routes
  • allowed actions
  • dialog keys

This allows domain hooks to consume one shared preset contract rather than duplicating action/title/dialog metadata per domain.

Migration Sequence

  1. Define list/detail compositions in module manifests via core.ui.widgets templates.
  2. Ensure each domain hook resolves action/title/dialog config from a shared preset key.
  3. Move route pages to polymorphic entity routes (/entities/[entityType] and /entities/[entityType]/[entityId]) and drive rendering from the preset key.
  4. Convert existing domain-specific routes into compatibility wrappers.
  5. Remove old custom page-only render logic once preset coverage is complete.

Immediate Follow-Up

  • Add organizations preset and align ui-domain-organizations-components with EntityPage contract.
  • Add plan-years domain hooks/components and register plan-years list/detail presets.
  • Add module validation checks that each first-class entity has both list and detail view presets.

Schema.org Alignment For Declarative Workbench

To keep the module workbench self-hosted and semantically portable, prefer schema.org-aligned modeling in module manifests and runtime contracts.

Canonical Type Alignment

  • Workbench page shell: schema:WebPage
  • Workbench sections and controls: schema:WebPageElement
  • Declarative form definition: schema:DefinedTerm
  • Enumerated option sets: schema:DefinedTermSet
  • Query-backed option collections: schema:ItemList
  • User-triggered UI events: schema:Action and specialized actions such as schema:CreateAction, schema:UpdateAction, and schema:DeleteAction

Canonical Property Alignment

  • Stable id and key fields: schema:identifier
  • Human-readable label: schema:name
  • Help text and long description: schema:description
  • Control ordering and option ordering: schema:position
  • Parent-child composition: schema:hasPart and schema:isPartOf
  • Select option entries and ordered results: schema:itemListElement
  • Event actor, target, and output: schema:agent, schema:object, schema:result
  • Event lifecycle status: schema:actionStatus
  • Event timing: schema:startTime, schema:endTime
  • Documentation links for behaviors: schema:url

Primitives Required For Scoped Dropdowns And Cascades

  1. Field primitive
    • identifier, name, description, position
    • Declares value path, required flag, visibility rules, and enabled rules.
  2. Option source primitive
    • additionalType to classify source kind (static, query, derived).
    • itemListElement for resolved options and url for resolver endpoints.
  3. Scope primitive
    • Scope dimensions expressed via about and additionalType (for example local/imported/global/contextual).
    • Include namespace and type constraints, role/permission constraints, and ownership constraints.
  4. Cascade primitive
    • Parent linkage via isPartOf and dependency list via about or structured additionalProperty.
    • Defines clear/requery/preserve behavior when parent values change.
  5. Filter primitive
    • Query filters encoded as declarative expressions in additionalProperty and tied to parent fields through identifiers.
  6. Validation primitive
    • Membership and scope validation represented as schema:Action policies with actionStatus outcomes.
  7. Event primitive
    • schema:Action envelope for on-init, on-change, on-submit flows using agent, object, result, and timing/status fields.

When both schema.org and custom fields are possible, prefer schema.org fields first and use custom fields only for behavior that cannot be represented with existing schema.org identifiers.