Appearance
Style System Architecture in Cavai Platform
This document explains the style system architecture used across the Cavai platform components, particularly in the Creative-Engine project.
Style System as "Lego Blocks"
The style system in the Cavai platform functions like modular "lego blocks" that can be combined to create complex visual components. Each style aspect (borders, shadows, background, positioning, etc.) is encapsulated into its own config object and combined through mixins.
Key Components of the Style System
1. Style Config Objects
Style configurations are defined as TypeScript interfaces that represent different aspects of visual styling:
BoxShadowConfig: Controls box shadow properties
- Required properties:
boxShadow,boxShadowSettings
- Required properties:
BorderConfig: Controls border styles
- Required properties:
border,borderStyle
- Required properties:
BackgroundConfig: Controls background properties
- Required properties:
background,backgroundSettings
- Required properties:
SizeConfig: Controls dimension properties
- There are two variants:
MandatorySizeConfig: Required properties:size: boolean,sizeStyle: MandatorySizeStyleOptionalSizeConfig: For components where size is optional
- There are two variants:
2. Style Mixins
The style system is implemented through Vue mixins that apply these style configurations:
- StyleAndClassNameGenerationMixin: Core mixin for generating style objects and class names
- BlockMixin: Applies block-specific styling to components that have a block structure
- VisualElementMixin: Specifically for visual elements with a position in the creative
Specialized Blocks vs Visual Elements
Visual Elements (Simple Blocks)
- Use both
BlockMixinandVisualElementMixin - Require a
blockprop that contains all styling properties - Examples: Text, Button, HTML, Graphic
Specialized Blocks (Complex Blocks)
- Generally do not use
BlockMixinorVisualElementMixindirectly - Access their properties directly from the DataStore
- Handle their own styling through computed properties
- Examples: Form, Slider, Video, Conversation
Implementation Pattern for Specialized Blocks
For specialized blocks like FormBlock and SliderBlock:
- Create a computed property that accesses the block properties directly from DataStore:
javascript
typedBlock(): any {
return DataStore.creativeSettings.creativeBlocks.formProperties
}- Create a styles computed property that processes these properties:
javascript
styles() {
const formProps = this.typedBlock || {}
const styles = {
wrap: {
// Style properties
},
// Other style objects
}
return styles
}- Apply these styles directly in the template:
html
<div :style="styles.wrap">
<!-- Component content -->
</div>Style System Best Practices
- Type Safety: Always ensure style objects match their expected TypeScript interfaces
- Defaults: Provide sensible defaults for all style properties to prevent rendering issues
- Specialized Block Pattern: For specialized blocks, follow the pattern of directly accessing DataStore properties rather than using the general mixins
- Consistent Naming: Use consistent naming conventions for style objects (wrap, container, etc.)
- Error Handling: Include null checks and fallbacks for style properties that might be missing
Common Issues and Solutions
Missing Properties:
- Problem: Errors like "Property 'boxShadow' is missing in type..."
- Solution: Ensure all required properties (boxShadow, border, background, etc.) are defined in your style objects
Type Mismatches:
- Problem: "Type 'Record<string, any>' is not assignable to parameter..."
- Solution: Define explicit types for your style objects that match the expected interfaces
Missing Position:
- Problem: Visual elements require position properties
- Solution: For specialized blocks, don't use VisualElementMixin if position tracking is handled differently