Skip to content

Latest commit

 

History

History
367 lines (320 loc) · 9.61 KB

File metadata and controls

367 lines (320 loc) · 9.61 KB
title ObjectUI - UI Layer Architecture
description Deep dive into the ObjectUI (Server-Driven UI) protocol architecture

ObjectUI - UI Layer Architecture

Deep dive into the ObjectUI (Server-Driven UI) protocol architecture

Overview

ObjectUI is the presentation protocol that defines how user interfaces are configured and rendered. It enables building dynamic UIs without hardcoding components.

Key Components

1. Application Structure (src/ui/app.zod.ts)

Defines the top-level application configuration:

const app = {
  name: 'sales_app',
  label: 'Sales CRM',
  branding: {
    logo: '/assets/logo.png',
    primaryColor: '#0066CC',
    secondaryColor: '#FF6B00',
  },
  navigation: [
    { type: 'object', object: 'customer_account', label: 'Accounts' },
    { type: 'object', object: 'opportunity', label: 'Opportunities' },
    { type: 'dashboard', dashboard: 'sales_dashboard', label: 'Dashboard' },
  ],
};

2. View Configuration (src/ui/view.zod.ts)

List Views

Display collections of records:

Grid View - Tabular data display:

{
  type: 'grid',
  columns: ['name', 'email', 'revenue', 'status'],
  filters: ['status:active'],
  sortBy: 'revenue:desc',
  pageSize: 25,
}

Kanban View - Card-based workflow:

{
  type: 'kanban',
  groupByField: 'status',
  cardTitle: 'name',
  cardFields: ['email', 'revenue'],
}

Calendar View - Time-based display:

{
  type: 'calendar',
  dateField: 'event_date',
  titleField: 'name',
  defaultView: 'month',
}

Gantt View - Timeline and dependencies:

{
  type: 'gantt',
  startDateField: 'start_date',
  endDateField: 'end_date',
  titleField: 'task_name',
  parentField: 'parent_task',
}

Form Views

Display/edit single records:

Simple Form - Basic layout:

{
  type: 'simple',
  sections: [
    {
      title: 'Basic Information',
      columns: 2,
      fields: ['name', 'email', 'phone'],
    }
  ],
}

Tabbed Form - Organized by tabs:

{
  type: 'tabbed',
  tabs: [
    { title: 'Details', fields: ['name', 'email'] },
    { title: 'Address', fields: ['street', 'city', 'country'] },
  ],
}

Wizard Form - Multi-step process:

{
  type: 'wizard',
  steps: [
    { title: 'Step 1', fields: ['name', 'email'] },
    { title: 'Step 2', fields: ['company', 'role'] },
  ],
}

3. Analytics (src/ui/analytics/)

Reports

Data analysis and visualization:

const report = {
  type: 'tabular',
  object: 'customer_account',
  columns: ['name', 'industry', 'revenue'],
  groupBy: ['industry'],
  aggregations: [
    { field: 'revenue', function: 'SUM' },
    { field: 'id', function: 'COUNT' },
  ],
  filters: [{ field: 'status', operator: 'eq', value: 'active' }],
  sortBy: [{ field: 'revenue', direction: 'desc' }],
};

Dashboards

Multiple widgets in a grid layout:

const dashboard = {
  name: 'sales_dashboard',
  label: 'Sales Dashboard',
  layout: [
    { x: 0, y: 0, w: 6, h: 4, widget: 'revenue_chart' },
    { x: 6, y: 0, w: 6, h: 4, widget: 'pipeline_summary' },
    { x: 0, y: 4, w: 12, h: 6, widget: 'top_accounts' },
  ],
  widgets: [
    {
      id: 'revenue_chart',
      type: 'chart',
      chartType: 'line',
      report: 'monthly_revenue',
    },
    {
      id: 'pipeline_summary',
      type: 'metric',
      label: 'Pipeline Value',
      aggregation: { field: 'amount', function: 'SUM' },
    },
  ],
};

4. Theming (src/ui/theme.zod.ts)

Consistent design system:

const theme = {
  colors: {
    primary: '#0066CC',
    secondary: '#FF6B00',
    success: '#28A745',
    warning: '#FFC107',
    error: '#DC3545',
    background: '#FFFFFF',
    surface: '#F8F9FA',
    text: '#212529',
  },
  typography: {
    fontFamily: 'Inter, sans-serif',
    fontSize: {
      xs: '0.75rem',
      sm: '0.875rem',
      base: '1rem',
      lg: '1.125rem',
      xl: '1.25rem',
    },
  },
  spacing: {
    xs: '0.25rem',
    sm: '0.5rem',
    md: '1rem',
    lg: '1.5rem',
    xl: '2rem',
  },
  borderRadius: {
    sm: '0.25rem',
    md: '0.5rem',
    lg: '1rem',
  },
};

5. Actions (src/ui/action.zod.ts)

User-triggered operations:

const action = {
  name: 'approve_record',
  label: 'Approve',
  type: 'flow',
  flowName: 'approval_flow',
  confirmMessage: 'Are you sure you want to approve this record?',
  successMessage: 'Record approved successfully',
  icon: 'check',
  variant: 'primary',
};

Rendering Flow

┌─────────────────────────────────────────────────────────┐
│ User Action (Navigate, Click, Edit)                     │
└─────────────────────────────────────────────────────────┘
                         ↓
┌─────────────────────────────────────────────────────────┐
│ UI Protocol Resolver                                    │
│ - Resolves view configuration                          │
│ - Fetches object metadata                              │
│ - Checks user permissions                              │
└─────────────────────────────────────────────────────────┘
                         ↓
┌─────────────────────────────────────────────────────────┐
│ Data Fetcher (ObjectQL)                                 │
│ - Builds query from view config                        │
│ - Executes query via driver                            │
│ - Returns data with metadata                           │
└─────────────────────────────────────────────────────────┘
                         ↓
┌─────────────────────────────────────────────────────────┐
│ Renderer (React, Vue, etc.)                             │
│ - Renders components from protocol                     │
│ - Applies theme configuration                          │
│ - Binds data to UI elements                            │
└─────────────────────────────────────────────────────────┘
                         ↓
┌─────────────────────────────────────────────────────────┐
│ Browser / Mobile App                                    │
└─────────────────────────────────────────────────────────┘

Field Widget System

Custom field rendering:

interface FieldWidgetProps {
  value: any;
  onChange: (value: any) => void;
  field: Field;
  readonly: boolean;
  required: boolean;
  error?: string;
}

// Example: Custom email field widget
const EmailWidget: React.FC<FieldWidgetProps> = (props) => {
  return (
    <input
      type="email"
      value={props.value || ''}
      onChange={(e) => props.onChange(e.target.value)}
      disabled={props.readonly}
      required={props.required}
      className={props.error ? 'error' : ''}
    />
  );
};

Page Layouts (FlexiPage)

Flexible page composition:

const page = {
  name: 'account_detail',
  label: 'Account Details',
  regions: [
    {
      name: 'header',
      components: [
        { type: 'record_header', showActions: true },
      ],
    },
    {
      name: 'main',
      columns: [
        {
          components: [
            { type: 'record_detail', layout: 'two_column' },
            { type: 'related_list', relatedObject: 'opportunity' },
          ],
        },
        {
          components: [
            { type: 'activity_timeline' },
            { type: 'chatter_feed' },
          ],
        },
      ],
    },
  ],
};

Best Practices

  1. View Configuration

    • Keep views focused and simple
    • Use appropriate view types for data
    • Optimize column count for readability
    • Provide meaningful default filters
  2. Form Design

    • Group related fields in sections
    • Use 2-column layouts for efficiency
    • Show only necessary fields
    • Provide clear labels and help text
  3. Dashboard Design

    • Limit widgets to 6-8 per dashboard
    • Use consistent chart types
    • Provide drill-down capabilities
    • Update data in real-time or near-real-time
  4. Theme Consistency

    • Use design tokens
    • Maintain color contrast ratios
    • Follow accessibility guidelines
    • Test on multiple screen sizes
  5. Performance

    • Lazy load components
    • Paginate large lists
    • Cache view configurations
    • Minimize re-renders

Related Documentation

For complete API reference, see UI Protocol References.