UI BuilderUI Builder
Core
  • Introduction
  • Quick Start
Component System
  • Components Intro
  • Shadcn Registry
  • Custom Components
  • Advanced Configuration
  • Panel Configuration
Data & Variables
  • Variables
  • Variable Binding
  • Function Registry
  • Editing Restrictions
Layout & Persistence
  • Layer Structure
  • State Management & Persistence
Rendering
  • Rendering Pages
  1. Component System
  2. Advanced Configuration
Advanced Component Configuration

Take your component integration to the next level with field overrides, default children, and automatic variable bindings. These advanced techniques create polished, user-friendly editing experiences.

Loading...
Live Demo: Immutable Bindings

Best Practices

Field Overrides

  • Always override className with classNameFieldOverrides() for consistent Tailwind editing
  • Choose appropriate children overrides based on content type:
    • childrenAsTextareaFieldOverrides() for simple text (span, p, headings)
    • childrenFieldOverrides() for nested components (div, containers)
    • childrenAsTipTapFieldOverrides() for rich text (Markdown components)
  • Create domain-specific overrides for complex data types (colors, dates, files)
  • Use conditional overrides to hide advanced options in simple mode

Default Children

  • Provide meaningful defaults that demonstrate proper component usage
  • Keep structures shallow initially to avoid overwhelming new users
  • Use descriptive names for child layers to help with navigation
  • Include all dependencies - ensure referenced component types are in your registry
  • Use unique IDs to prevent conflicts when components are duplicated

Variable Bindings

  • Use immutable bindings for:
    • System data (user IDs, system versions)
    • Brand elements (colors, logos, company names)
    • Security-sensitive data (roles, permissions)
    • Template integrity variables
  • Leave content variables mutable so editors can customize text and messaging
  • Combine with field overrides using textInputFieldOverrides() for the best UX
  • Test binding scenarios to ensure the editing experience is smooth

Performance Tips

  • Use commonFieldOverrides() when you need standard className/children handling
  • Memoize expensive overrides if they perform complex calculations
  • Keep default children reasonable to avoid slow initial renders
  • Cache field override functions to prevent unnecessary re-renders

Integration with Other Features

These advanced configuration techniques work seamlessly with:

  • Variables Panel - Manage variables that power your bindings
  • Props Panel - Enhanced forms with your custom field overrides
  • Code Generation - Exported code respects your component definitions
  • LayerRenderer - Variable values are resolved at render time

What's Next?

With advanced configuration mastered, explore:

  • Variables - Create dynamic, data-driven interfaces
  • Panel Configuration - Customize the editor panels themselves
  • Persistence - Save and load your enhanced component configurations

These advanced techniques transform UI Builder from a simple visual editor into a powerful, domain-specific design tool tailored to your exact needs.

Field Overrides

Field overrides replace auto-generated form fields with specialized input controls. Instead of basic text inputs, users get rich editors, color pickers, icon selectors, and more.

Available Built-in Field Overrides

classNameFieldOverrides(layer)

Advanced Tailwind CSS class editor with:

  • Auto-complete for Tailwind classes
  • Responsive breakpoint controls (sm:, md:, lg:, xl:)
  • Visual class grouping and validation
  • Theme-aware suggestions
tsx
1fieldOverrides: { 2 className: (layer) => classNameFieldOverrides(layer) 3}

childrenFieldOverrides(layer)

Searchable component selector for child components:

  • Dropdown with available component types
  • Search and filter capabilities
  • Respects component hierarchy
tsx
1fieldOverrides: { 2 children: (layer) => childrenFieldOverrides(layer) 3}

childrenAsTextareaFieldOverrides(layer)

Multi-line text editor for simple text content:

  • Perfect for span, p, and heading elements
  • Multi-line editing support
tsx
1fieldOverrides: { 2 children: (layer) => childrenAsTextareaFieldOverrides(layer) 3}

childrenAsTipTapFieldOverrides(layer)

Rich text editor using TipTap:

  • WYSIWYG markdown editing
  • Formatting toolbar with bold, italic, links
  • Ideal for Markdown components
tsx
1fieldOverrides: { 2 children: (layer) => childrenAsTipTapFieldOverrides(layer) 3}

iconNameFieldOverrides(layer)

Visual icon picker:

  • Grid of available icons
  • Search functionality
  • Live preview
tsx
1fieldOverrides: { 2 iconName: (layer) => iconNameFieldOverrides(layer) 3}

textInputFieldOverrides(layer, allowVariableBinding, propName)

Enhanced text input with optional variable binding support:

  • Variable binding UI when allowVariableBinding is true
  • Automatic binding/unbinding controls
  • Immutable binding badges
tsx
1fieldOverrides: { 2 title: (layer) => textInputFieldOverrides(layer, true, 'title') 3}

commonFieldOverrides()

Convenience function that applies standard overrides for className and children:

tsx
1fieldOverrides: commonFieldOverrides() 2// Equivalent to: 3// { 4// className: (layer) => classNameFieldOverrides(layer), 5// children: (layer) => childrenFieldOverrides(layer) 6// }

Creating Custom Field Overrides

Create specialized input controls for unique data types:

tsx
1import { AutoFormInputComponentProps } from '@/components/ui/ui-builder/types'; 2import { FormItem, FormLabel, FormControl } from '@/components/ui/form'; 3 4const colorPickerFieldOverride = (layer) => ({ 5 fieldType: ({ label, field }: AutoFormInputComponentProps) => ( 6 <FormItem> 7 <FormLabel>{label}</FormLabel> 8 <FormControl> 9 <div className="flex gap-2 items-center"> 10 <input 11 type="color" 12 value={field.value || '#000000'} 13 onChange={(e) => field.onChange(e.target.value)} 14 className="w-12 h-8 rounded border cursor-pointer" 15 /> 16 <input 17 type="text" 18 value={field.value || ''} 19 onChange={(e) => field.onChange(e.target.value)} 20 placeholder="#000000" 21 className="flex-1 px-3 py-2 border rounded-md" 22 /> 23 </div> 24 </FormControl> 25 </FormItem> 26 ) 27}); 28 29// Use in component definition: 30fieldOverrides: { 31 brandColor: colorPickerFieldOverride, 32 className: (layer) => classNameFieldOverrides(layer) 33}

Conditional Field Overrides

Hide or show fields based on other prop values:

tsx
1const conditionalFieldOverride = (layer) => ({ 2 isHidden: (currentValues) => currentValues.mode === 'simple', 3 fieldType: ({ label, field }) => ( 4 <FormItem> 5 <FormLabel>{label}</FormLabel> 6 <FormControl> 7 <AdvancedEditor value={field.value} onChange={field.onChange} /> 8 </FormControl> 9 </FormItem> 10 ) 11});

Default Children

Provide sensible default child components when users add your component to the canvas.

Simple Text Defaults

For basic text components:

tsx
1span: { 2 schema: z.object({ 3 className: z.string().optional(), 4 children: z.string().optional(), 5 }), 6 fieldOverrides: { 7 className: (layer) => classNameFieldOverrides(layer), 8 children: (layer) => childrenAsTextareaFieldOverrides(layer) 9 }, 10 defaultChildren: "Default text content" 11}

Component Layer Defaults

For complex nested structures:

tsx
1Button: { 2 component: Button, 3 schema: z.object({ 4 className: z.string().optional(), 5 children: z.any().optional(), 6 variant: z.enum(['default', 'destructive']).default('default'), 7 }), 8 from: '@/components/ui/button', 9 defaultChildren: [ 10 { 11 id: "button-text", 12 type: "span", 13 name: "Button Text", 14 props: {}, 15 children: "Click me", 16 } 17 ], 18 fieldOverrides: commonFieldOverrides() 19}

Important: All component types referenced in defaultChildren must exist in your registry.

Rich Default Structures

Create sophisticated default layouts:

tsx
1Card: { 2 component: Card, 3 schema: z.object({ 4 className: z.string().optional(), 5 children: z.any().optional(), 6 }), 7 from: '@/components/ui/card', 8 defaultChildren: [ 9 { 10 id: "card-header", 11 type: "div", 12 name: "Header", 13 props: { className: "p-6 pb-0" }, 14 children: [ 15 { 16 id: "card-title", 17 type: "span", 18 name: "Title", 19 props: { className: "text-2xl font-semibold" }, 20 children: "Card Title" 21 } 22 ] 23 }, 24 { 25 id: "card-content", 26 type: "div", 27 name: "Content", 28 props: { className: "p-6" }, 29 children: "Card content goes here." 30 } 31 ], 32 fieldOverrides: commonFieldOverrides() 33}

Default Variable Bindings

Automatically bind component properties to variables when components are added to the canvas. Perfect for system data, branding, and user information.

Basic Variable Bindings

tsx
1UserProfile: { 2 component: UserProfile, 3 schema: z.object({ 4 userId: z.string().default(''), 5 displayName: z.string().default('Anonymous'), 6 email: z.string().optional(), 7 }), 8 from: '@/components/ui/user-profile', 9 defaultVariableBindings: [ 10 { 11 propName: 'userId', 12 variableId: 'current_user_id', 13 immutable: true // System data - cannot be unbound 14 }, 15 { 16 propName: 'displayName', 17 variableId: 'current_user_name', 18 immutable: false // Can be customized 19 } 20 ], 21 fieldOverrides: { 22 userId: (layer) => textInputFieldOverrides(layer, true, 'userId'), 23 displayName: (layer) => textInputFieldOverrides(layer, true, 'displayName'), 24 email: (layer) => textInputFieldOverrides(layer, true, 'email'), 25 } 26}

Immutable Bindings for Critical Data

Use immutable: true to prevent users from unbinding critical data:

tsx
1BrandedButton: { 2 component: BrandedButton, 3 schema: z.object({ 4 text: z.string().default('Click me'), 5 brandColor: z.string().default('#000000'), 6 companyName: z.string().default('Company'), 7 }), 8 from: '@/components/ui/branded-button', 9 defaultVariableBindings: [ 10 { 11 propName: 'brandColor', 12 variableId: 'primary_brand_color', 13 immutable: true // Prevents breaking brand guidelines 14 }, 15 { 16 propName: 'companyName', 17 variableId: 'company_name', 18 immutable: true // Consistent branding 19 } 20 // 'text' is not bound, allowing content customization 21 ], 22 fieldOverrides: { 23 text: (layer) => textInputFieldOverrides(layer, true, 'text'), 24 brandColor: (layer) => textInputFieldOverrides(layer, true, 'brandColor'), 25 companyName: (layer) => textInputFieldOverrides(layer, true, 'companyName'), 26 } 27}

When to Use Immutable Bindings:

  • System data: User IDs, tenant IDs, system versions
  • Brand consistency: Colors, logos, company names
  • Security: Roles, permissions, access levels
  • Template integrity: Critical variables in white-label scenarios

Variable Binding UI

When using textInputFieldOverrides with variable binding enabled, users see:

  • 🔗 Bind Variable button for unbound properties
  • Variable name, type, and default value for bound properties
  • 🔒 Immutable badge for protected bindings
  • Unbind button for mutable bindings only

Live Example

See these advanced configuration techniques in action: