Style Inheritance
Implementing prototype chains and style inheritance for themes, defaults, and templates.
Application Pattern
Style inheritance is an application-level pattern built on top of CRDTs, not a CRDT feature itself. It leverages CRDT properties (automatic sync, conflict resolution) while keeping the inheritance logic in application code.
The Pattern
Instead of storing all properties on each element:
- Store a reference to a parent style/template
- Store only the overridden properties
const styles = yDoc.getMap('styles')
styles.set('heading', {
fontSize: 24,
fontWeight: 'bold',
color: '#333333'
})
const elements = yDoc.getMap('elements')
elements.set('title', {
text: 'Welcome',
styleId: 'heading',
overrides: { color: '#0066cc' } // Override just this
})Resolving Styles
function resolveStyle(element: ElementData): ResolvedStyle {
const baseStyle = styles.get(element.styleId) || {}
return { ...baseStyle, ...element.overrides }
}
// { fontSize: 24, fontWeight: 'bold', color: '#0066cc' }
Multi-Level Inheritance
Chain multiple levels for complex theming:
theme/colors → { primary: '#0066cc', text: '#333' }
↓
templates/card → { padding: 16, titleColor: 'theme.colors.primary' }
↓
elements/card-1 → { templateId: 'card', overrides: { padding: 24 } }Resolution cascades: element overrides → template defaults → theme values.
Named Style Classes
Like CSS classes, elements can reference multiple styles by name. Store class definitions in a map (styleClasses), and let elements specify an array of class names. Resolution merges classes in order, then applies overrides.
Cascading Updates
When a base style changes, all dependent elements automatically get new values:
theme.observeDeep(() => {
renderAll() // Elements resolve to new values
})See Also
- Presentations - Full template system example