Smart Variant Creator - UX Review & Critical Issues
Comprehensive analysis of current implementation, bugs, missing features, and required improvements
Smart Variant Creator - UX Review & Critical Issues
๐ธ Current State Analysis
Based on the screenshots and code review, the Smart Variant Creator has significant UX and functionality issues that prevent it from being "incredibly easy to use."
๐จ Critical Issues
1. Modal Doesn't Close โ
Problem: Close buttons are non-functional
Root Cause:
// component.ts line 259
close(): void {
console.log('๐ช [SmartVariantCreator] Close clicked');
this.portalData?.onClosed?.();
}
The modal calls onClosed() but the UX Portal Service might not be properly configured to destroy the component when this callback is invoked.
Fix Required:
- Verify
VariantCreatorModalServiceproperly passesonClosedcallback - Ensure UX Portal destroys the component on close
- Add fallback to directly call
portalService.closePortal()
2. Material Icons Don't Render โ
Problem: Icons show as text ("palette", "close", etc.) instead of Material Symbols
Root Cause: Missing Material Symbols font or incorrect CSS class
What We See:
<!-- This should show an icon but shows "palette" text -->
<span class="material-symbols-outlined">{{ metadataForm.value.icon || 'palette' }}</span>
Fix Required:
- Add Material Symbols font to global styles:
@import url('https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200');
- Or use Angular Material icons with
<mat-icon>component
3. "Customize" Tab Stuck on Loading โ
Problem: Screenshot 2 shows "Loading widget properties..." indefinitely
Root Cause: WidgetPropertyGroupsProvider doesn't include button-specific property groups!
// widget-property-groups.provider.ts line 19-31
private readonly propertyGroups: Record<string, PropertyGroup[]> = {
'button': [...DEFAULT_PROPERTY_GROUPS], // โ Only defaults, no button-specific groups!
// Line 9 has this commented out:
// import { BUTTON_WIDGET_PROPERTY_GROUPS } from '../components/button-widget/button-widget-property-groups';
The property groups EXIST (BUTTON_WIDGET_PROPERTY_GROUPS) but are NOT IMPORTED OR REGISTERED!
Fix Required:
// 1. Uncomment line 9
import { BUTTON_WIDGET_PROPERTY_GROUPS } from '../components/button-widget/button-widget-property-groups';
import { CARD_WIDGET_PROPERTY_GROUPS } from '../components/card-widget/card-widget-property-groups';
import { INPUT_WIDGET_PROPERTY_GROUPS } from '../components/input-widget/input-widget-property-groups';
// ... etc for all core widgets
// 2. Update line 23
'button': [...DEFAULT_PROPERTY_GROUPS, ...BUTTON_WIDGET_PROPERTY_GROUPS],
'card': [...DEFAULT_PROPERTY_GROUPS, ...CARD_WIDGET_PROPERTY_GROUPS],
'input': [...DEFAULT_PROPERTY_GROUPS, ...INPUT_WIDGET_PROPERTY_GROUPS],
4. Confusing User Flow โ ๏ธ
Problem: Users don't understand WHERE core widget properties come from or HOW to modify them
User's Question (from screenshot feedback):
"When we are dealing with core widgets, where do we modify the properties? Or are they hardcoded always? It's very hard to understand still."
Current State:
- Property Groups ARE defined for each core widget (button, card, input, etc.)
- BUT they're not properly loaded in the variant creator
- AND there's no clear explanation that:
- โ Variants customize existing core widget properties
- โ Property groups define what can be customized
- โ Each core widget has pre-defined properties (not hardcoded, but standardized)
Fix Required - Add Clear Onboarding:
<!-- Add at top of "Customize" tab -->
<div class="onboarding-banner">
<span class="material-symbols-outlined">help_outline</span>
<div>
<strong>How it works:</strong>
<p>Core widgets (like Button, Input, Card) have pre-defined property groups.
Customize any property here to create your variant. Unmodified properties
will use the widget's default values.</p>
</div>
</div>
๐ฏ Missing Critical Features
5. No Live Preview โ ๏ธ
Screenshot 3 shows: "Dynamic Preview Coming Soon" placeholder
User Expectation: Real-time widget rendering with applied properties
Current Implementation:
<!-- Just a placeholder -->
<div class="preview-placeholder">
<div class="preview-widget-demo">
<span class="material-symbols-outlined preview-icon">{{ portalData?.baseWidget }}</span>
<h4>{{ metadataForm.value.name || 'Your Variant' }}</h4>
</div>
</div>
Fix Required:
- Dynamically render actual widget component based on
portalData.baseWidget - Apply property values from
propertiesFormto preview widget - Update in real-time when properties change (use
effect())
Implementation Strategy:
// Use Angular's dynamic component loading
private previewContainerRef = viewChild<ViewContainerRef>('previewContainer');
async updateLivePreview() {
const widgetType = this.portalData?.baseWidget;
const componentType = await this.widgetRegistry.getComponentForType(widgetType);
// Clear existing
this.previewContainerRef()?.clear();
// Create instance with current property values
const componentRef = this.previewContainerRef()?.createComponent(componentType);
componentRef.setInput('widget', this.buildPreviewWidget());
}
6. Property Groups Collapsed by Default โ ๏ธ
Current State: Only 2 groups expanded: ['content', 'design']
Problem: Users don't know what other properties exist without manually expanding each group
Fix Options:
Option A - Expand All by Default:
// Initialize with all groups expanded
this.expandedGroups.set(new Set(this.propertyGroups().map(g => g.title)));
Option B - Smart Expansion (Better UX):
// Expand groups with most commonly modified properties
const importantGroups = ['content', 'design', 'appearance', 'layout'];
this.expandedGroups.set(new Set(importantGroups));
7. No Property Search/Filter โ ๏ธ
Problem: Widgets like Card have 8 property groups with 50+ properties
User Pain: Scrolling through all properties to find "border radius" or "background color"
Fix Required: Add search bar at top of Customize tab
<div class="property-search">
<input
type="text"
placeholder="๐ Search properties..."
[(ngModel)]="propertySearchTerm"
class="input">
</div>
// Filter properties based on search
readonly filteredPropertyControls = computed(() => {
const term = this.propertySearchTerm().toLowerCase();
if (!term) return this.propertyControls();
return this.propertyControls().filter(c =>
c.property.label.toLowerCase().includes(term) ||
c.property.description?.toLowerCase().includes(term)
);
});
๐ค Conceptual Clarity Issues
8. Core Widget Properties vs Variants
User's Confusion:
"Where do we modify the properties? Are they hardcoded?"
The Truth (that needs better communication):
Core UI Widgets (Button, Input, Card, etc.) have standardized property groups
- Defined in:
libs/libs-widgets/widgets/src/lib/components/{widget-type}/{widget-type}-property-groups.ts - Example:
BUTTON_WIDGET_PROPERTY_GROUPSdefines all customizable properties - These are NOT hardcoded - they're extensible and discoverable
- Defined in:
Variants are pre-configured instances of core widgets
- A variant is: "Button with these specific property values"
- Example: "Primary Button" = Button widget + {buttonType: 'primary', size: 'medium', theme: 'brand'}
Property Groups Define Customization Surface
- Each property group says: "These are the knobs you can turn"
- Variant Creator shows these knobs and lets you set values
Fix Required - Add Conceptual Guide:
## ๐ Understanding Core Widgets & Variants
### Core UI Widgets
Pre-built components with standardized, extensible properties:
- **Button**: text, type, size, theme, icon, action
- **Input**: placeholder, type, validation, mask
- **Card**: title, image, layout, elevation, actions
### Variants
Your customized versions of core widgets:
- **Primary Button**: Button with brand colors and medium size
- **Login Input**: Input with email validation and custom styling
- **Product Card**: Card with image-first layout and shadow
### Property Groups
Organized collections of customizable properties:
- **Content**: What the widget displays
- **Design**: Colors, borders, spacing
- **Behavior**: Interactions, animations
- **Accessibility**: Labels, ARIA attributes
๐ Step-by-Step Missing Steps
Based on screenshot analysis, the flow is incomplete:
Current Flow (3 steps):
- โ Basic Info - Name, description, category (works)
- โ Customize - Stuck loading (broken)
- โ Preview - Placeholder only (incomplete)
What's Missing:
Before Step 2 (Customize):
- โ No explanation of what properties will be shown
- โ No "Reset to Defaults" option
- โ No "Import from Existing Variant" option
During Step 2 (Customize):
- โ Properties don't load (bug #3)
- โ No search/filter (issue #7)
- โ No "Restore Default Value" per property
- โ No validation feedback
- โ No tooltips explaining what each property does
During Step 3 (Preview):
- โ No live preview (issue #5)
- โ No responsive preview (mobile/tablet/desktop)
- โ No "Test Interactions" mode
- โ No comparison with base widget
After Saving:
- โ No confirmation modal
- โ No "What's Next?" guidance
- โ No quick action to "Use in Builder" or "View in Gallery"
๐ฏ Required Improvements - Priority Matrix
๐ด Critical (Breaks Functionality)
- Fix Property Groups Loading (issue #3)
- Fix Close Button (issue #1)
- Fix Material Icons (issue #2)
๐ก High Priority (Poor UX)
- Add Live Preview (issue #5)
- Add Property Search (issue #7)
- Add Clear Onboarding (issue #4)
๐ข Medium Priority (Nice to Have)
- Smart Property Group Expansion (issue #6)
- Add "Reset to Default" per property
- Add validation feedback
- Add responsive preview modes
๐ต Low Priority (Polish)
- Add property tooltips
- Add "Import from Variant" feature
- Add post-save guidance
- Add comparison mode
๐ ๏ธ Implementation Plan
Phase 1: Fix Broken Functionality โ
Goal: Make it actually work
Fix Property Groups Loading
- Uncomment imports in
WidgetPropertyGroupsProvider - Register all core widget property groups
- Test: Button variant should show 15-20 properties
- Uncomment imports in
Fix Close Button
- Debug
onClosedcallback flow - Add direct portal service call as fallback
- Test: Modal closes on X, Cancel, Escape
- Debug
Fix Material Icons
- Add Material Symbols font to global styles
- Or migrate to Angular Material icons
- Test: All icons render properly
Phase 2: Add Core UX Features ๐
Goal: Make it usable
Implement Live Preview
- Dynamic component loading
- Real-time property application
- Responsive breakpoints
- Test: Preview updates as properties change
Add Property Search
- Search input component
- Filter by label/description
- Highlight matches
- Test: Can find "color" across all groups
Add Onboarding
- Explanation banners
- Contextual help
- Example variants
- Test: New users understand the flow
Phase 3: Polish & Delight โจ
Goal: Make it incredible
Smart Defaults & Suggestions
- AI-suggested property values based on variant name
- "Similar Variants" recommendations
- One-click templates
Advanced Features
- Import from existing variant
- Duplicate with modifications
- Batch property editing
Developer Tools
- Export as code (TypeScript)
- JSON inspector
- Property history/undo
๐จ Design Improvements
Current Design Issues:
- โ Icons shown as text (not actual icons)
- โ "Loading..." state never resolves
- โ Preview shows placeholder instead of widget
- โ Layout is good (3-step wizard)
- โ Color scheme is professional
Design Goals:
- Visual Hierarchy: Guide user through 3 steps clearly
- Immediate Feedback: Show property changes in real-time
- Reduce Cognitive Load: Group related properties, hide complexity
- Delight: Smooth transitions, helpful micro-interactions
๐งช Testing Strategy
Manual Testing Checklist:
Test 1: Create Button Variant
- Open Core UI Library (http://localhost:5200/space/un-test-space/widgets/guide/button)
- Click "Create Variant"
- Modal opens with "Create Button Variant" title
- Step 1: Fill name "My Primary Button", description, select "Style" category
- Click "Next" โ Should go to Step 2
- Step 2: Should see 15-20 button properties (not "Loading...")
- Modify "buttonType" to "primary", "size" to "large"
- Click "Next" โ Should go to Step 3
- Step 3: Should see live preview of button with applied properties
- Click "Save Variant"
- Modal closes
- Variant appears in button variants list
Test 2: Close Modal
- Open variant creator
- Click X button โ Modal closes
- Open again, click "Cancel" โ Modal closes
- Open again, press Escape key โ Modal closes
Test 3: Icons Render
- All Material Symbols icons render as icons (not text)
- Icon in header updates when changing icon field
- Category icons display properly
๐ Success Metrics
Before (Current State):
- โ 0% of variants can be created successfully (blocked by loading bug)
- โ 0% of users understand where properties come from
- โ Modal cannot be closed properly
After (Phase 1):
- โ 100% of core widgets show their property groups
- โ Modal can be closed reliably
- โ Icons render properly
After (Phase 2):
- โ Live preview works for all core widgets
- โ Users can search and find properties quickly
- โ 80% of users complete variant creation without help
After (Phase 3):
- โ Users describe the flow as "incredibly easy"
- โ Average variant creation time: < 2 minutes
- โ 95% variant save success rate
๐ Next Steps
Fix Critical Bugs (Phase 1)
- Start with Property Groups loading (#3)
- Then fix close button (#1)
- Then fix icons (#2)
User Test (After Phase 1)
- Can we create a simple button variant?
- Does the modal close properly?
- Do icons render?
Implement Live Preview (Phase 2, Priority #1)
- This is the most important UX feature
- Without it, users are "flying blind"
Iterate Based on Feedback
- Test with actual space-builders
- Measure completion rates
- Identify pain points
๐ก Key Insight
The infrastructure is 80% there - property groups exist, forms work, styling is good.
The problem is integration - the pieces aren't connected properly:
- Property groups defined โ but not loaded โ
- Close callback defined โ but not wired โ
- Icons components exist โ but font not loaded โ
- Preview structure exists โ but widget not rendered โ
This is a "last mile" problem - we need to connect the dots, not rebuild from scratch.
Last Updated: November 17, 2025 Status: Critical Review - Requires Immediate Action