Blueprint UI hint vocabulary
Blueprint UI hints describe semantic product intent without importing Flutter. The fixed Blueprint UI and Studio runtimes translate that intent into CDX controls, views, routes, forms, docks, and shell contributions.
Cascade
Inheritable hints resolve one property at a time. The closest declaration wins:
entity -> module -> Blueprint -> platform defaultAn entity can therefore override only maxSortLevels while continuing to inherit maxGroupLevels from its module. Assembly materializes the effective value once onto the effective entity UI plan; renderers do not walk the Blueprint graph during every build.
final blueprint = Blueprint(
name: 'ops',
version: '0.3.0',
ui: const BlueprintUI(
query: QueryUI(maxSortLevels: 3, maxGroupLevels: 3),
),
modules: [
Module(
name: 'elog',
schema: 'elog',
version: '0.3.0',
ui: const ModuleUI(
query: QueryUI(maxGroupLevels: 2),
),
entities: [
Entity(
name: 'activity',
tableName: 'activities',
facets: const [],
ui: const EntityUI(
list: ListUI.auto(
query: QueryUI(maxSortLevels: 1),
),
),
),
],
),
],
);The effective elog.activity query policy is one sort level and two group levels.
Domain-attached hints
These types live in vyuh_blueprint and travel with the domain declaration.
| Scope | Vocabulary | Semantic intent |
|---|---|---|
| Blueprint | BlueprintUI, QueryUI, ActionPlacementUI | Cross-module defaults such as query composition limits and default action placements. |
| Module | ModuleUI, NavigationCategoryUI | Icon, visibility, access, category, route prefix, navigation hierarchy and disclosure behavior, query overrides, and module action placements. |
| Entity | EntityUI, EntityUIOverride, ListUI, DetailUI, EditorUI, RelatedUI | Icon, visibility, access, category, route prefix, typed list layouts/query, detail views, editors, relationships, read-only posture, priority, detail-tab extension refs, and entity action placements. |
| Facet | FacetUI, UISectionKind | Form/detail/lifecycle/evidence/audit/relationship/analytics section semantics, order, access, and initial collapse. |
| Field | FieldUI, UIFieldControl, UIFieldDerivation | Intrinsic editor family, access, order, filtering, sorting, search, input posture, read-only/hidden posture, help, placeholder, option search, dependencies, transforms, and a custom editor ref. |
| Collection | ListUI, ListLayoutUI, TableUI, GridUI, KanbanUI, CalendarUI, TreeUI, TimelineUI, CustomUI | Ordered available layouts, default layout, layout-specific projection/query, and declarative content composition. |
| Table | TableColumnUI, UIColumnAppearance, UIColumnViewport | Field placement, cell treatment, width, responsive visibility, initial visibility, and required visibility. |
| Form | FormUI, FormSectionUI, EditorUI, EditorPartUI | Derived or explicit form composition, sections, columns, editor presentation, tabs/steps, and operation support. |
| Field value | UIBooleanLabels, UIOptionSearch | Semantic boolean labels and search posture for choices. |
| Field reference | UIReferenceHint | Target entity and picker projection for reference-shaped fields. |
| Relationship | RelationshipUI, UIRelationshipPresentation | Picker/rendering mode, projection, option search, editor/detail/inverse visibility, inline create, order, access, picker ref, and renderer ref. |
| Action | Action, ActionScope, ActionUI | Facet-owned action semantics, target cardinality, icon, access, order, confirmation, destructive posture, presentation defaults, tooltip, and custom capture form ref. |
| Action placement | ActionPlacementRef, ActionPlacementUI, ActionUIRef | Extensible placement identity plus ordered references into the effective facet action catalog. |
| Cross-cutting | UIIcon, UIVisibility, UIPlacement, UIAccess, UIAccessRule, UIAccessFallback | Portable icons, discoverability, read/write/execute gates, and denied-state behavior. |
UIFieldControl currently supports automatic, text, multiline text, number, decimal, checkbox, date, date-time, enum select, reference picker, JSON, evidence, signature, checklist, photo capture, instrument capture, and custom editors.
Module navigation
Module and category menu behavior is declared with the Blueprint. Renderers preserve these values; they do not decide which groups are collapsible.
ui: const ModuleUI(
collapsible: true,
initiallyCollapsed: false,
navigationCategories: [
NavigationCategoryUI(
name: 'execution',
title: 'Execution',
collapsible: false,
),
NavigationCategoryUI(
name: 'configuration',
title: 'Configuration',
collapsible: true,
initiallyCollapsed: true,
),
],
),Categories without a parentRef are flat sections within the module. A parentRef creates one nested category level. Entities join a declared category through EntityUI.category or EntityUIOverride.category.
collapsible controls whether the label is an interactive disclosure. initiallyCollapsed controls its initial expansion state and may only be true when collapsible is true. Subsequent expansion is runtime user state.
Field dependencies and transforms
A target field can declaratively depend on one or more other fields. The dependency belongs to FieldUI; it is not hard-coded into a semantic field such as CodeField, and the editor does not infer it from field names.
const name = NameField();
const code = CodeField.configured(
ui: FieldUI(
filterable: true,
sortable: true,
searchable: true,
derivation: UIFieldDerivation(
sourceFields: [name],
transforms: [
UITrimTransform(),
UIUpperCaseTransform(),
UIReplacePatternTransform(
pattern: r'[^A-Z0-9]+',
replacement: '-',
),
UIReplacePatternTransform(pattern: r'^-+|-+$'),
],
),
),
);Table placement is configured once in the table layout:
const list = ListUI(
layouts: [
TableUI(
columns: [
TableColumnUI(
field: code,
appearance: UIColumnAppearance.identity,
required: true,
),
TableColumnUI(field: name),
TableColumnUI(field: description, visible: false),
],
),
],
);TableUI.columns is the complete column catalog for that table layout. It contains both the columns shown initially and optional columns that a user may enable later. Set visible: false to keep a column in the chooser without showing it initially. Set required: true for identity columns that a renderer must keep visible.
UIFieldTransform is sealed. The platform-owned defaults are therefore typed and exhaustively handled:
| Transform | Purpose |
|---|---|
UIJoinTransform(separator: ...) | Combines multiple source values. |
UITrimTransform() | Removes leading and trailing whitespace. |
UIUpperCaseTransform() | Converts text to uppercase. |
UILowerCaseTransform() | Converts text to lowercase. |
UIReplacePatternTransform(...) | Applies a typed regular-expression replacement. |
The default vocabulary can expand without making every declaration stringly-typed. A product-specific transform uses the single escape hatch, UIFieldTransformRef:
const site = ReferenceIdField('site_id');
const room = TextField('room');
derivation: UIFieldDerivation(
sourceFields: [site, room],
transforms: [
UIJoinTransform(separator: '/'),
UIFieldTransformRef(
'ops.location.key',
arguments: {'prefix': 'LOC'},
),
],
),Dot-qualified references are recommended because they make ownership visible. Blueprint UI resolves the reference against the host registry:
BlueprintRecordEditor(
// ...
valueTransformers: {
'ops.location.key': (context) {
final prefix = context.arguments['prefix'] ?? 'LOC';
return '$prefix:${context.value}';
},
},
);RecordFieldTransformContext provides the current pipeline value, declared source values, a read-only form snapshot, reference arguments, the target field, and the create/update operation. Referenced transforms are deliberately pure and synchronous: source fields express dependencies, while the registry supplies implementation. Remote lookups belong in reference pickers, async validation, or an action—not in a keystroke transform.
By default, a derivation applies on create and follows its sources until the person edits the target. The editor then preserves the override and exposes a relink affordance. UIFieldDerivationOverride.always, applyOnCreate, and applyOnUpdate make that behavior explicit. During assembly/runtime, unresolved or ambiguous source refs and dependency cycles are rejected.
This feature provides editor defaulting and linked input behavior. A server-enforced invariant still belongs in validation, a database expression, or action execution so every client observes the same rule.
Typed collection layouts
ListUI owns one ordered list of typed ListLayoutUI declarations. The first layout is the default. Every layout owns the projection, initial filter, and initial order it consumes; layout-specific placement does not leak into FieldUI.
| Layout | Configuration |
|---|---|
TableUI | TableColumnUI entries with typed fields, appearance, width, responsive threshold, initial visibility, and required visibility. |
GridUI | Column-based grid using CardContentUI for each repeated item, with identity/status/media/body/badge fields, minimum width, and maximum columns. |
KanbanUI | Required column field, optional swimlane field, and card content. |
CalendarUI | Required start field, optional end/resource fields, scale, and event content. |
TreeUI | Required id/parent fields, initial expansion, and node content. |
TimelineUI | Required start field, optional end/lane fields, scale, and item content. |
CustomUI | Stable renderer ref plus serializable configuration. |
ListUI.auto() asks assembly to derive a conservative TableUI and GridUI from semantic identity and lifecycle fields. Use it for ordinary masters. Declare layouts explicitly whenever the entity has meaningful Kanban, calendar, tree, or timeline semantics.
Forms and editors
FormUI is the complete declarative form configuration. There is no separate “form structure” vocabulary:
FormUI.derived()orders input-capable fields using facet and field metadata.FormUI.sections(...)contains orderedFormSectionUIdeclarations.FormSectionUIselects facets and/or typed field refs and sets a one-to-four column layout.EditorUI.formconfigures a single-form editor.EditorPartUI.formconfigures one tab or step in a multipart editor.
EditorUI additionally controls create/update support, adaptive/dock/dialog/ full-screen presentation, parts, actions, and the custom widget escape hatch. Fields remain responsible for intrinsic input capability and editor behavior; forms decide composition and order.
Effective actions
Facets own action definitions. UI declarations never copy an action and never become a second action catalog. Assembly traverses the entity once and materializes one EffectiveActionCatalog, whose entries can be referenced as:
action_namewhen the name is unique in the entityfacet_name.action_namemodule.entity.facet_name.action_name
Known placements are collection.toolbar, collection.menu, selection.toolbar, selection.menu, record.header, record.action-bar, record.menu, command-palette, tab.<tab-id>.toolbar, and tab.<tab-id>.menu. ActionPlacementRef is a value type, so a runtime can add another stable placement without extending an enum.
final Entity holidayCalendar = Entity(
name: 'holiday_calendar',
tableName: 'holiday_calendars',
ui: const EntityUI(
actionPlacements: [
ActionPlacementUI(
placement: ActionPlacementRef.recordHeader,
actions: [
ActionUIRef(
'governance.activate',
presentation: UIActionPresentation.icon,
),
],
),
ActionPlacementUI(
placement: ActionPlacementRef.recordMenu,
actions: [ActionUIRef('governance.retire')],
),
ActionPlacementUI(
placement: ActionPlacementRef('tab.audit.toolbar'),
actions: [ActionUIRef('governance.export_audit')],
),
],
),
facets: [
Facet(
name: 'governance',
actions: [
Action(name: 'activate', scope: ActionScope.record),
Action(name: 'retire', scope: ActionScope.record),
Action(name: 'export_audit', scope: ActionScope.record),
],
),
],
);Placement declarations follow the same override cascade:
entity -> module -> Blueprint -> scope-derived platform defaultThe closest declaration replaces the less-specific declaration for the same placement. When no placements are declared, ActionScope.collection, ActionScope.selection, and ActionScope.record map to the collection toolbar, selection toolbar, and record action bar respectively.
At runtime, EffectiveActionResolver combines the precomputed catalog, effective placements, selected record/count, actor permissions, policies, roles, groups, grants, qualifications, evidence, lifecycle/data rules, and optional custom condition evaluator. It returns one EffectiveActionSet per placement. Each member is explicitly enabled, disabled, or hidden, with a reason and tooltip suitable for rendering. The server remains the final execution authority.
App and workspace UI
Product composition belongs to vyuh_blueprint, not to entity hints. It describes where domain intent appears:
AppEntityUIScope separates domain availability from product ownership. Every portfolio app can retain the complete entity graph for protocol, authorization, scope, and reference resolution while deriving CRUD routes, collections, navigation, and commands only for its selected modules/entities.
| UI family | Vocabulary |
|---|---|
| Routing | RouteUI, AppRouteKind |
| Collections | EffectiveEntityUI, ListUI, ListLayoutUI, TableUI, GridUI, KanbanUI, CalendarUI, TreeUI, TimelineUI, CustomUI, RelatedUI |
| Record details and editing | DetailUI, DetailUIKind, EditorUI, EditorUIKind |
| Actions | EffectiveActionCatalog, ActionPlacementUI, EffectiveActionSet |
| Work queues and analytics | InboxUI, InboxItemKind, DashboardUI, DashboardWidgetKind |
| Discovery | SearchUI, SearchMode, CommandPaletteUI, SavedViewUI |
| Settings and profile | SettingsUI, LocalizationUI, ProfileUI, AppearanceUI |
| Workspace navigation | Workspace, Navigation, NavigationGroup, NavigationItem |
| Shell and scope | AppShell, AppScope, ActorUI, TenantUI, SiteUI, ScopeSelectorUI |
| Menus | MenuBarUI, MenuUI, MenuItemUI, MenuItemKind, UserMenuUI |
| Status and activity | StatusBarUI, StatusIndicator, StatusIndicatorContext, NotificationUI, ActivityStreamUI |
| Governance and execution | InspectorUI, PolicyUI, AccessUI, EvidenceUI, AuditUI, ExecutionUI, OfflineExecutionUI |
| Reports and help | ReportUI, ReportBlock, ReportBlockKind, ReportOutputKind, HelpUI, HelpFragment, HelpScope |
| Runtime posture | RealtimeUI, OfflineUI, OfflineStrategy, SimulationUI, IntegrationUI, DemoUI |
SearchUI defaults to the server-derived global_search projection. It combines id, the available human identity fields (code, name, title, label, display_name, username, and email), and additional readable fields explicitly marked searchable. CommandPaletteUI.searchRefs keeps these search declarations independent, allowing each command-palette tab to render as soon as its own provider completes.
Extension vocabulary
Declarative hints are not a closed rendering system. BlueprintExtensionRef provides stable server/client seams for action handlers, rule evaluators, policy resolvers, effect handlers, routes, widgets, detail tabs, empty states, dashboard widgets, report blocks, forms, and custom extensions. Domain hints attach symbolic refs such as FieldUI.editorRef, RelationshipUI.pickerRef, RelationshipUI.rendererRef, ActionUI.formRef, and EntityUI.detailTabRefs; client/server registries bind them to code.
Ownership rule
Use typed Blueprint hints for portable product intent, map them into generic enterprise contracts in vyuh_blueprint_ui, render those contracts through vyuh_studio_ui, and keep low-level mechanics and tokens in CDX. Use a stable extension ref when product-specific code is required.