WIDGET CONSOLIDATION ANALYSIS

Comprehensive guidelines for AI-assisted development within the Editor platform

πŸ” Widget/Embeddable Duplication Analysis

Date: December 6, 2024
Status: 🚨 DUPLICATES FOUND
Impact: HIGH (code maintenance, bundle size, confusion)


🎯 The Problem

We have SIGNIFICANT DUPLICATION across our component libraries:

❌ Same component exists in MULTIPLE places:
β”œβ”€β”€ libs-widgets/widgets (full widgets)
β”œβ”€β”€ libs-ui-core/ui-core (embeddables)
└── libs-ui-core/ui-forms (form embeddables)

πŸ“Š Duplicate Components Found

Category 1: UI Components (12 duplicates)

Component widgets/widgets ui-core ui-forms Status
breadcrumb βœ… βœ… ❌ ⚠️ DUPLICATE
card βœ… (card-widget) βœ… ❌ ⚠️ DUPLICATE
chip βœ… βœ… ❌ ⚠️ DUPLICATE
chip-list βœ… βœ… ❌ ⚠️ DUPLICATE
clipboard βœ… βœ… ❌ ⚠️ DUPLICATE
context-menu βœ… βœ… ❌ ⚠️ DUPLICATE
editable-slug βœ… βœ… ❌ ⚠️ DUPLICATE
icon/icons βœ… (icon-widget) βœ… ❌ ⚠️ DUPLICATE
input βœ… (input-widget) βœ… ❌ ⚠️ DUPLICATE
module-dock-slot βœ… βœ… ❌ ⚠️ DUPLICATE
simple-tabs βœ… βœ… ❌ ⚠️ DUPLICATE
ux-tabs βœ… βœ… ❌ ⚠️ DUPLICATE

Category 2: Form Components (2 duplicates)

Component widgets/widgets ui-core ui-forms Status
checkbox βœ… (checkbox-widget) ❌ βœ… ⚠️ DUPLICATE
select βœ… (select-widget) ❌ βœ… (ux-select) ⚠️ DUPLICATE

Category 3: Unique to libs-widgets (Clean βœ…)

Category 4: Unique to ui-core (Embeddables βœ…)

Category 5: Unique to ui-forms (Form Embeddables βœ…)


πŸ—οΈ Correct Architecture (What It Should Be)

Design Principle

Embeddables (ui-core, ui-forms)
    ↓ used by
Widgets (libs-widgets)
    ↓ used in
Editor/Canvas

Library Responsibilities

1. ui-core (Pure Embeddables)

Purpose: Reusable UI components with NO widget logic

Should contain:

Should NOT contain: Widget lifecycle, BaseWidgetComponent, property groups

2. ui-forms (Form Embeddables)

Purpose: Form-specific reusable components

Should contain:

Should NOT contain: Widget wrappers

3. libs-widgets/widgets (Full Widgets)

Purpose: Editor-aware widgets that extend BaseWidgetComponent

Should contain:

Should: Use embeddables from ui-core and ui-forms, add widget logic


⚠️ Current Issues

Issue 1: Duplicate Implementation

Problem: Same component logic exists in multiple places

Example:

libs-widgets/widgets/src/lib/components/icon-widget/
libs-ui-core/ui-core/src/lib/components/icon/

Both implement icon rendering - which is correct?

Issue 2: Unclear Separation

Problem: No clear rule about what goes where

Questions:

Issue 3: Maintenance Burden

Problem: Changes must be made in multiple places

Example: Fix a bug in chip β†’ Must fix in:

  1. libs-widgets/widgets/chip/
  2. libs-ui-core/ui-core/chip/

❌ Violates DRY principle

Issue 4: Bundle Size

Problem: Same code shipped multiple times

Impact: Larger bundle, slower loads


πŸ’‘ Recommended Consolidation Strategy

Phase 1: Categorize (Define Source of Truth)

For each duplicate, decide:

Option A: Embeddable Only (Keep in ui-core/ui-forms)

Option B: Widget Only (Keep in libs-widgets)

Option C: Both (Embeddable + Widget Wrapper)


Phase 2: Consolidation Rules

Rule 1: UI Components β†’ ui-core

Move to ui-core (keep as embeddables):

Delete from libs-widgets/widgets: Duplicate implementations

Rule 2: Form Components β†’ ui-forms

Move to ui-forms (keep as embeddables):

Delete from libs-widgets/widgets: Duplicate implementations

Rule 3: Widgets β†’ Use Embeddables

Refactor widgets to use embeddables:

// ❌ BEFORE: Widget implements everything
@Component({
  selector: 'lib-icon-widget',
  template: `
    <i class="material-icons">{{ icon }}</i>
  `
})
export class IconWidgetComponent { }

// βœ… AFTER: Widget uses embeddable
@Component({
  selector: 'lib-icon-widget',
  template: `
    <ui-icon [icon]="config().icon" [customStyles]="customStyles()"></ui-icon>
  `
})
export class IconWidgetComponent extends BaseWidgetComponent { }

Phase 3: Implementation Plan

Step 1: Audit (Which implementation to keep?)

For each duplicate:

  1. Compare implementations (ui-core vs widgets)
  2. Choose most robust/feature-complete
  3. Document decision

Step 2: Migrate (Move logic to embeddables)

  1. Keep embeddable in ui-core/ui-forms
  2. Refactor widget to use embeddable
  3. Add widget-specific logic (properties, variants)
  4. Test thoroughly

Step 3: Delete (Remove duplicates)

  1. Delete duplicate from widgets/
  2. Update imports across codebase
  3. Update barrel exports
  4. Verify no broken references

Step 4: Document (Prevent future duplication)

  1. Update AGENTS.md with clear rules
  2. Add linting rules (if possible)
  3. Document architecture decisions

🎯 Specific Consolidation Examples

Example 1: Icon Component

Current State ❌

libs-widgets/widgets/src/lib/components/icon-widget/
β”œβ”€β”€ icon-widget.component.ts (widget implementation)
β”œβ”€β”€ icon-widget-property-groups.ts
└── index.ts

libs-ui-core/ui-core/src/lib/components/icon/
β”œβ”€β”€ icon.component.ts (embeddable implementation)
└── index.ts

Desired State βœ…

libs-ui-core/ui-core/src/lib/components/icon/
β”œβ”€β”€ icon.component.ts (embeddable - pure UI)
└── index.ts

libs-widgets/widgets/src/lib/components/icon-widget/
β”œβ”€β”€ icon-widget.component.ts (widget - uses <ui-icon>)
β”œβ”€β”€ icon-widget-property-groups.ts
└── index.ts

Implementation

// icon-widget.component.ts
import { UiIconComponent } from '@libs-ui-core/ui-core';

@Component({
  selector: 'lib-icon-widget',
  imports: [UiIconComponent],
  template: `
    <ui-icon 
      [icon]="config().icon"
      [size]="config().size"
      [color]="config().color"
      [customStyles]="customStyles()"
    ></ui-icon>
  `
})
export class IconWidgetComponent extends BaseWidgetComponent {
  config = computed(() => ({...}));
  customStyles = computed(() => ({...}));
}

Example 2: Input Component

Current State ❌

libs-widgets/widgets/src/lib/components/input-widget/
└── input-widget.component.ts (full implementation)

libs-ui-core/ui-core/src/lib/components/input/
└── ui-input.component.ts (full implementation)

Desired State βœ…

libs-ui-core/ui-core/src/lib/components/input/
└── ui-input.component.ts (embeddable - pure input)

libs-widgets/widgets/src/lib/components/input-widget/
└── input-widget.component.ts (widget - uses <ui-input>)

Example 3: Card Component

Current State ❌

libs-widgets/widgets/src/lib/components/card-widget/
└── card-widget.component.ts (full implementation)

libs-ui-core/ui-core/src/lib/components/card/
β”œβ”€β”€ card.component.ts (full implementation)
β”œβ”€β”€ card-header.component.ts
β”œβ”€β”€ card-content.component.ts
└── card-footer.component.ts

Desired State βœ…

libs-ui-core/ui-core/src/lib/components/card/
β”œβ”€β”€ card.component.ts (embeddable - pure card UI)
β”œβ”€β”€ card-header.component.ts
β”œβ”€β”€ card-content.component.ts
└── card-footer.component.ts

libs-widgets/widgets/src/lib/components/card-widget/
└── card-widget.component.ts (widget - uses <ui-card>)

CardWidget should use <ui-card> embeddable!


πŸ”₯ Impact of Consolidation

Before ❌

After βœ…


πŸ“Š Estimated Effort

Phase Components Effort Impact
Audit 14 duplicates 1 hour Understand current state
Migrate High Priority 5 components 3-4 hours Button, Card, Input, Icon, Checkbox
Migrate Medium Priority 5 components 2-3 hours Tabs, Chip, Select, Context Menu
Migrate Low Priority 4 components 1-2 hours Breadcrumb, Clipboard, Editable Slug, Module Dock
Testing & Cleanup All 2 hours Verify, delete duplicates, update docs
TOTAL 14 duplicates 9-12 hours Clean architecture

🎯 Recommended Approach

Option 1: Aggressive Consolidation (Recommended ⭐)

Timeline: 2-3 days
Risk: Medium
Reward: Clean architecture

Steps:

  1. Audit all 14 duplicates (1 hour)
  2. Keep embeddables in ui-core/ui-forms as source of truth
  3. Refactor widgets to use embeddables (like ButtonWidget does)
  4. Delete duplicates from widgets/
  5. Test thoroughly
  6. Document architecture

Result: Clear separation, no duplication, smaller bundle


Option 2: Gradual Consolidation

Timeline: 1-2 weeks
Risk: Low
Reward: Medium

Steps:

  1. Mark duplicates with deprecation warnings
  2. Create migration guide for each
  3. Gradually migrate over time
  4. Delete when all usages updated

Result: Safer, but slower


Option 3: Live with Duplication (NOT Recommended ❌)

Timeline: 0 (no action)
Risk: None
Reward: None

Consequence: Technical debt grows, bundle size increases, maintenance harder


πŸ’‘ My Strong Recommendation

Do Option 1: Aggressive Consolidation NOW

Why?

  1. You're in active development - no backward compatibility needed
  2. Patterns are clear - ButtonWidget shows the way
  3. Momentum is high - we just fixed all sizing issues
  4. Foundation is solid - unified property system ready
  5. Technical debt is young - easier to fix now than later

Plus, you said: "condensce the similar or same widgets" - you WANT this done!


πŸš€ Proposed Consolidation Order

Priority 1: Most Impactful (Start Here!)

  1. card-widget β†’ Use <ui-card> embeddable
  2. input-widget β†’ Use <ui-input> embeddable
  3. checkbox-widget β†’ Use <ui-checkbox> embeddable from ui-forms
  4. select-widget β†’ Use <ux-select> embeddable from ui-forms

Why: High usage, clear embeddable pattern, immediate benefit


Priority 2: Medium Impact

  1. icon-widget β†’ Use <ui-icon> embeddable
  2. simple-tabs β†’ Use <simple-tabs> embeddable (or consolidate into ux-tabs)
  3. ux-tabs β†’ Keep embeddable, remove widget duplicate
  4. chip-widget β†’ Use <ui-chip> embeddable
  5. context-menu β†’ Keep embeddable in ui-core, delete from widgets

Priority 3: Lower Impact

  1. breadcrumb β†’ Likely keep in ui-core only (not typically a widget)
  2. clipboard β†’ Likely keep in ui-core only (utility component)
  3. editable-slug β†’ Keep in ui-core only (specialized input)
  4. module-dock-slot β†’ Keep in ui-core only (layout component)

πŸ“ Consolidation Checklist

For EACH duplicate:

Step 1: Audit

Step 2: Choose Source of Truth

Step 3: Refactor Widget (if needed)

Step 4: Delete Duplicate

Step 5: Test


🎊 Expected Outcomes

After consolidation:

Code Quality βœ…

Bundle Size βœ…

Developer Experience βœ…


πŸ”₯ The Bottom Line

Current State: 🚨 14 duplicate components
Goal: 🎯 Zero duplication, clear architecture
Effort: 9-12 hours over 2-3 days
Reward: ♾️ Clean codebase, easy maintenance, smaller bundle

Recommendation: DO IT NOW while momentum is high!


🎯 What Do You Want?

Option A: FULL CONSOLIDATION (Aggressive)

βœ… Fix all 14 duplicates
βœ… Clean architecture
⏰ 9-12 hours

Option B: TOP 5 ONLY (Balanced)

βœ… Fix most impactful (card, input, checkbox, select, icon)
⏰ 3-4 hours

Option C: DOCUMENT ONLY (Passive)

πŸ“š Document the issue, fix later
⏰ 30 minutes


Status: πŸ“‹ Analysis complete
Decision: Awaiting your call
Ready: To execute immediately

Let me know which option you prefer! πŸš€