WIDGET TIGHTENING PLAN
Comprehensive guidelines for AI-assisted development within the Editor platform
๐ฏ Widget Tightening Plan - Systematic Rollout
Status: ๐ Ready to Execute
Priority: ๐ฅ High
Effort: ~2-4 hours per wave
๐ Current State Analysis
What We Have โ
- 23 widgets total in the system
- 19 widgets have property groups defined
- Most widgets already extend
BaseWidgetComponent(good foundation!) - ButtonWidget is fully enhanced (our reference implementation)
- Unified property system integrated and operational
What Needs Tightening ๐ง
Based on analysis, EVERY widget needs these 4 critical fixes:
- โ Sizing Pattern - Remove hardcoded
width: 100%/height: 100% - โ Property Reading - Ensure reading from correct source (
widget.propertiesvswidget.styles) - โ Custom Styles - Pass explicit inline styles to embeddables
- โ Property Organization - Standardize property groups (Content โ Appearance โ Custom โ Actions)
๐ฏ Recommended Approach: WAVE ROLLOUT
Apply fixes in priority waves to minimize risk and maximize learning.
Why Wave Rollout?
- โ Test each wave before moving to next
- โ Learn patterns that emerge
- โ Adjust strategy based on findings
- โ Minimize risk of breaking multiple widgets
- โ Clear progress tracking
๐ Wave 1: HIGH PRIORITY (Content Widgets)
Duration: 2-3 hours
Impact: Highest user visibility
Risk: Low (clear patterns established)
Widgets to Fix
- TextWidget โญ Most used
- ImageWidget โญ Most used
- LinkWidget
- IconWidget
Why These First?
- Content widgets are most frequently used
- Have clear property patterns (text, colors, sizes)
- Similar structure to ButtonWidget
- Highest ROI for user experience
Fixes Needed Per Widget
1. Sizing Fix (Apply to ALL)
// โ REMOVE from containerStyles:
containerStyles = computed(() => ({
width: '100%', // REMOVE
height: '100%', // REMOVE
// Keep only visual properties
}));
// โ
KEEP in wrapperStyles (inner elements):
wrapperStyles = computed(() => ({
width: '100%', // OK - fills parent
height: '100%', // OK - fills parent
}));
2. Property Reading Fix
// โ WRONG: Reading font from styles
const fontSize = widgetStyles.fontSize;
// โ
CORRECT: Read font from properties
const fontSize = this.widget()?.properties?.fontSize ?? '16px';
3. Custom Styles Fix
// Add customStyles computed signal
customStyles = computed(() => {
const props = this.widget()?.properties || {};
const styles: Record<string, string> = {};
// Font properties
if (props['fontSize']) styles['font-size'] = `${props['fontSize']}px`;
if (props['fontFamily']) styles['font-family'] = props['fontFamily'];
if (props['color']) styles['color'] = props['color'];
// Background/borders (if applicable)
if (props['backgroundColor']) styles['background-color'] = props['backgroundColor'];
return styles;
});
<!-- Pass to embeddable or element -->
<div [ngStyle]="customStyles()">Content</div>
4. Property Groups (Check & Standardize)
// Standard order:
export const WIDGET_PROPERTY_GROUPS: PropertyGroup[] = [
CONTENT_GROUP, // order: 10
APPEARANCE_GROUP, // order: 20
CUSTOM_STYLES_GROUP, // order: 21 (conditional)
LAYOUT_GROUP, // order: 30
ACTIONS_GROUP, // order: 40
];
๐ Wave 2: MEDIUM PRIORITY (Layout/Container Widgets)
Duration: 2-3 hours
Impact: Medium (affects structure)
Risk: Medium (complex layouts)
Widgets to Fix
- CardWidget
- ContainerWidget
- HeroWidget
- FeatureWidget
Why These Second?
- Container widgets with complex layouts
- May have nested widgets (need careful handling)
- Less frequently edited than content widgets
- Patterns learned from Wave 1 apply here
Additional Considerations
- Container sizing: May need
min-heightinstead ofheight: 100% - Nested widgets: Ensure child widgets also resize correctly
- Layout modes: Grid vs Flex vs Free - handle each
๐ Wave 3: LOWER PRIORITY (Form/Input Widgets)
Duration: 2-3 hours
Impact: Medium (form functionality)
Risk: Medium (validation/state management)
Widgets to Fix
- InputWidget
- SelectWidget
- CheckboxWidget
- RadioWidget
- RangeWidget
Why These Third?
- Form widgets have additional complexity (validation, state)
- Less visual customization (more functional)
- Patterns from Waves 1 & 2 refined by now
Additional Considerations
- Form bindings: Ensure reactive forms still work
- Validation: Property changes shouldn't break validation
- State management: Disabled/required states must persist
๐ Wave 4: SPECIALIZED (Media/Complex Widgets)
Duration: 2-4 hours
Impact: Low-Medium (specialized use cases)
Risk: Higher (complex functionality)
Widgets to Fix
- VideoWidget
- GalleryWidget
- PricingWidget (already partially done)
- TestimonialWidget
- DividerWidget
- SpacerWidget
- ShapeWidget
- SimpleWidget
- EmbeddableHostWidget
Why These Last?
- Specialized widgets with unique requirements
- Less frequently used in typical projects
- By now, patterns are well-established
- Can learn from all previous waves
๐ Per-Widget Checklist
For EACH widget, complete this checklist:
1. Sizing โ
- Remove
width: '100%'from root containerStyles - Remove
height: '100%'from root containerStyles - Keep visual properties only (position, display, etc.)
- Verify inner wrappers CAN use 100% (if needed)
- Test drag-to-resize works (right, bottom, corner)
2. Property Reading โ
- Identify all property reads (fontSize, color, etc.)
- Ensure reading from
widget.properties(notwidget.styles) - Add default values for all properties
- Verify font properties work correctly
3. Custom Styles โ
- Create
customStyles = computed(...)signal - Include font properties (fontSize, fontFamily, etc.)
- Include color properties (color, backgroundColor)
- Include border/spacing (if applicable)
- Pass to embeddable via
[ngStyle]or[customStyles]
4. Property Groups โ
- Verify property groups exist (
*-property-groups.ts) - Check group order (Content=10, Appearance=20, etc.)
- Add conditional visibility (if needed)
- Ensure
getValuereads from correct source - Ensure
setValueupdates correct location
5. Testing โ
- Compile successfully (no TypeScript errors)
- Widget renders correctly
- Properties panel shows all groups
- Property changes reflect immediately
- Widget resizes via drag handles
- Changes persist after refresh (flash-persistence)
๐ง Implementation Pattern (Copy-Paste Template)
Step 1: Update Component TypeScript
// 1. Remove hardcoded dimensions
containerStyles = computed(() => {
const props = this.widget()?.properties || {};
return {
// โ NO width, NO height
position: 'relative',
display: 'flex',
'flex-direction': 'column',
'box-sizing': 'border-box',
// ... only visual properties
};
});
// 2. Add customStyles signal
customStyles = computed(() => {
const props = this.widget()?.properties || {};
const styles: Record<string, string> = {};
// Font properties (if text-based widget)
if (props['fontSize']) styles['font-size'] = `${props['fontSize']}px`;
if (props['fontFamily']) styles['font-family'] = props['fontFamily'];
if (props['fontWeight']) styles['font-weight'] = props['fontWeight'];
if (props['color']) styles['color'] = props['color'];
// Background/borders (if visual widget)
if (props['backgroundColor']) styles['background-color'] = props['backgroundColor'];
if (props['borderRadius']) styles['border-radius'] = `${props['borderRadius']}px`;
return styles;
});
// 3. Ensure config reads from properties
config = computed(() => {
const defaultConfig = { /* defaults */ };
return { ...defaultConfig, ...(this.widget()?.properties || {}) };
});
Step 2: Update Template
<!-- Pass customStyles to inner element or embeddable -->
<div
class="widget-container"
[ngStyle]="containerStyles()">
<div
class="content-wrapper"
style="width: 100%; height: 100%;"
[ngStyle]="customStyles()">
<!-- Content here -->
</div>
</div>
Step 3: Update Property Groups
// Ensure standard structure
export const WIDGET_PROPERTY_GROUPS: PropertyGroup[] = [
{
id: 'widget-content',
title: 'Content',
icon: 'fa-edit',
order: 10,
properties: [
{
key: 'text',
label: 'Text',
type: 'string',
getValue: (widget) => widget.properties?.text ?? '',
setValue: (widget, value) => ({
...widget,
properties: { ...widget.properties, text: value }
})
}
]
},
{
id: 'widget-appearance',
title: 'Appearance',
icon: 'fa-palette',
order: 20,
properties: [
// Font, colors, etc.
]
},
// ... more groups
];
๐ฏ Success Metrics
Track progress after each wave:
Per Wave
- All widgets in wave compile successfully
- All widgets render correctly in editor
- All widgets resize via drag handles
- Property changes reflect immediately
- No regression in existing functionality
Overall
- 23/23 widgets follow consistent patterns
- 100% resizable - all widgets drag-resize
- 100% reactive - property changes instant
- 100% persistent - changes survive refresh
- 0 TypeScript errors - clean compilation
- Documentation - patterns documented for AI
โก Quick Wins (Can Do Now)
1. PricingWidget (Already Started)
File: libs/libs-widgets/widgets/src/lib/components/pricing-widget/pricing-widget.component.scss
// โ REMOVE these lines:
.pricing-widget {
width: 100%;
height: 100%;
}
.pricing-widget-container {
width: 100%;
height: 100%;
}
// โ
Replace with:
.pricing-widget {
position: relative;
display: flex;
flex-direction: column;
}
.pricing-widget-container {
position: relative;
display: flex;
flex-direction: column;
flex: 1;
}
Impact: 5 minutes, fixes resizing immediately
๐ Estimated Timeline
| Wave | Widgets | Time | Completion |
|---|---|---|---|
| Wave 1 | 4 widgets | 2-3 hours | Day 1 |
| Wave 2 | 4 widgets | 2-3 hours | Day 2 |
| Wave 3 | 5 widgets | 2-3 hours | Day 3 |
| Wave 4 | 10 widgets | 3-4 hours | Day 4 |
| Total | 23 widgets | 9-13 hours | 4 days |
With your focus: Could complete in 2-3 days working steadily.
๐ Recommended Next Actions
Option 1: Wave-by-Wave (Safest)
- Start with Wave 1 (TextWidget, ImageWidget, LinkWidget, IconWidget)
- Test thoroughly after each widget
- Move to Wave 2 once Wave 1 is solid
- Continue through Wave 4
Pros: Lower risk, clear progress
Cons: Takes longer
Option 2: Pattern-by-Pattern (Fastest)
- Fix sizing pattern across ALL widgets at once
- Then fix property reading across ALL
- Then custom styles across ALL
- Then property groups across ALL
Pros: Faster, consistent pattern
Cons: Higher risk, harder to test
Option 3: Critical Path (Balanced) โญ RECOMMENDED
- Fix Wave 1 completely (most used widgets)
- Apply sizing pattern only to remaining widgets
- Come back for custom styles + property groups later
Pros: Quick wins, lower risk, progressive enhancement
Cons: Widgets temporarily inconsistent
๐ก My Recommendation
Start with Wave 1 + Quick Win
Today/This Session:
- โ Quick Win: Fix PricingWidget CSS (5 minutes)
- ๐ฏ Wave 1: TextWidget (30 minutes)
- ๐ฏ Wave 1: ImageWidget (30 minutes)
- ๐ฏ Wave 1: LinkWidget (20 minutes)
- ๐ฏ Wave 1: IconWidget (20 minutes)
Total: ~2 hours for massive improvement
Why This Order?
- TextWidget + ImageWidget are most frequently used
- Patterns are clear from ButtonWidget
- Quick wins build momentum
- Immediate user value
๐ Bonus: Automated Script (Future)
Idea: Create a script to automate the repetitive parts:
#!/bin/bash
# auto-tighten-widget.sh
# Automatically applies sizing pattern to widget
WIDGET_NAME=$1
echo "๐ง Tightening $WIDGET_NAME..."
# Remove width/height from containerStyles
# Add customStyles template
# Update property groups
echo "โ
$WIDGET_NAME tightened!"
When: After Wave 2 (once patterns are 100% clear)
๐ Documentation to Reference
As you work through each wave, reference these docs:
- WIDGET_SIZING_FIX.md - Sizing pattern
- FONT_PROPERTIES_FIX.md - Property reading pattern
- INTELLIGENT_PROPERTY_ORGANIZATION.md - Property groups
- button-widget.component.ts - Reference implementation
โ Final Checklist: Widget Perfection
Once all waves complete, verify:
- All 23 widgets extend
BaseWidgetComponent - All 23 widgets follow sizing pattern (no hardcoded dimensions)
- All text widgets read font from
properties - All widgets pass custom styles explicitly
- All property groups organized consistently
- All widgets resizable via drag handles
- All property changes instant (flash-persistence)
- 0 TypeScript errors
- 0 linter warnings
- Comprehensive testing complete
Status: ๐ Plan Ready
Next: Execute Wave 1
Goal: Widget Perfection
LET'S TIGHTEN IT UP! ๐งโจ