diff --git a/dev-docs/tasks/phase-8-styles-overhaul/PHASE-8-OVERVIEW.md b/dev-docs/tasks/phase-8-styles-overhaul/PHASE-8-OVERVIEW.md new file mode 100644 index 0000000..9ee409d --- /dev/null +++ b/dev-docs/tasks/phase-8-styles-overhaul/PHASE-8-OVERVIEW.md @@ -0,0 +1,170 @@ +# Phase 8: Styles Overhaul + +## Overview + +Phase 8 transforms Noodl's styling experience from "start with nothing, figure it out yourself" to "sensible defaults that scale with your needs." This phase builds on Noodl's existing style tokens and variant systems, enhancing them into a cohesive design system that works for beginners and power users alike. + +**Philosophy**: Make the happy path so good that manual styling feels unnecessary, while preserving complete freedom for those who need it. + +--- + +## The Problem We're Solving + +### Current Pain Points + +1. **Blank Canvas Syndrome**: Every new project starts with unstyled HTML elements +2. **Repetitive Setup**: Users recreate the same color schemes, spacing scales, and button styles for every project +3. **Inconsistent Results**: Without a system, apps become a patchwork of arbitrary values +4. **Beginner Overwhelm**: New users don't know where to start with styling +5. **Power User Friction**: Experienced users want systematic design tokens but have to build them from scratch + +### The Vision + +``` +TODAY: + Drag "Button" → Get unstyled HTML button → 10 min styling + +AFTER PHASE 8: + Choose preset at project creation → + Drag "Button" → Get beautiful themed button → + Customize if needed (or don't) +``` + +--- + +## Three Levels of Styling Freedom + +| Level | Users | What They See | Philosophy | +| ---------------------- | ---------- | --------------------------- | ------------------------------ | +| **1. Variants** | Everyone | Dropdown picker | "Pick one, done" | +| **2. Token Overrides** | Designers | Token selector per property | "Stay systematic, customize" | +| **3. Manual Values** | Edge cases | Full CSS control | "You're on your own, but free" | + +All three levels coexist. Nothing is blocked. The UX guides users toward systematic approaches while preserving escape hatches. + +--- + +## Task Series + +| Task | Name | Effort | Dependencies | +| ---------- | -------------------------- | --------- | ------------------------------------------- | +| STYLE-001 | Token System Enhancement | 12-16 hrs | None | +| STYLE-002 | Element Configs & Variants | 16-20 hrs | STYLE-001 | +| STYLE-003 | Style Presets System | 8-12 hrs | STYLE-001, STYLE-002 | +| STYLE-004 | Property Panel UX Overhaul | 12-16 hrs | STYLE-002 | +| STYLE-005 | Smart Style Suggestions | 8-10 hrs | STYLE-004 | +| WIZARD-001 | Project Creation Wizard | 20-28 hrs | STYLE-003, GIT-004A*, DEPLOY-001*, AI-004\* | + +\*Optional dependencies - wizard can ship incrementally + +**Total Estimated Effort**: 76-102 hours + +--- + +## Architecture Overview + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ PROJECT STYLE SYSTEM │ +└─────────────────────────────────────────────────────────────────┘ + │ + ┌────────────────────┼────────────────────┐ + ▼ ▼ ▼ +┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ +│ STYLE TOKENS │ │ ELEMENT CONFIGS │ │ STYLE PRESETS │ +│ (STYLE-001) │ │ (STYLE-002) │ │ (STYLE-003) │ +│ │ │ │ │ │ +│ Colors │ │ Group defaults │ │ "Modern" │ +│ Spacing │ │ Button variants │ │ "Minimal" │ +│ Typography │ │ Text defaults │ │ "Playful" │ +│ Borders │ │ Input variants │ │ "Enterprise" │ +│ Shadows │ │ etc. │ │ "Custom" │ +│ Animations │ │ │ │ │ +└────────┬────────┘ └────────┬────────┘ └────────┬────────┘ + │ │ │ + └────────────────────┼────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ PROPERTY PANEL UX (STYLE-004) │ +│ │ +│ Level 1: Variant Picker (default view) │ +│ Level 2: Token Overrides (expanded) │ +│ Level 3: Manual Values (advanced section) │ +└─────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ SMART SUGGESTIONS (STYLE-005) │ +│ │ +│ "You've used this color 5 times - save as token?" │ +│ "This element has 4 custom values - save as variant?" │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Integration Points + +### Project Creation Wizard (WIZARD-001) + +- Preset selection UI with visual previews +- Sets initial token values based on chosen preset +- Can be skipped (defaults to "Modern" preset) + +### Existing Style Tokens Panel + +- Enhanced with full token categories +- Visual token picker with previews +- Import/export functionality + +### Existing Style Variants + +- Pre-populated based on element configs +- New "Save as Variant" workflow +- Variant inheritance from project tokens + +--- + +## Success Metrics + +| Metric | Current | Target | Measurement | +| ------------------------ | ------- | ------- | ----------------- | +| Time to styled button | ~10 min | <10 sec | User testing | +| Projects using tokens | ~5% | >60% | Analytics | +| Style consistency score | Low | High | Design review | +| Beginner completion rate | ~40% | >80% | Onboarding funnel | + +--- + +## Risk Assessment + +| Risk | Likelihood | Impact | Mitigation | +| --------------------------------- | ---------- | ------ | ----------------------------------------------- | +| Breaking existing projects | Medium | High | Backward compatibility layer; new system opt-in | +| Performance overhead | Low | Medium | Token resolution caching; lazy loading | +| User confusion (too many options) | Medium | Medium | Progressive disclosure; sensible defaults | +| Migration complexity | Medium | Medium | Clear upgrade path; automatic token extraction | + +--- + +## Open Questions + +1. **Migration**: How do we handle existing projects? Opt-in to new system, or automatic detection/upgrade? +2. **Custom Presets**: Should users be able to save/share their own presets? +3. **Dark Mode**: Built into presets (each preset has light/dark), or separate toggle? +4. **Component Library**: Does Phase 8 create the foundation for a future Noodl prefab library? + +--- + +## References + +- Tailwind CSS Design System: https://tailwindcss.com/docs +- shadcn/ui Theming: https://ui.shadcn.com/docs/theming +- Radix Themes: https://www.radix-ui.com/themes/docs +- Existing Noodl Style Tokens (experimental) +- Existing Noodl Style Variants system + +--- + +_Last Updated: January 2026_ diff --git a/dev-docs/tasks/phase-8-styles-overhaul/QUICK-REFERENCE.md b/dev-docs/tasks/phase-8-styles-overhaul/QUICK-REFERENCE.md new file mode 100644 index 0000000..b3ee427 --- /dev/null +++ b/dev-docs/tasks/phase-8-styles-overhaul/QUICK-REFERENCE.md @@ -0,0 +1,169 @@ +# Phase 8: Styles Overhaul - Quick Reference + +## TL;DR + +Transform Noodl's styling from "blank canvas every time" to "beautiful defaults that scale." Three levels of control: Variant Picker (easy) → Token Overrides (intermediate) → Manual Values (advanced). + +--- + +## Task Summary + +| Task | Name | Effort | Status | +|------|------|--------|--------| +| STYLE-001 | Token System Enhancement | 12-16 hrs | 🔴 Not Started | +| STYLE-002 | Element Configs & Variants | 16-20 hrs | 🔴 Not Started | +| STYLE-003 | Style Presets System | 8-12 hrs | 🔴 Not Started | +| STYLE-004 | Property Panel UX Overhaul | 12-16 hrs | 🔴 Not Started | +| STYLE-005 | Smart Style Suggestions | 8-10 hrs | 🔴 Not Started | +| WIZARD-001 | Project Creation Wizard | 20-28 hrs | 🔴 Not Started | + +**Total: 76-102 hours** + +--- + +## Dependency Chain + +``` +STYLE-001 (Tokens) + │ + ├──► STYLE-002 (Element Configs) ──┐ + │ │ + └──► STYLE-003 (Presets) ─────────►├──► STYLE-004 (Property Panel) + │ │ │ + │ │ ▼ + │ │ STYLE-005 (Suggestions) + │ │ + └──────────────────────┴──► WIZARD-001 (Project Wizard) + │ + ┌───────┴───────┐ + │ Optional: │ + │ GIT-004A │ + │ DEPLOY-001 │ + │ AI-004 │ + │ BACKEND-001 │ + └───────────────┘ +``` + +--- + +## Key Deliverables + +### STYLE-001: Token System +- Complete token categories (colors, spacing, typography, borders, shadows, animations) +- Tailwind-inspired scales +- Token picker component +- Enhanced tokens panel + +### STYLE-002: Element Configs +- Pre-built variants for Button, Group, Text, Input +- Size presets (sm, md, lg, xl) +- State handling (hover, active, disabled) +- **BUG FIX**: Text element default sizing + +### STYLE-003: Presets +- 5 built-in presets (Modern, Minimal, Playful, Enterprise, Soft) +- Preset selector with previews +- Custom preset creation +- Import/export + +### STYLE-004: Property Panel +- Variant picker (Level 1) +- Token overrides section (Level 2) +- Advanced/manual section (Level 3) +- Override indicators + +### STYLE-005: Suggestions +- Repeated value detection +- Variant candidate detection +- Inconsistency detection +- Non-intrusive UI + +### WIZARD-001: Project Creation Wizard +- Three entry modes (Quick/Guided/AI Builder) +- Style preset selection with previews +- Backend & auth configuration +- GitHub & deployment integration +- AI scaffold generation (optional) + +--- + +## File Locations + +``` +dev-docs/tasks/phase-8-styles-overhaul/ +├── PHASE-8-OVERVIEW.md +├── STYLE-001-token-system/ +│ └── README.md +├── STYLE-002-element-configs/ +│ └── README.md +├── STYLE-003-presets/ +│ └── README.md +├── STYLE-004-property-panel/ +│ └── README.md +├── STYLE-005-suggestions/ +│ └── README.md +└── WIZARD-001-project-creation/ + └── README.md +``` + +--- + +## Integration Points + +| Feature | Integrates With | +|---------|-----------------| +| Presets | Project Creation Wizard (WIZARD-001) | +| Tokens | Existing experimental style tokens panel | +| Variants | Existing style variants system | +| Property Panel | Existing property editor | +| Suggestions | New floating UI system | + +--- + +## The Big Picture + +**Before Phase 8:** +``` +New Project → Blank elements → 10 min styling each → Inconsistent app +``` + +**After Phase 8:** +``` +New Project → Pick preset → Styled elements instantly → Consistent app + → Customize with tokens if needed + → Full CSS control always available +``` + +--- + +## Risk Mitigation + +1. **Backward Compatibility**: All existing projects work unchanged +2. **Opt-In System**: New features don't force migration +3. **Preserved Freedom**: Manual controls always available in Advanced section +4. **Progressive Disclosure**: Complexity hidden until needed + +--- + +## Success Metrics + +| Metric | Target | +|--------|--------| +| Time to styled button | <10 seconds (from ~10 min) | +| Projects using tokens | >60% (from ~5%) | +| Beginner completion rate | >80% (from ~40%) | + +--- + +## Notes for Implementation + +1. Start with STYLE-001 - everything else depends on it +2. The Text element bug fix is in STYLE-002 +3. STYLE-003 and STYLE-002 can be parallelized after STYLE-001 +4. STYLE-005 is polish - can be deprioritized if needed +5. WIZARD-001 can ship incrementally (start with just presets, add integrations later) +6. WIZARD-001's optional dependencies (GIT, DEPLOY, AI) can be stubbed initially + +--- + +*Quick Reference v1.0 - January 2026* diff --git a/dev-docs/tasks/phase-8-styles-overhaul/README.md b/dev-docs/tasks/phase-8-styles-overhaul/README.md new file mode 100644 index 0000000..f58bdc6 --- /dev/null +++ b/dev-docs/tasks/phase-8-styles-overhaul/README.md @@ -0,0 +1,857 @@ +# WIZARD-001: Project Creation Wizard + +## Overview + +Create a guided project setup experience that transforms "blank canvas anxiety" into "ready to build in 60 seconds." The wizard integrates style presets, backend configuration, GitHub connection, deployment setup, and AI scaffolding into a streamlined flow. + +**Phase:** 8 (Styles Overhaul) or standalone +**Priority:** HIGH (major UX improvement) +**Effort:** 20-28 hours +**Risk:** Medium (integrates multiple systems) +**Dependencies:** STYLE-003 (Presets), GIT-004A (GitHub OAuth), DEPLOY-001, AI-004 + +--- + +## Background + +### Current State + +Creating a new Noodl project: +1. Click "New Project" +2. Enter name +3. Get blank canvas +4. Manually configure everything: styling, backend, git, deployment... + +### Target State + +A Replit/Vercel-style wizard: +1. Choose how to start (Quick/Guided/AI) +2. Pick style preset (or describe your app) +3. Configure backend +4. Connect GitHub +5. Set up deployment +6. (Optional) AI generates scaffold +7. **Start building with everything ready** + +--- + +## The Three Entry Modes + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ CREATE NEW PROJECT │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ How would you like to start? │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ ⚡ QUICK START │ │ +│ │ Blank project with Modern preset. │ │ +│ │ Configure everything later. │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ 🛠️ GUIDED SETUP │ │ +│ │ Walk through style, backend, GitHub, and deployment │ │ +│ │ options step by step. │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ ✨ AI PROJECT BUILDER │ │ +│ │ Describe what you want to build. AI sets up │ │ +│ │ everything and generates starter components. │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Guided Setup Flow + +### Step 1: Project Basics + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ NEW PROJECT Step 1/6 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ PROJECT NAME │ +│ [My Awesome App ] │ +│ │ +│ DESCRIPTION (optional) │ +│ [A task management tool for small teams ] │ +│ │ +│ 💡 Tip: A good description helps AI generate better │ +│ components if you enable AI scaffolding later. │ +│ │ +│ │ +│ │ +│ [Next: Style Preset →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Step 2: Style Preset + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ STYLE PRESET Step 2/6 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Choose a visual style for your project: │ +│ │ +│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ +│ │ Modern │ │ Minimal │ │ Playful │ │ Corp │ │ Soft │ │ +│ │ │ │ │ │ │ │ │ │ │ │ +│ │ ┌─────┐ │ │ ┌─────┐ │ │ ┌─────┐ │ │ ┌─────┐ │ │ ┌─────┐ │ │ +│ │ │ btn │ │ │ │ btn │ │ │ │ btn │ │ │ │ btn │ │ │ │ btn │ │ │ +│ │ └─────┘ │ │ └─────┘ │ │ └─────┘ │ │ └─────┘ │ │ └─────┘ │ │ +│ │ ─────── │ │ ─────── │ │ ─────── │ │ ─────── │ │ ─────── │ │ +│ │ ─────── │ │ ─────── │ │ ─────── │ │ ─────── │ │ ─────── │ │ +│ └────●────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ +│ Selected │ +│ │ +│ "Clean and professional with subtle depth" │ +│ │ +│ [x] I'll customize colors and fonts later │ +│ │ +│ [← Back] [Next: Backend →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Step 3: Backend & Data + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ BACKEND & DATA Step 3/6 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Does your app need to store data? │ +│ │ +│ ○ NO BACKEND │ +│ Frontend only - static content, no user data │ +│ │ +│ ● LOCAL BACKEND (Recommended for starting) │ +│ SQLite database that works offline. │ +│ Zero configuration. Sync to cloud later. │ +│ ✓ Free ✓ No account needed ✓ Works offline │ +│ │ +│ ○ CLOUD BACKEND │ +│ Connect to an existing backend service: │ +│ ┌─────────────────────────────────────────────────────┐ │ +│ │ [Supabase ▼] │ │ +│ │ • Supabase (Postgres + Auth + Realtime) │ │ +│ │ • Pocketbase (Self-hosted, simple) │ │ +│ │ • Firebase (Google ecosystem) │ │ +│ │ • Directus (Headless CMS) │ │ +│ │ • Custom REST API │ │ +│ │ • Custom GraphQL API │ │ +│ └─────────────────────────────────────────────────────┘ │ +│ │ +│ ○ DOCKER │ +│ Spin up Postgres/MySQL in a local container. │ +│ For developers who want full database control. │ +│ │ +│ [← Back] [Next: Authentication →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Step 4: Authentication (Conditional) + +Only shown if backend selected: + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ AUTHENTICATION Step 4/6 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Does your app need user login? │ +│ │ +│ ○ NO AUTHENTICATION │ +│ Public app - anyone can access everything │ +│ │ +│ ● EMAIL + PASSWORD │ +│ Traditional signup/login with email verification │ +│ │ +│ ○ MAGIC LINK │ +│ Passwordless - users click a link sent to email │ +│ │ +│ ○ SOCIAL LOGIN │ +│ Sign in with Google, GitHub, etc. │ +│ ┌─────────────────────────────────────────────────────┐ │ +│ │ [x] Google [x] GitHub [ ] Apple [ ] Microsoft │ │ +│ └─────────────────────────────────────────────────────┘ │ +│ │ +│ ○ I'LL CONFIGURE LATER │ +│ Skip for now, add authentication later │ +│ │ +│ [x] Generate login/signup UI components │ +│ │ +│ [← Back] [Next: GitHub →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Step 5: Version Control + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ VERSION CONTROL Step 5/6 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Connect your project to GitHub for backup and collaboration. │ +│ │ +│ ○ SKIP FOR NOW │ +│ I'll set up Git later │ +│ │ +│ ● CONNECT TO GITHUB │ +│ │ +│ ┌─────────────────────────────────────────────────────┐ │ +│ │ [🔗 Sign in with GitHub] │ │ +│ └─────────────────────────────────────────────────────┘ │ +│ │ +│ ─────────── After signing in ─────────── │ +│ │ +│ Repository: │ +│ ● Create new repository │ +│ Name: [my-awesome-app ] │ +│ Visibility: [Private ▼] │ +│ │ +│ ○ Use existing repository │ +│ ┌─────────────────────────────────────────────────────┐ │ +│ │ my-org/existing-repo │ │ +│ │ my-org/another-project │ │ +│ │ personal/side-project │ │ +│ └─────────────────────────────────────────────────────┘ │ +│ │ +│ ○ Paste repository URL │ +│ [https://github.com/... ] │ +│ │ +│ [← Back] [Next: Deployment →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Step 6: Deployment (Conditional) + +Only shown if GitHub connected: + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ DEPLOYMENT Step 6/6 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Set up automatic deployment when you push to GitHub. │ +│ │ +│ ○ SKIP FOR NOW │ +│ I'll deploy manually or set this up later │ +│ │ +│ ● AUTO-DEPLOY ON PUSH │ +│ │ +│ Platform: │ +│ ● Vercel (Recommended for React) │ +│ [🔗 Connect Vercel Account] │ +│ │ +│ ○ Netlify │ +│ [🔗 Connect Netlify Account] │ +│ │ +│ ○ GitHub Pages (Static sites only) │ +│ No account needed - uses GitHub Actions │ +│ │ +│ ○ Cloudflare Pages │ +│ [🔗 Connect Cloudflare Account] │ +│ │ +│ Options: │ +│ [x] Create preview deployments for pull requests │ +│ [x] Show deployment status in Noodl dashboard │ +│ │ +│ [← Back] [Next: Review →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Step 7: AI Setup (Optional) + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ AI ASSISTANT Optional │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Let AI help you get started faster. │ +│ │ +│ ○ SKIP AI FEATURES │ +│ I'll build everything manually │ +│ │ +│ ● ENABLE AI ASSISTANT │ +│ │ +│ API Key: │ +│ [sk-ant-•••••••••••••••••••••••••••••] [Verify ✓] │ +│ Don't have one? [Get API key from Anthropic →] │ +│ │ +│ What should AI generate? │ +│ │ +│ [x] Starter components based on project description │ +│ AI will create basic UI structure and navigation │ +│ │ +│ [x] Database schema (if backend selected) │ +│ AI will suggest tables and fields based on your │ +│ project description │ +│ │ +│ [ ] Sample data │ +│ Populate database with realistic test data │ +│ │ +│ ┌─────────────────────────────────────────────────────┐ │ +│ │ 💰 Estimated cost: ~$0.05 - $0.15 (one-time) │ │ +│ │ Based on project complexity │ │ +│ │ [?] How is this calculated? │ │ +│ └─────────────────────────────────────────────────────┘ │ +│ │ +│ [← Back] [Next: Review →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Final Step: Review & Create + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ REVIEW & CREATE │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Project: "My Awesome App" │ +│ A task management tool for small teams │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ CONFIGURATION SUMMARY │ │ +│ ├─────────────────────────────────────────────────────────┤ │ +│ │ Style: Modern preset (blue theme) [Edit] │ │ +│ │ Backend: Local SQLite [Edit] │ │ +│ │ Auth: Email + Password [Edit] │ │ +│ │ GitHub: my-org/my-awesome-app (new) [Edit] │ │ +│ │ Deployment: Vercel (auto-deploy) [Edit] │ │ +│ │ AI: Generate components + schema [Edit] │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ COST ESTIMATE │ │ +│ ├─────────────────────────────────────────────────────────┤ │ +│ │ Monthly: │ │ +│ │ • Style system ─────────────────────── Free │ │ +│ │ • Local SQLite ─────────────────────── Free │ │ +│ │ • GitHub (private repo) ────────────── Free │ │ +│ │ • Vercel (hobby tier) ──────────────── Free │ │ +│ │ ───────── │ │ +│ │ Total: $0/month │ │ +│ │ │ │ +│ │ One-time: │ │ +│ │ • AI scaffold generation ───────────── ~$0.08 │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ [ ] Remember these settings for future projects │ +│ │ +│ [← Back] [Create Project →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Creation Progress + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ CREATING "MY AWESOME APP" │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ ✓ Creating project structure │ +│ ✓ Applying Modern style preset │ +│ ✓ Setting up SQLite database │ +│ ✓ Configuring authentication │ +│ ● Generating components with AI... │ +│ ├─ Analyzing project description │ +│ ├─ Creating navigation structure │ +│ └─ Building task management components │ +│ ○ Generating database schema │ +│ ○ Creating GitHub repository │ +│ ○ Configuring Vercel deployment │ +│ ○ Initial commit and push │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ AI is generating: TaskList component │ │ +│ │ ████████████████████░░░░░░░░░░░░░░░░░░░░ 45% │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ [View Details] [Cancel] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## AI Project Builder Mode + +When user selects "AI Project Builder": + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ AI PROJECT BUILDER │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Describe what you want to build: │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ A project management app where teams can create │ │ +│ │ projects, add tasks with due dates and priorities, │ │ +│ │ assign tasks to team members, and track progress │ │ +│ │ with a kanban board view. Users should be able to │ │ +│ │ comment on tasks and get notifications. │ │ +│ │ │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ Examples: │ +│ • "A recipe app where users can save and organize recipes" │ +│ • "An invoice generator for freelancers" │ +│ • "A booking system for a hair salon" │ +│ │ +│ API Key: [sk-ant-•••••••••••••] [Verify ✓] │ +│ │ +│ [Analyze & Suggest →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +After analysis: + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ AI SUGGESTIONS │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Based on your description, here's what I recommend: │ +│ │ +│ PROJECT TYPE: Web Application (Dashboard) │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ STYLE │ │ +│ │ Recommended: Modern │ │ +│ │ A clean, professional look suits project management │ │ +│ │ [Change ▼] │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ BACKEND │ │ +│ │ Recommended: Local SQLite → Supabase │ │ +│ │ Start local, sync to cloud when ready for team use │ │ +│ │ [Change ▼] │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ AUTHENTICATION │ │ +│ │ Recommended: Email + Password │ │ +│ │ Team members need accounts to be assigned tasks │ │ +│ │ [Change ▼] │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ SUGGESTED DATABASE SCHEMA │ │ +│ │ │ │ +│ │ 📁 users (id, email, name, avatar, role) │ │ +│ │ 📁 projects (id, name, description, owner_id) │ │ +│ │ 📁 tasks (id, title, status, priority, assignee_id...) │ │ +│ │ 📁 comments (id, task_id, author_id, content) │ │ +│ │ 📁 notifications (id, user_id, type, read, data) │ │ +│ │ │ │ +│ │ [View Full Schema] [Edit Schema] │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ COMPONENTS TO GENERATE │ │ +│ │ │ │ +│ │ [x] Dashboard layout with sidebar navigation │ │ +│ │ [x] Project list and project detail views │ │ +│ │ [x] Task list with filtering and sorting │ │ +│ │ [x] Kanban board view │ │ +│ │ [x] Task detail with comments │ │ +│ │ [x] User profile and settings │ │ +│ │ [x] Login/Signup pages │ │ +│ │ [ ] Notification center │ │ +│ │ [ ] Team management │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ Estimated AI cost: ~$0.12 │ +│ │ +│ [← Back] [Customize More] [Create Project →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Implementation + +### Phase 1: Wizard Framework (6-8 hrs) + +**Files to create:** + +``` +packages/noodl-editor/src/editor/src/views/ +├── ProjectWizard/ +│ ├── ProjectWizard.tsx # Main wizard container +│ ├── ProjectWizard.module.scss +│ ├── WizardContext.tsx # Shared state +│ ├── WizardNavigation.tsx # Step indicators +│ ├── steps/ +│ │ ├── EntryModeStep.tsx # Quick/Guided/AI selection +│ │ ├── ProjectBasicsStep.tsx # Name, description +│ │ ├── StylePresetStep.tsx # Preset selection +│ │ ├── BackendStep.tsx # Backend configuration +│ │ ├── AuthenticationStep.tsx # Auth options +│ │ ├── GitHubStep.tsx # Version control +│ │ ├── DeploymentStep.tsx # Deployment setup +│ │ ├── AISetupStep.tsx # AI configuration +│ │ ├── ReviewStep.tsx # Summary & create +│ │ └── CreationProgressStep.tsx # Progress display +│ └── index.ts +``` + +**Wizard State:** + +```typescript +interface WizardState { + // Basics + projectName: string; + description: string; + + // Style + stylePreset: string; + + // Backend + backendType: 'none' | 'local' | 'cloud' | 'docker'; + cloudProvider?: 'supabase' | 'pocketbase' | 'firebase' | 'directus' | 'custom'; + cloudConfig?: Record; + + // Auth + authType: 'none' | 'email' | 'magic-link' | 'social' | 'later'; + socialProviders?: string[]; + generateAuthUI: boolean; + + // GitHub + gitHubEnabled: boolean; + gitHubRepo?: { + type: 'new' | 'existing' | 'url'; + name?: string; + visibility?: 'public' | 'private'; + url?: string; + }; + + // Deployment + deploymentEnabled: boolean; + deploymentPlatform?: 'vercel' | 'netlify' | 'github-pages' | 'cloudflare'; + previewDeployments: boolean; + + // AI + aiEnabled: boolean; + aiApiKey?: string; + aiGenerateComponents: boolean; + aiGenerateSchema: boolean; + aiGenerateSampleData: boolean; +} + +interface WizardContextValue { + state: WizardState; + updateState: (partial: Partial) => void; + currentStep: number; + goToStep: (step: number) => void; + nextStep: () => void; + prevStep: () => void; + canProceed: boolean; + createProject: () => Promise; +} +``` + +### Phase 2: Integration Hooks (6-8 hrs) + +**Files to create:** + +``` +packages/noodl-editor/src/editor/src/views/ProjectWizard/ +├── hooks/ +│ ├── useStylePresets.ts # Preset loading and preview +│ ├── useGitHubSetup.ts # GitHub OAuth and repo management +│ ├── useDeploymentSetup.ts # Vercel/Netlify integration +│ ├── useAIScaffold.ts # AI generation orchestration +│ └── useProjectCreation.ts # Final project creation +``` + +**Integration Points:** + +```typescript +// useGitHubSetup.ts +function useGitHubSetup() { + const [isAuthenticated, setAuthenticated] = useState(false); + const [repos, setRepos] = useState([]); + + const authenticate = async () => { + // Uses GIT-004A OAuth flow + const token = await GitHubOAuth.authenticate(); + setAuthenticated(true); + const userRepos = await GitHubClient.listRepos(token); + setRepos(userRepos); + }; + + const createRepo = async (name: string, visibility: 'public' | 'private') => { + // Uses GIT-004A repo creation + return await GitHubClient.createRepo({ name, private: visibility === 'private' }); + }; + + return { isAuthenticated, repos, authenticate, createRepo }; +} +``` + +### Phase 3: AI Builder Mode (4-6 hrs) + +**Files to create:** + +``` +packages/noodl-editor/src/editor/src/views/ProjectWizard/ +├── ai/ +│ ├── AIProjectAnalyzer.ts # Analyze description +│ ├── AISchemaGenerator.ts # Generate database schema +│ ├── AIComponentGenerator.ts # Generate components +│ ├── AIPrompts.ts # Prompt templates +│ └── types.ts +``` + +**AI Analysis Flow:** + +```typescript +interface AIProjectAnalysis { + projectType: 'webapp' | 'ecommerce' | 'content' | 'custom'; + suggestedPreset: string; + suggestedBackend: BackendConfig; + suggestedAuth: AuthConfig; + schema: DatabaseSchema; + components: ComponentSuggestion[]; + estimatedCost: number; +} + +async function analyzeProject(description: string): Promise { + const prompt = buildAnalysisPrompt(description); + const response = await anthropic.complete(prompt); + return parseAnalysisResponse(response); +} +``` + +### Phase 4: Creation Orchestration (4-6 hrs) + +**Files to create:** + +``` +packages/noodl-editor/src/editor/src/views/ProjectWizard/ +├── creation/ +│ ├── ProjectCreator.ts # Main orchestrator +│ ├── steps/ +│ │ ├── CreateProjectStructure.ts +│ │ ├── ApplyStylePreset.ts +│ │ ├── SetupBackend.ts +│ │ ├── SetupAuthentication.ts +│ │ ├── GenerateAIComponents.ts +│ │ ├── GenerateAISchema.ts +│ │ ├── CreateGitHubRepo.ts +│ │ ├── ConfigureDeployment.ts +│ │ └── InitialCommit.ts +│ └── types.ts +``` + +**Creation Pipeline:** + +```typescript +class ProjectCreator { + private steps: CreationStep[] = []; + private progress: CreationProgress; + + constructor(config: WizardState) { + // Build step list based on config + this.steps.push(new CreateProjectStructure(config)); + this.steps.push(new ApplyStylePreset(config.stylePreset)); + + if (config.backendType !== 'none') { + this.steps.push(new SetupBackend(config)); + } + + if (config.authType !== 'none') { + this.steps.push(new SetupAuthentication(config)); + } + + if (config.aiEnabled && config.aiGenerateSchema) { + this.steps.push(new GenerateAISchema(config)); + } + + if (config.aiEnabled && config.aiGenerateComponents) { + this.steps.push(new GenerateAIComponents(config)); + } + + if (config.gitHubEnabled) { + this.steps.push(new CreateGitHubRepo(config.gitHubRepo!)); + + if (config.deploymentEnabled) { + this.steps.push(new ConfigureDeployment(config)); + } + + this.steps.push(new InitialCommit()); + } + } + + async execute(onProgress: (progress: CreationProgress) => void): Promise { + for (const step of this.steps) { + this.progress = { + currentStep: step.name, + completed: this.steps.indexOf(step), + total: this.steps.length + }; + onProgress(this.progress); + + await step.execute(); + } + + return this.project; + } +} +``` + +--- + +## Dependencies + +### Required Before WIZARD-001: + +| Dependency | Task | Status | Notes | +|------------|------|--------|-------| +| Style Presets | STYLE-003 | Required | Preset selector integration | +| GitHub OAuth | GIT-004A | Required | GitHub connection step | +| Deployment | DEPLOY-001 | Optional | Can be added later | +| AI Scaffold | AI-004 | Optional | Can be added later | +| Local Backend | BACKEND-001 | Optional | Can default to "none" | + +### Can Work Incrementally: + +The wizard can ship with partial functionality: + +**V1 (Minimum):** +- Entry mode selection +- Project basics +- Style preset +- Review & create + +**V2 (Add Backend):** +- Backend step +- Authentication step + +**V3 (Add Git):** +- GitHub step +- Deployment step + +**V4 (Add AI):** +- AI builder mode +- AI setup step + +--- + +## Testing Strategy + +### Unit Tests + +- Wizard state management +- Step validation logic +- Creation pipeline ordering +- AI prompt generation + +### Integration Tests + +- Full wizard flow completion +- GitHub OAuth integration +- Deployment configuration +- Project creation with all options + +### Manual Testing Checklist + +- [ ] Quick Start creates project with Modern preset +- [ ] Guided flow navigates all steps correctly +- [ ] Style presets show visual previews +- [ ] Backend options configure correctly +- [ ] GitHub OAuth connects successfully +- [ ] Repository creation works +- [ ] Deployment configuration applies +- [ ] AI analysis generates reasonable suggestions +- [ ] AI schema generation works +- [ ] Progress display updates correctly +- [ ] Created project has all configured features + +--- + +## Success Criteria + +- [ ] Three entry modes work (Quick/Guided/AI) +- [ ] All guided steps functional +- [ ] Style preset applies correctly +- [ ] Backend configuration works +- [ ] GitHub integration functional +- [ ] Deployment setup works +- [ ] AI builder generates reasonable scaffolds +- [ ] Progress display accurate +- [ ] Created projects fully configured +- [ ] User can skip any optional step + +--- + +## Future Enhancements + +### Templates Library + +Pre-built project templates: + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ START FROM TEMPLATE │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ +│ │ Dashboard │ │ E-commerce│ │ Blog │ │ Landing │ │ +│ │ │ │ │ │ │ │ Page │ │ +│ │ 📊 │ │ 🛒 │ │ 📝 │ │ 🚀 │ │ +│ └───────────┘ └───────────┘ └───────────┘ └───────────┘ │ +│ │ +│ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ +│ │ Booking │ │ Social │ │ CRM │ │ Custom │ │ +│ │ System │ │ App │ │ │ │ │ │ +│ │ 📅 │ │ 👥 │ │ 📇 │ │ ⚡ │ │ +│ └───────────┘ └───────────┘ └───────────┘ └───────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Settings Presets + +Remember wizard settings: + +```typescript +interface WizardPreset { + name: string; + settings: Partial; +} + +// "My Standard Setup" +const preset: WizardPreset = { + name: "My Standard Setup", + settings: { + stylePreset: 'modern', + backendType: 'local', + authType: 'email', + gitHubEnabled: true, + deploymentPlatform: 'vercel' + } +}; +``` + +### Team Templates + +Shared templates within organizations: + +- Admin creates standard project setup +- Team members start new projects from org template +- Ensures consistency across team projects + +--- + +*Last Updated: January 2026* diff --git a/dev-docs/tasks/phase-8-styles-overhaul/STYLE-001-token-system-enhancement/README.md b/dev-docs/tasks/phase-8-styles-overhaul/STYLE-001-token-system-enhancement/README.md new file mode 100644 index 0000000..a2f35d2 --- /dev/null +++ b/dev-docs/tasks/phase-8-styles-overhaul/STYLE-001-token-system-enhancement/README.md @@ -0,0 +1,526 @@ +# STYLE-001: Token System Enhancement + +## Overview + +Enhance Noodl's experimental style tokens into a comprehensive design token system inspired by Tailwind CSS. This task establishes the foundation that all other Phase 8 tasks build upon. + +**Phase:** 8 (Styles Overhaul) +**Priority:** CRITICAL (blocks STYLE-002, STYLE-003, STYLE-004) +**Effort:** 12-16 hours +**Risk:** Medium + +--- + +## Background + +### Current State + +Noodl has an experimental "Style Tokens" panel that allows defining CSS custom properties. However: + +- Limited token categories +- No pre-defined scales (spacing, typography, etc.) +- Requires manual setup for every project +- No visual token picker in property panels +- Tokens exist but aren't integrated into element defaults + +### Target State + +A complete design token system with: + +- Pre-defined token categories (colors, spacing, typography, borders, shadows, animations) +- Tailwind-inspired scales with sensible defaults +- Visual token picker integrated throughout the editor +- Semantic tokens that reference base tokens +- Full CSS custom property integration + +--- + +## Token Categories + +### 1. Color Tokens + +#### Semantic Colors (User-Facing) + +```css +/* Primary - Main brand/action color */ +--primary: #3b82f6; +--primary-hover: #2563eb; +--primary-foreground: #ffffff; + +/* Secondary - Supporting actions */ +--secondary: #64748b; +--secondary-hover: #475569; +--secondary-foreground: #ffffff; + +/* Destructive - Dangerous actions, errors */ +--destructive: #ef4444; +--destructive-hover: #dc2626; +--destructive-foreground: #ffffff; + +/* Muted - Subtle backgrounds, disabled states */ +--muted: #f1f5f9; +--muted-foreground: #64748b; + +/* Accent - Highlights, selections */ +--accent: #f1f5f9; +--accent-foreground: #0f172a; + +/* Surface colors */ +--background: #ffffff; +--foreground: #0f172a; +--surface: #f8fafc; +--surface-raised: #ffffff; + +/* Border colors */ +--border: #e2e8f0; +--border-subtle: #f1f5f9; +--border-strong: #cbd5e1; + +/* Focus/Ring */ +--ring: #3b82f6; +--ring-offset: #ffffff; +``` + +#### Palette Colors (Advanced - Optional) + +```css +/* Gray scale */ +--gray-50: #f8fafc; +--gray-100: #f1f5f9; +--gray-200: #e2e8f0; +--gray-300: #cbd5e1; +--gray-400: #94a3b8; +--gray-500: #64748b; +--gray-600: #475569; +--gray-700: #334155; +--gray-800: #1e293b; +--gray-900: #0f172a; +--gray-950: #020617; + +/* Additional palettes: blue, red, green, yellow, purple, pink, etc. */ +/* (Full Tailwind palette as optional advanced tokens) */ +``` + +### 2. Spacing Tokens + +```css +/* Numeric scale (Tailwind-style) */ +--space-0: 0px; +--space-px: 1px; +--space-0.5: 2px; +--space-1: 4px; +--space-1.5: 6px; +--space-2: 8px; +--space-2.5: 10px; +--space-3: 12px; +--space-3.5: 14px; +--space-4: 16px; +--space-5: 20px; +--space-6: 24px; +--space-7: 28px; +--space-8: 32px; +--space-9: 36px; +--space-10: 40px; +--space-11: 44px; +--space-12: 48px; +--space-14: 56px; +--space-16: 64px; +--space-20: 80px; +--space-24: 96px; +--space-28: 112px; +--space-32: 128px; + +/* Semantic aliases */ +--space-xs: var(--space-1); /* 4px */ +--space-sm: var(--space-2); /* 8px */ +--space-md: var(--space-4); /* 16px */ +--space-lg: var(--space-6); /* 24px */ +--space-xl: var(--space-8); /* 32px */ +--space-2xl: var(--space-12); /* 48px */ +--space-3xl: var(--space-16); /* 64px */ +``` + +### 3. Typography Tokens + +```css +/* Font families */ +--font-sans: ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'; +--font-serif: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif; +--font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace; + +/* Font sizes */ +--text-xs: 12px; +--text-sm: 14px; +--text-base: 16px; +--text-lg: 18px; +--text-xl: 20px; +--text-2xl: 24px; +--text-3xl: 30px; +--text-4xl: 36px; +--text-5xl: 48px; +--text-6xl: 60px; + +/* Line heights */ +--leading-none: 1; +--leading-tight: 1.25; +--leading-snug: 1.375; +--leading-normal: 1.5; +--leading-relaxed: 1.625; +--leading-loose: 2; + +/* Font weights */ +--font-thin: 100; +--font-extralight: 200; +--font-light: 300; +--font-normal: 400; +--font-medium: 500; +--font-semibold: 600; +--font-bold: 700; +--font-extrabold: 800; +--font-black: 900; + +/* Letter spacing */ +--tracking-tighter: -0.05em; +--tracking-tight: -0.025em; +--tracking-normal: 0em; +--tracking-wide: 0.025em; +--tracking-wider: 0.05em; +--tracking-widest: 0.1em; +``` + +### 4. Border Tokens + +```css +/* Border radius */ +--radius-none: 0px; +--radius-sm: 4px; +--radius-md: 8px; +--radius-lg: 12px; +--radius-xl: 16px; +--radius-2xl: 24px; +--radius-3xl: 32px; +--radius-full: 9999px; + +/* Border width */ +--border-0: 0px; +--border-1: 1px; +--border-2: 2px; +--border-4: 4px; +--border-8: 8px; +``` + +### 5. Shadow Tokens + +```css +--shadow-none: none; +--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); +--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); +--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); +--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); +--shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25); +--shadow-inner: inset 0 2px 4px 0 rgb(0 0 0 / 0.05); +``` + +### 6. Animation Tokens + +```css +/* Durations */ +--duration-75: 75ms; +--duration-100: 100ms; +--duration-150: 150ms; +--duration-200: 200ms; +--duration-300: 300ms; +--duration-500: 500ms; +--duration-700: 700ms; +--duration-1000: 1000ms; + +/* Timing functions */ +--ease-linear: linear; +--ease-in: cubic-bezier(0.4, 0, 1, 1); +--ease-out: cubic-bezier(0, 0, 0.2, 1); +--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1); +--ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55); +``` + +--- + +## Implementation + +### Phase 1: Token Data Structure (4-6 hrs) + +**Files to create/modify:** + +``` +packages/noodl-editor/src/editor/src/models/ +├── StyleTokens/ +│ ├── StyleTokensModel.ts # Main model class +│ ├── TokenCategories.ts # Token category definitions +│ ├── DefaultTokens.ts # Default token values +│ ├── TokenResolver.ts # CSS variable resolution +│ └── index.ts +``` + +**Tasks:** + +1. Define TypeScript interfaces for token categories +2. Create default token values (as shown above) +3. Build token resolution system (semantic → base → value) +4. Integrate with ProjectModel for persistence +5. Ensure backward compatibility with existing style tokens + +**Token Data Structure:** + +```typescript +interface StyleToken { + name: string; // e.g., "--primary" + value: string; // e.g., "#3b82f6" or "var(--blue-500)" + category: TokenCategory; + isCustom: boolean; // User-defined vs system default + description?: string; +} + +type TokenCategory = 'color-semantic' | 'color-palette' | 'spacing' | 'typography' | 'border' | 'shadow' | 'animation'; + +interface StyleTokensState { + tokens: Map; + customTokens: Map; + presetName: string | null; +} +``` + +### Phase 2: Token Panel Enhancement (4-5 hrs) + +**Files to modify:** + +``` +packages/noodl-editor/src/editor/src/views/panels/StyleTokensPanel/ +├── StyleTokensPanel.tsx # Main panel (enhance existing) +├── TokenCategorySection.tsx # Collapsible category sections +├── TokenEditor.tsx # Individual token editor +├── TokenColorPicker.tsx # Enhanced color picker with palette +├── TokenPreview.tsx # Visual preview of token +└── StyleTokensPanel.module.scss +``` + +**Tasks:** + +1. Reorganize panel into collapsible category sections +2. Add visual previews for each token type +3. Create enhanced color picker showing palette options +4. Add "Reset to Default" per token and per category +5. Add Import/Export functionality + +**Panel UI Structure:** + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ STYLE TOKENS [Import][Export]│ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ ▼ SEMANTIC COLORS [Reset Section] │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ --primary [■ #3b82f6] [🎨] Main brand color │ │ +│ │ --primary-hover [■ #2563eb] [🎨] Hover state │ │ +│ │ --secondary [■ #64748b] [🎨] Secondary actions │ │ +│ │ ... │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ▶ PALETTE COLORS (Advanced) │ +│ │ +│ ▼ SPACING │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ --space-xs [4px ▼] ████ │ │ +│ │ --space-sm [8px ▼] ████████ │ │ +│ │ --space-md [16px ▼] ████████████████ │ │ +│ │ ... │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ▼ TYPOGRAPHY │ +│ ▼ BORDERS │ +│ ▼ SHADOWS │ +│ ▼ ANIMATIONS │ +│ │ +│ ─────────────────────────────────────────────────────────────── │ +│ + Add Custom Token │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Phase 3: Token Picker Component (3-4 hrs) + +**Files to create:** + +``` +packages/noodl-core-ui/src/components/inputs/ +├── TokenPicker/ +│ ├── TokenPicker.tsx # Main component +│ ├── TokenPicker.module.scss +│ ├── TokenPicker.stories.tsx +│ ├── TokenPickerDropdown.tsx # Dropdown with categories +│ ├── TokenPreviewSwatch.tsx # Visual preview swatch +│ └── index.ts +``` + +**Tasks:** + +1. Create reusable TokenPicker component +2. Support all token categories with appropriate previews +3. Include "Custom Value" escape hatch option +4. Show token resolution (what the actual value is) +5. Write Storybook stories for all states + +**TokenPicker Interface:** + +```typescript +interface TokenPickerProps { + category: TokenCategory | TokenCategory[]; // Filter to specific categories + value: string; // Current value (token name or raw) + onChange: (value: string, isToken: boolean) => void; + allowCustom?: boolean; // Show "Custom Value" option + placeholder?: string; + showPreview?: boolean; // Show visual swatch +} +``` + +### Phase 4: CSS Variable Injection (2-3 hrs) + +**Files to modify:** + +``` +packages/noodl-viewer-react/src/ +├── viewer.jsx # Inject tokens into preview +├── styles/ +│ └── tokens.css # Generated token CSS + +packages/noodl-editor/src/editor/src/ +├── preview/ +│ └── PreviewServer.ts # Token injection for preview +``` + +**Tasks:** + +1. Generate CSS from token model +2. Inject token CSS into preview iframe +3. Update tokens in real-time when changed +4. Include tokens in deployed projects +5. Handle dark mode variant tokens (future consideration) + +--- + +## Technical Considerations + +### Backward Compatibility + +Existing projects with custom style tokens must continue to work: + +```typescript +// Migration logic in ProjectModel +function migrateStyleTokens(legacyTokens: any): StyleTokensState { + // Preserve all custom tokens + // Map legacy names to new structure where possible + // Add new default tokens that don't conflict +} +``` + +### Performance + +Token resolution should be efficient: + +```typescript +// Cache resolved values +class TokenResolver { + private cache = new Map(); + + resolve(tokenName: string): string { + if (this.cache.has(tokenName)) { + return this.cache.get(tokenName)!; + } + // Resolution logic... + this.cache.set(tokenName, resolvedValue); + return resolvedValue; + } + + invalidate(tokenName?: string) { + if (tokenName) { + this.cache.delete(tokenName); + } else { + this.cache.clear(); + } + } +} +``` + +### CSS Variable Naming + +Follow conventions that avoid conflicts: + +```css +/* Noodl tokens use --noodl- prefix internally */ +--noodl-primary: #3b82f6; + +/* Exposed to users without prefix for cleaner usage */ +--primary: var(--noodl-primary); +``` + +--- + +## Testing Strategy + +### Unit Tests + +- Token resolution (semantic → base → value chains) +- Token validation (valid CSS values) +- Migration logic (legacy → new format) +- Import/export (JSON round-trip) + +### Integration Tests + +- Token changes reflect in preview +- Tokens persist across project save/load +- Token picker shows correct categories + +### Manual Testing Checklist + +- [ ] Create new project, verify default tokens present +- [ ] Modify token, see preview update in real-time +- [ ] Export tokens, import into another project +- [ ] Open legacy project with custom tokens, verify preserved +- [ ] Use token picker in property panel, apply to element + +--- + +## Success Criteria + +- [ ] All default tokens defined and documented +- [ ] Token panel shows all categories with previews +- [ ] Token picker component works in property panels +- [ ] Tokens inject into preview correctly +- [ ] Tokens include in deployed projects +- [ ] Legacy projects migrate without data loss +- [ ] Import/export functionality works + +--- + +## Dependencies + +**Blocks:** + +- STYLE-002 (Element Configs) - needs tokens to reference +- STYLE-003 (Presets) - needs token system to populate +- STYLE-004 (Property Panel UX) - needs token picker component + +**Blocked By:** + +- None (can start immediately) + +--- + +## References + +- Tailwind CSS Colors: https://tailwindcss.com/docs/customizing-colors +- Tailwind CSS Spacing: https://tailwindcss.com/docs/customizing-spacing +- CSS Custom Properties: https://developer.mozilla.org/en-US/docs/Web/CSS/--* +- shadcn/ui CSS Variables: https://ui.shadcn.com/docs/theming + +--- + +_Last Updated: January 2026_ diff --git a/dev-docs/tasks/phase-8-styles-overhaul/STYLE-002-element-configs/README.md b/dev-docs/tasks/phase-8-styles-overhaul/STYLE-002-element-configs/README.md new file mode 100644 index 0000000..6dfa56a --- /dev/null +++ b/dev-docs/tasks/phase-8-styles-overhaul/STYLE-002-element-configs/README.md @@ -0,0 +1,818 @@ +# STYLE-002: Element Configs & Variants + +## Overview + +Define default configurations and pre-built style variants for Noodl's core visual nodes. When users drag a Button, Group, Text, or Input onto the canvas, it should look good immediately and offer variant options via a simple dropdown. + +**Phase:** 8 (Styles Overhaul) +**Priority:** HIGH (core feature of Phase 8) +**Effort:** 16-20 hours +**Risk:** Medium +**Dependencies:** STYLE-001 (Token System) + +--- + +## Background + +### Current State + +- Visual nodes render with browser defaults (unstyled) +- Users must manually style every element from scratch +- No variant system for quick style switching +- Existing "style variants" feature is underutilized (requires manual setup) + +### Target State + +- Visual nodes have sensible, themed defaults on creation +- Common components (Button, Input) have pre-built variants (Primary, Secondary, etc.) +- Variants reference project tokens (change token → all variants update) +- Users can create custom variants and save them + +--- + +## Core Visual Nodes to Configure + +| Node | Default Variants | Notes | +|------|------------------|-------| +| **Button** | primary, secondary, outline, ghost, destructive, link | Most important | +| **Group** | default, card, section, inset | Container patterns | +| **Text** | body, heading-1 through heading-6, muted, label, code | Typography hierarchy | +| **TextInput** | default, error | Form inputs | +| **TextArea** | default, error | Multi-line input | +| **Checkbox** | default | Form control | +| **Radio Button** | default | Form control | +| **Switch** | default | Toggle control | +| **Image** | default, rounded, circle | Image display | + +--- + +## Element Configurations + +### Button Config + +```typescript +const ButtonConfig: ElementConfig = { + nodeType: 'net.noodl.visual.button', + + // Default styling applied on node creation + defaults: { + // Layout defaults + paddingTop: 'var(--space-2)', + paddingBottom: 'var(--space-2)', + paddingLeft: 'var(--space-4)', + paddingRight: 'var(--space-4)', + + // Typography defaults + fontSize: 'var(--text-sm)', + fontWeight: 'var(--font-medium)', + fontFamily: 'var(--font-sans)', + + // Border defaults + borderRadius: 'var(--radius-md)', + + // Behavior + cursor: 'pointer', + + // Default variant + _variant: 'primary' + }, + + // Size presets + sizes: { + sm: { + paddingTop: 'var(--space-1)', + paddingBottom: 'var(--space-1)', + paddingLeft: 'var(--space-2)', + paddingRight: 'var(--space-2)', + fontSize: 'var(--text-xs)', + }, + md: { + paddingTop: 'var(--space-2)', + paddingBottom: 'var(--space-2)', + paddingLeft: 'var(--space-4)', + paddingRight: 'var(--space-4)', + fontSize: 'var(--text-sm)', + }, + lg: { + paddingTop: 'var(--space-3)', + paddingBottom: 'var(--space-3)', + paddingLeft: 'var(--space-6)', + paddingRight: 'var(--space-6)', + fontSize: 'var(--text-base)', + }, + xl: { + paddingTop: 'var(--space-4)', + paddingBottom: 'var(--space-4)', + paddingLeft: 'var(--space-8)', + paddingRight: 'var(--space-8)', + fontSize: 'var(--text-lg)', + } + }, + + // Style variants + variants: { + primary: { + backgroundColor: 'var(--primary)', + color: 'var(--primary-foreground)', + borderWidth: '0', + boxShadow: 'var(--shadow-sm)', + states: { + hover: { + backgroundColor: 'var(--primary-hover)', + }, + active: { + transform: 'scale(0.98)', + }, + disabled: { + opacity: '0.5', + cursor: 'not-allowed', + } + } + }, + + secondary: { + backgroundColor: 'var(--secondary)', + color: 'var(--secondary-foreground)', + borderWidth: '0', + boxShadow: 'var(--shadow-sm)', + states: { + hover: { + backgroundColor: 'var(--secondary-hover)', + }, + active: { + transform: 'scale(0.98)', + }, + disabled: { + opacity: '0.5', + cursor: 'not-allowed', + } + } + }, + + outline: { + backgroundColor: 'transparent', + color: 'var(--foreground)', + borderWidth: 'var(--border-1)', + borderColor: 'var(--border)', + borderStyle: 'solid', + states: { + hover: { + backgroundColor: 'var(--accent)', + color: 'var(--accent-foreground)', + }, + disabled: { + opacity: '0.5', + cursor: 'not-allowed', + } + } + }, + + ghost: { + backgroundColor: 'transparent', + color: 'var(--foreground)', + borderWidth: '0', + states: { + hover: { + backgroundColor: 'var(--accent)', + color: 'var(--accent-foreground)', + }, + disabled: { + opacity: '0.5', + cursor: 'not-allowed', + } + } + }, + + destructive: { + backgroundColor: 'var(--destructive)', + color: 'var(--destructive-foreground)', + borderWidth: '0', + boxShadow: 'var(--shadow-sm)', + states: { + hover: { + backgroundColor: 'var(--destructive-hover)', + }, + disabled: { + opacity: '0.5', + cursor: 'not-allowed', + } + } + }, + + link: { + backgroundColor: 'transparent', + color: 'var(--primary)', + borderWidth: '0', + textDecoration: 'none', + paddingLeft: '0', + paddingRight: '0', + states: { + hover: { + textDecoration: 'underline', + } + } + } + } +}; +``` + +### Group Config + +```typescript +const GroupConfig: ElementConfig = { + nodeType: 'net.noodl.visual.group', + + defaults: { + // Flexbox defaults + display: 'flex', + flexDirection: 'column', + alignItems: 'stretch', + + // No default variant - groups start transparent + _variant: 'default' + }, + + variants: { + default: { + backgroundColor: 'transparent', + padding: '0', + borderWidth: '0', + borderRadius: '0', + }, + + card: { + backgroundColor: 'var(--surface)', + padding: 'var(--space-4)', + borderWidth: 'var(--border-1)', + borderColor: 'var(--border-subtle)', + borderStyle: 'solid', + borderRadius: 'var(--radius-lg)', + boxShadow: 'var(--shadow-md)', + }, + + section: { + padding: 'var(--space-8)', + }, + + inset: { + backgroundColor: 'var(--muted)', + padding: 'var(--space-4)', + borderRadius: 'var(--radius-md)', + }, + + 'flex-row': { + flexDirection: 'row', + alignItems: 'center', + gap: 'var(--space-2)', + }, + + 'flex-col': { + flexDirection: 'column', + gap: 'var(--space-2)', + }, + + centered: { + alignItems: 'center', + justifyContent: 'center', + } + } +}; +``` + +### Text Config + +```typescript +const TextConfig: ElementConfig = { + nodeType: 'net.noodl.visual.text', + + // ============================================================ + // 🐛 BUG FIX: Text element default sizing + // ============================================================ + // ISSUE: Text elements default to 100% width in a way that + // causes overflow when siblings are added. The element forces + // full width instead of sharing space with siblings. + // + // ROOT CAUSE: Default width is set to '100%' with no flex-shrink, + // causing the element to refuse to shrink when siblings exist. + // + // FIX: Set proper flex defaults so text elements participate + // correctly in flex layout: + // - flexShrink: '1' (allow shrinking) + // - flexGrow: '0' (don't expand beyond content) + // - width: 'auto' (size to content by default) + // - minWidth: '0' (allow shrinking below content size if needed) + // ============================================================ + + defaults: { + // FIXED: Proper flex participation defaults + width: 'auto', // Was: '100%' - caused overflow + height: 'auto', // Content height (correct) + flexShrink: '1', // NEW: Allow shrinking in flex container + flexGrow: '0', // NEW: Don't expand beyond content + minWidth: '0', // NEW: Allow shrinking below content + + // Typography defaults + fontFamily: 'var(--font-sans)', + fontSize: 'var(--text-base)', + fontWeight: 'var(--font-normal)', + lineHeight: 'var(--leading-normal)', + color: 'var(--foreground)', + + // Default variant + _variant: 'body' + }, + + variants: { + body: { + fontSize: 'var(--text-base)', + fontWeight: 'var(--font-normal)', + lineHeight: 'var(--leading-normal)', + color: 'var(--foreground)', + }, + + 'heading-1': { + fontSize: 'var(--text-4xl)', + fontWeight: 'var(--font-bold)', + lineHeight: 'var(--leading-tight)', + color: 'var(--foreground)', + letterSpacing: 'var(--tracking-tight)', + }, + + 'heading-2': { + fontSize: 'var(--text-3xl)', + fontWeight: 'var(--font-semibold)', + lineHeight: 'var(--leading-tight)', + color: 'var(--foreground)', + }, + + 'heading-3': { + fontSize: 'var(--text-2xl)', + fontWeight: 'var(--font-semibold)', + lineHeight: 'var(--leading-snug)', + color: 'var(--foreground)', + }, + + 'heading-4': { + fontSize: 'var(--text-xl)', + fontWeight: 'var(--font-semibold)', + lineHeight: 'var(--leading-snug)', + color: 'var(--foreground)', + }, + + 'heading-5': { + fontSize: 'var(--text-lg)', + fontWeight: 'var(--font-medium)', + lineHeight: 'var(--leading-normal)', + color: 'var(--foreground)', + }, + + 'heading-6': { + fontSize: 'var(--text-base)', + fontWeight: 'var(--font-medium)', + lineHeight: 'var(--leading-normal)', + color: 'var(--foreground)', + }, + + muted: { + fontSize: 'var(--text-sm)', + color: 'var(--muted-foreground)', + }, + + label: { + fontSize: 'var(--text-sm)', + fontWeight: 'var(--font-medium)', + color: 'var(--foreground)', + }, + + small: { + fontSize: 'var(--text-xs)', + color: 'var(--muted-foreground)', + }, + + code: { + fontFamily: 'var(--font-mono)', + fontSize: 'var(--text-sm)', + backgroundColor: 'var(--muted)', + padding: '2px 4px', + borderRadius: 'var(--radius-sm)', + }, + + lead: { + fontSize: 'var(--text-xl)', + color: 'var(--muted-foreground)', + lineHeight: 'var(--leading-relaxed)', + }, + + blockquote: { + fontStyle: 'italic', + borderLeftWidth: '4px', + borderLeftColor: 'var(--border)', + borderLeftStyle: 'solid', + paddingLeft: 'var(--space-4)', + color: 'var(--muted-foreground)', + } + } +}; +``` + +### TextInput Config + +```typescript +const TextInputConfig: ElementConfig = { + nodeType: 'net.noodl.visual.textinput', + + defaults: { + // Sizing + width: '100%', + height: 'auto', + + // Spacing + paddingTop: 'var(--space-2)', + paddingBottom: 'var(--space-2)', + paddingLeft: 'var(--space-3)', + paddingRight: 'var(--space-3)', + + // Typography + fontFamily: 'var(--font-sans)', + fontSize: 'var(--text-base)', + color: 'var(--foreground)', + + // Border + borderWidth: 'var(--border-1)', + borderColor: 'var(--border)', + borderStyle: 'solid', + borderRadius: 'var(--radius-md)', + + // Background + backgroundColor: 'var(--background)', + + // Default variant + _variant: 'default' + }, + + variants: { + default: { + borderColor: 'var(--border)', + backgroundColor: 'var(--background)', + states: { + focus: { + borderColor: 'var(--ring)', + boxShadow: '0 0 0 2px var(--ring)', + outline: 'none', + }, + disabled: { + backgroundColor: 'var(--muted)', + opacity: '0.5', + cursor: 'not-allowed', + }, + placeholder: { + color: 'var(--muted-foreground)', + } + } + }, + + error: { + borderColor: 'var(--destructive)', + states: { + focus: { + borderColor: 'var(--destructive)', + boxShadow: '0 0 0 2px var(--destructive)', + } + } + } + } +}; +``` + +--- + +## Implementation + +### Phase 1: Config System Architecture (4-6 hrs) + +**Files to create:** + +``` +packages/noodl-editor/src/editor/src/models/ +├── ElementConfigs/ +│ ├── ElementConfigModel.ts # Main config model +│ ├── ElementConfigTypes.ts # TypeScript interfaces +│ ├── configs/ +│ │ ├── ButtonConfig.ts +│ │ ├── GroupConfig.ts +│ │ ├── TextConfig.ts +│ │ ├── TextInputConfig.ts +│ │ ├── CheckboxConfig.ts +│ │ └── index.ts # Exports all configs +│ ├── ElementConfigRegistry.ts # Registry for configs +│ └── index.ts +``` + +**TypeScript Interfaces:** + +```typescript +interface ElementConfig { + nodeType: string; + defaults: Record; + sizes?: Record>; + variants: Record; +} + +interface VariantConfig { + [property: string]: string | StateConfig; + states?: StateConfig; +} + +interface StateConfig { + hover?: Record; + active?: Record; + focus?: Record; + disabled?: Record; + placeholder?: Record; +} + +interface ElementConfigRegistry { + configs: Map; + register(config: ElementConfig): void; + get(nodeType: string): ElementConfig | undefined; + getVariants(nodeType: string): string[]; + applyDefaults(node: NodeModel): void; + applyVariant(node: NodeModel, variantName: string): void; +} +``` + +### Phase 2: Node Creation Integration (4-5 hrs) + +**Files to modify:** + +``` +packages/noodl-editor/src/editor/src/models/ +├── NodeModel.ts # Apply defaults on creation +├── NodeGraphModel.ts # Hook into node creation + +packages/noodl-viewer-react/src/ +├── nodes/basic/Text.jsx # Fix defaults (BUG FIX) +├── nodes/controls/Button.jsx # Apply variant styles +└── react-component-node.js # Variant resolution +``` + +**Tasks:** + +1. Hook into node creation lifecycle +2. Apply config defaults when node is created +3. Store variant selection in node data +4. Apply variant styles at render time +5. **BUG FIX**: Fix Text element default sizing + +**Node Creation Flow:** + +```typescript +// In NodeGraphModel.ts or similar +function createNode(nodeType: string, position: Point): NodeModel { + const node = new NodeModel(nodeType, position); + + // Apply element config defaults + const config = ElementConfigRegistry.get(nodeType); + if (config) { + ElementConfigRegistry.applyDefaults(node); + } + + return node; +} +``` + +### Phase 3: Variant Selector UI (4-5 hrs) + +**Files to create/modify:** + +``` +packages/noodl-core-ui/src/components/inputs/ +├── VariantSelector/ +│ ├── VariantSelector.tsx +│ ├── VariantSelector.module.scss +│ ├── VariantSelector.stories.tsx +│ ├── VariantPreview.tsx # Visual preview of variant +│ └── index.ts + +packages/noodl-editor/src/editor/src/views/panels/propertyeditor/ +├── VariantSection.tsx # Variant section in property panel +``` + +**Variant Selector UI:** + +``` +┌───────────────────────────────────────────┐ +│ Variant: [Primary ▼] │ +│ ┌─────────────────────────────┐ │ +│ │ ● Primary [████████████] │ │ +│ │ Secondary [████████████] │ │ +│ │ Outline [░░░░░░░░░░░░] │ │ +│ │ Ghost [············] │ │ +│ │ Destructive[████████████] │ │ +│ │ Link [____________] │ │ +│ │ ─────────────────────────── │ │ +│ │ + Create Variant │ │ +│ └─────────────────────────────┘ │ +└───────────────────────────────────────────┘ +``` + +### Phase 4: State Handling (3-4 hrs) + +**Tasks:** + +1. Implement hover state application +2. Implement active/pressed state +3. Implement focus state +4. Implement disabled state +5. Implement placeholder styling (inputs) + +**State Implementation:** + +```typescript +// In react-component-node.js or component wrapper +function applyVariantStates( + baseStyles: CSSProperties, + variant: VariantConfig, + states: { isHovered: boolean; isActive: boolean; isFocused: boolean; isDisabled: boolean } +): CSSProperties { + let styles = { ...baseStyles }; + + if (states.isDisabled && variant.states?.disabled) { + styles = { ...styles, ...variant.states.disabled }; + } else { + if (states.isHovered && variant.states?.hover) { + styles = { ...styles, ...variant.states.hover }; + } + if (states.isActive && variant.states?.active) { + styles = { ...styles, ...variant.states.active }; + } + if (states.isFocused && variant.states?.focus) { + styles = { ...styles, ...variant.states.focus }; + } + } + + return styles; +} +``` + +--- + +## Text Element Bug Fix Details + +### Current Behavior (Bug) + +``` +Parent Group (row layout) +├── Text "Hello" → Takes 100% width, pushes sibling off-screen +└── Text "World" → Overflows to the right (not visible) +``` + +### Expected Behavior (After Fix) + +``` +Parent Group (row layout) +├── Text "Hello" → Takes ~50% width (flex shrinks) +└── Text "World" → Takes ~50% width (both visible) +``` + +### Root Cause Analysis + +The Text node's default styling sets `width: 100%` without proper flex shrink behavior: + +```javascript +// Current (problematic) defaults in Text.jsx +const defaultStyle = { + width: '100%', // Forces full width + height: 'auto', + // Missing: flexShrink, flexGrow, minWidth +}; +``` + +### Fix Implementation + +```javascript +// Fixed defaults in Text.jsx +const defaultStyle = { + width: 'auto', // Changed from '100%' + height: 'auto', + flexShrink: 1, // Allow shrinking + flexGrow: 0, // Don't expand beyond content + minWidth: 0, // Allow shrinking below intrinsic size +}; +``` + +### Files to Modify + +``` +packages/noodl-viewer-react/src/nodes/basic/Text.jsx + - Update defaultStyle object + - Add flexShrink, flexGrow, minWidth defaults + +packages/noodl-runtime/src/nodes/basic/text.js (if exists) + - Mirror changes for runtime consistency +``` + +### Testing the Fix + +1. Create a Group with row layout +2. Add two Text elements as children +3. **Before fix**: Second text overflows +4. **After fix**: Both texts share space equally + +--- + +## Custom Variant Creation + +Users should be able to create their own variants: + +### "Save as Variant" Flow + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ CREATE NEW VARIANT │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ This button has custom styling. Save it as a reusable variant? │ +│ │ +│ Variant Name: [success-button ] │ +│ │ +│ Apply to: │ +│ ○ This project only │ +│ ● All projects (global) │ +│ │ +│ Preview: │ +│ ┌─────────────────────────────────────┐ │ +│ │ [ Success ] │ │ +│ └─────────────────────────────────────┘ │ +│ │ +│ [Cancel] [Save Variant] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Storage + +```typescript +interface CustomVariant extends VariantConfig { + name: string; + nodeType: string; + scope: 'project' | 'global'; + createdAt: Date; +} + +// Project-scoped variants stored in project file +// Global variants stored in user preferences +``` + +--- + +## Testing Strategy + +### Unit Tests + +- Config registry operations +- Variant style resolution +- State style merging +- Token reference resolution in variants + +### Integration Tests + +- Node creation applies defaults +- Variant change updates styles +- State changes reflect visually +- Custom variants persist + +### Manual Testing Checklist + +- [ ] Create Button, verify styled by default +- [ ] Change Button variant, see instant update +- [ ] Create Group with "card" variant +- [ ] Create Text with "heading-1" variant +- [ ] **Test Text bug fix**: Two Text elements in row layout share space +- [ ] Create custom variant and reuse it +- [ ] Hover/active/disabled states work correctly + +--- + +## Success Criteria + +- [ ] All listed nodes have default configs +- [ ] Variant dropdown appears in property panel +- [ ] Variants reference tokens correctly +- [ ] State styles apply on interaction +- [ ] Custom variant creation works +- [ ] **Text element bug is fixed** +- [ ] No regression in existing projects + +--- + +## Dependencies + +**Blocked By:** +- STYLE-001 (Token System) - variants reference tokens + +**Blocks:** +- STYLE-004 (Property Panel UX) - uses variant selector + +--- + +*Last Updated: January 2026* diff --git a/dev-docs/tasks/phase-8-styles-overhaul/STYLE-003-presets/README.md b/dev-docs/tasks/phase-8-styles-overhaul/STYLE-003-presets/README.md new file mode 100644 index 0000000..373f961 --- /dev/null +++ b/dev-docs/tasks/phase-8-styles-overhaul/STYLE-003-presets/README.md @@ -0,0 +1,639 @@ +# STYLE-003: Style Presets System + +## Overview + +Create a library of style presets (Modern, Minimal, Playful, Enterprise) that users can choose when creating a new project. Each preset defines token values that cascade through the entire style system. + +**Phase:** 8 (Styles Overhaul) +**Priority:** HIGH +**Effort:** 8-12 hours +**Risk:** Low +**Dependencies:** STYLE-001 (Token System), STYLE-002 (Element Configs) + +--- + +## Background + +### The Goal + +When a user creates a new project, they should be able to: + +1. Choose a visual style preset from a gallery +2. See live previews of what their UI will look like +3. Start building immediately with consistent, professional styling +4. Customize the preset later if desired + +### Why Presets Matter + +- **Beginners**: Don't know what colors/spacing to choose +- **Speed**: Skip the "design token setup" phase +- **Consistency**: Entire project has cohesive look from start +- **Exploration**: Easy to try different aesthetics + +--- + +## Preset Definitions + +### Modern (Default) + +A clean, professional look with subtle shadows and medium rounding. Works for most applications. + +```typescript +const ModernPreset: StylePreset = { + name: 'Modern', + description: 'Clean and professional with subtle depth', + + tokens: { + // Colors + '--primary': '#3b82f6', // Blue + '--primary-hover': '#2563eb', + '--primary-foreground': '#ffffff', + '--secondary': '#64748b', + '--secondary-hover': '#475569', + '--secondary-foreground': '#ffffff', + '--destructive': '#ef4444', + '--destructive-hover': '#dc2626', + '--destructive-foreground': '#ffffff', + '--muted': '#f1f5f9', + '--muted-foreground': '#64748b', + '--accent': '#f1f5f9', + '--accent-foreground': '#0f172a', + '--background': '#ffffff', + '--foreground': '#0f172a', + '--surface': '#f8fafc', + '--border': '#e2e8f0', + '--border-subtle': '#f1f5f9', + '--ring': '#3b82f6', + + // Typography + '--font-sans': 'Inter, ui-sans-serif, system-ui, sans-serif', + + // Borders + '--radius-sm': '4px', + '--radius-md': '8px', + '--radius-lg': '12px', + + // Shadows + '--shadow-sm': '0 1px 2px 0 rgb(0 0 0 / 0.05)', + '--shadow-md': '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)', + }, + + preview: { + primaryButton: '#3b82f6', + cardBackground: '#ffffff', + cardBorder: '#e2e8f0', + textColor: '#0f172a', + radius: '8px', + } +}; +``` + +### Minimal + +Ultra-clean with sharp corners, no shadows, and monochromatic palette. + +```typescript +const MinimalPreset: StylePreset = { + name: 'Minimal', + description: 'Ultra-clean with sharp edges and no shadows', + + tokens: { + // Colors - Monochromatic + '--primary': '#18181b', // Near black + '--primary-hover': '#27272a', + '--primary-foreground': '#ffffff', + '--secondary': '#71717a', + '--secondary-hover': '#52525b', + '--secondary-foreground': '#ffffff', + '--destructive': '#dc2626', + '--destructive-hover': '#b91c1c', + '--destructive-foreground': '#ffffff', + '--muted': '#f4f4f5', + '--muted-foreground': '#71717a', + '--accent': '#f4f4f5', + '--accent-foreground': '#18181b', + '--background': '#ffffff', + '--foreground': '#18181b', + '--surface': '#fafafa', + '--border': '#e4e4e7', + '--border-subtle': '#f4f4f5', + '--ring': '#18181b', + + // Typography + '--font-sans': 'system-ui, -apple-system, sans-serif', + + // Borders - Sharp + '--radius-sm': '2px', + '--radius-md': '4px', + '--radius-lg': '6px', + + // Shadows - None + '--shadow-sm': 'none', + '--shadow-md': 'none', + '--shadow-lg': 'none', + }, + + preview: { + primaryButton: '#18181b', + cardBackground: '#ffffff', + cardBorder: '#e4e4e7', + textColor: '#18181b', + radius: '4px', + } +}; +``` + +### Playful + +Vibrant colors, generous rounding, and friendly typography. + +```typescript +const PlayfulPreset: StylePreset = { + name: 'Playful', + description: 'Vibrant colors and rounded, friendly shapes', + + tokens: { + // Colors - Vibrant + '--primary': '#8b5cf6', // Purple + '--primary-hover': '#7c3aed', + '--primary-foreground': '#ffffff', + '--secondary': '#ec4899', // Pink + '--secondary-hover': '#db2777', + '--secondary-foreground': '#ffffff', + '--destructive': '#f43f5e', // Rose + '--destructive-hover': '#e11d48', + '--destructive-foreground': '#ffffff', + '--muted': '#faf5ff', + '--muted-foreground': '#6b7280', + '--accent': '#fce7f3', + '--accent-foreground': '#831843', + '--background': '#ffffff', + '--foreground': '#1e1b4b', + '--surface': '#faf5ff', + '--border': '#e9d5ff', + '--border-subtle': '#faf5ff', + '--ring': '#8b5cf6', + + // Typography - Friendly + '--font-sans': '"Nunito", "Quicksand", ui-sans-serif, sans-serif', + + // Borders - Very Rounded + '--radius-sm': '8px', + '--radius-md': '16px', + '--radius-lg': '24px', + '--radius-full': '9999px', + + // Shadows - Soft colored + '--shadow-sm': '0 1px 3px rgb(139 92 246 / 0.1)', + '--shadow-md': '0 4px 12px rgb(139 92 246 / 0.15)', + }, + + preview: { + primaryButton: '#8b5cf6', + cardBackground: '#faf5ff', + cardBorder: '#e9d5ff', + textColor: '#1e1b4b', + radius: '16px', + } +}; +``` + +### Enterprise + +Conservative, trustworthy palette with traditional styling. + +```typescript +const EnterprisePreset: StylePreset = { + name: 'Enterprise', + description: 'Professional and trustworthy for business applications', + + tokens: { + // Colors - Conservative + '--primary': '#0f172a', // Dark navy + '--primary-hover': '#1e293b', + '--primary-foreground': '#ffffff', + '--secondary': '#475569', + '--secondary-hover': '#334155', + '--secondary-foreground': '#ffffff', + '--destructive': '#b91c1c', + '--destructive-hover': '#991b1b', + '--destructive-foreground': '#ffffff', + '--muted': '#f1f5f9', + '--muted-foreground': '#475569', + '--accent': '#e2e8f0', + '--accent-foreground': '#0f172a', + '--background': '#ffffff', + '--foreground': '#0f172a', + '--surface': '#f8fafc', + '--border': '#cbd5e1', + '--border-subtle': '#e2e8f0', + '--ring': '#0f172a', + + // Typography - Traditional + '--font-sans': '"Source Sans Pro", "Segoe UI", ui-sans-serif, sans-serif', + + // Borders - Conservative + '--radius-sm': '2px', + '--radius-md': '4px', + '--radius-lg': '6px', + + // Shadows - Subtle + '--shadow-sm': '0 1px 2px rgb(0 0 0 / 0.05)', + '--shadow-md': '0 2px 4px rgb(0 0 0 / 0.06), 0 1px 2px rgb(0 0 0 / 0.04)', + }, + + preview: { + primaryButton: '#0f172a', + cardBackground: '#ffffff', + cardBorder: '#cbd5e1', + textColor: '#0f172a', + radius: '4px', + } +}; +``` + +### Soft + +Gentle, calming aesthetic with soft colors and generous whitespace. + +```typescript +const SoftPreset: StylePreset = { + name: 'Soft', + description: 'Gentle colors and soft shapes for a calming aesthetic', + + tokens: { + // Colors - Soft/Muted + '--primary': '#6366f1', // Indigo + '--primary-hover': '#4f46e5', + '--primary-foreground': '#ffffff', + '--secondary': '#a78bfa', // Light purple + '--secondary-hover': '#8b5cf6', + '--secondary-foreground': '#ffffff', + '--destructive': '#fb7185', // Soft red + '--destructive-hover': '#f43f5e', + '--destructive-foreground': '#ffffff', + '--muted': '#f5f3ff', + '--muted-foreground': '#6b7280', + '--accent': '#ede9fe', + '--accent-foreground': '#4c1d95', + '--background': '#fefefe', + '--foreground': '#374151', + '--surface': '#f9fafb', + '--border': '#e5e7eb', + '--border-subtle': '#f3f4f6', + '--ring': '#6366f1', + + // Typography + '--font-sans': '"DM Sans", ui-sans-serif, system-ui, sans-serif', + + // Borders - Soft rounded + '--radius-sm': '6px', + '--radius-md': '12px', + '--radius-lg': '20px', + + // Shadows - Very soft + '--shadow-sm': '0 1px 3px rgb(0 0 0 / 0.02)', + '--shadow-md': '0 4px 6px rgb(0 0 0 / 0.04)', + }, + + preview: { + primaryButton: '#6366f1', + cardBackground: '#fefefe', + cardBorder: '#e5e7eb', + textColor: '#374151', + radius: '12px', + } +}; +``` + +--- + +## Implementation + +### Phase 1: Preset Data Structure (2-3 hrs) + +**Files to create:** + +``` +packages/noodl-editor/src/editor/src/models/ +├── StylePresets/ +│ ├── StylePresetsModel.ts # Preset management +│ ├── presets/ +│ │ ├── ModernPreset.ts +│ │ ├── MinimalPreset.ts +│ │ ├── PlayfulPreset.ts +│ │ ├── EnterprisePreset.ts +│ │ ├── SoftPreset.ts +│ │ └── index.ts +│ ├── StylePresetTypes.ts # TypeScript interfaces +│ └── index.ts +``` + +**TypeScript Interfaces:** + +```typescript +interface StylePreset { + id: string; + name: string; + description: string; + tokens: Record; + preview: PresetPreview; + isBuiltIn: boolean; + createdAt?: Date; +} + +interface PresetPreview { + primaryButton: string; + cardBackground: string; + cardBorder: string; + textColor: string; + radius: string; +} + +interface StylePresetsModel { + builtInPresets: StylePreset[]; + customPresets: StylePreset[]; + + getPreset(id: string): StylePreset | undefined; + applyPreset(presetId: string): void; + saveCustomPreset(preset: Omit): StylePreset; + deleteCustomPreset(id: string): void; + exportPreset(id: string): string; // JSON + importPreset(json: string): StylePreset; +} +``` + +### Phase 2: Preset Selector Component (3-4 hrs) + +**Files to create:** + +``` +packages/noodl-core-ui/src/components/ +├── StylePresets/ +│ ├── PresetSelector.tsx # Main selector component +│ ├── PresetSelector.module.scss +│ ├── PresetSelector.stories.tsx +│ ├── PresetCard.tsx # Individual preset card +│ ├── PresetPreview.tsx # Live preview mini-UI +│ └── index.ts +``` + +**PresetSelector UI:** + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ STYLE PRESET │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Choose a visual style for your project: │ +│ │ +│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ +│ │ Modern │ │ Minimal │ │ Playful │ │ Corp │ │ Soft │ │ +│ │ │ │ │ │ │ │ │ │ │ │ +│ │ ┌─────┐ │ │ ┌─────┐ │ │ ┌─────┐ │ │ ┌─────┐ │ │ ┌─────┐ │ │ +│ │ │ btn │ │ │ │ btn │ │ │ │ btn │ │ │ │ btn │ │ │ │ btn │ │ │ +│ │ └─────┘ │ │ └─────┘ │ │ └─────┘ │ │ └─────┘ │ │ └─────┘ │ │ +│ │ ─────── │ │ ─────── │ │ ─────── │ │ ─────── │ │ ─────── │ │ +│ │ ─────── │ │ ─────── │ │ ─────── │ │ ─────── │ │ ─────── │ │ +│ │ ███████ │ │ ███████ │ │ ███████ │ │ ███████ │ │ ███████ │ │ +│ └────●────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ +│ Selected │ +│ │ +│ "Clean and professional with subtle depth" │ +│ │ +│ [Customize After Creation] │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +**PresetCard Component:** + +```typescript +interface PresetCardProps { + preset: StylePreset; + isSelected: boolean; + onSelect: (presetId: string) => void; +} + +function PresetCard({ preset, isSelected, onSelect }: PresetCardProps) { + return ( +
onSelect(preset.id)} + > + + {preset.name} +
+ ); +} +``` + +### Phase 3: Project Creation Integration (2-3 hrs) + +**Files to modify:** + +``` +packages/noodl-editor/src/editor/src/views/ +├── NewProjectDialog/ +│ ├── NewProjectDialog.tsx # Add preset selector +│ └── NewProjectDialog.module.scss + +packages/noodl-editor/src/editor/src/models/ +├── ProjectModel.ts # Apply preset on creation +``` + +**Integration Points:** + +```typescript +// In NewProjectDialog.tsx +function NewProjectDialog() { + const [selectedPreset, setSelectedPreset] = useState('modern'); + + const handleCreate = async () => { + const project = await ProjectModel.create({ + name: projectName, + // ... other options + }); + + // Apply selected preset's tokens + const preset = StylePresetsModel.getPreset(selectedPreset); + if (preset) { + StyleTokensModel.applyPreset(preset.tokens); + } + + // Open project + EditorModel.openProject(project); + }; + + return ( + + {/* ... name input ... */} + + {/* ... other options ... */} + + + ); +} +``` + +### Phase 4: Preset Management UI (2-3 hrs) + +**Files to create:** + +``` +packages/noodl-editor/src/editor/src/views/panels/ +├── PresetManagerPanel/ +│ ├── PresetManagerPanel.tsx # Full preset management +│ ├── PresetManagerPanel.module.scss +│ ├── CreatePresetDialog.tsx +│ └── index.ts +``` + +**Features:** + +1. View all presets (built-in + custom) +2. Create preset from current tokens +3. Edit custom presets +4. Delete custom presets +5. Import/Export presets + +--- + +## Custom Preset Creation + +### From Project Settings + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ SAVE AS PRESET │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Save your current token configuration as a reusable preset. │ +│ │ +│ Preset Name: [My Brand Style ] │ +│ Description: [Corporate brand colors] │ +│ │ +│ Preview: │ +│ ┌───────────────────────────────────────────────────────────┐ │ +│ │ ┌──────┐ │ │ +│ │ │ btn │ Heading Text │ │ +│ │ └──────┘ Body text preview with current styling │ │ +│ │ ┌──────────────────────────────────────────────────┐ │ │ +│ │ │ Card preview with surface color │ │ │ +│ │ └──────────────────────────────────────────────────┘ │ │ +│ └───────────────────────────────────────────────────────────┘ │ +│ │ +│ [Cancel] [Save Preset] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Import/Export + +```typescript +// Export format (JSON) +{ + "name": "My Brand Style", + "description": "Corporate brand colors", + "version": "1.0", + "tokens": { + "--primary": "#1a73e8", + "--primary-hover": "#1557b0", + // ... all token values + } +} +``` + +--- + +## Testing Strategy + +### Unit Tests + +- Preset loading and parsing +- Token application +- Custom preset CRUD operations +- Import/export JSON serialization + +### Integration Tests + +- Preset selection in new project dialog +- Tokens apply correctly to elements +- Custom presets persist across sessions + +### Manual Testing Checklist + +- [ ] Create project with each built-in preset +- [ ] Verify elements styled correctly per preset +- [ ] Create custom preset from current tokens +- [ ] Import preset from JSON +- [ ] Export preset to JSON +- [ ] Delete custom preset +- [ ] Preset preview matches actual result + +--- + +## Success Criteria + +- [ ] 5 built-in presets available +- [ ] Preset selector in project creation dialog +- [ ] Live preview in preset cards +- [ ] Custom preset creation works +- [ ] Import/export functionality +- [ ] Presets correctly populate all tokens + +--- + +## Future Considerations + +### Dark Mode Variants + +Each preset could have light/dark variants: + +```typescript +interface StylePreset { + // ... + modes: { + light: Record; + dark: Record; + }; +} +``` + +### Community Presets + +Allow sharing presets via: +- Export as JSON file +- Copy/paste shareable code +- (Future) Community preset gallery + +### Preset Inheritance + +Allow presets to extend other presets: + +```typescript +const MyPreset = { + extends: 'modern', + tokens: { + '--primary': '#custom-color', // Override just this + // Other tokens inherited from 'modern' + } +}; +``` + +--- + +## Dependencies + +**Blocked By:** +- STYLE-001 (Token System) - presets populate tokens +- STYLE-002 (Element Configs) - tokens flow to variants + +**Blocks:** +- WIZARD-001 (Project Wizard) - uses preset selector + +--- + +*Last Updated: January 2026* diff --git a/dev-docs/tasks/phase-8-styles-overhaul/STYLE-004-property-panel/README.md b/dev-docs/tasks/phase-8-styles-overhaul/STYLE-004-property-panel/README.md new file mode 100644 index 0000000..278d158 --- /dev/null +++ b/dev-docs/tasks/phase-8-styles-overhaul/STYLE-004-property-panel/README.md @@ -0,0 +1,555 @@ +# STYLE-004: Property Panel UX Overhaul + +## Overview + +Redesign the property panel to surface the three-level styling system: Variant Picker (easy), Token Overrides (intermediate), and Manual Values (advanced). The goal is progressive disclosure - make the happy path obvious while preserving full control. + +**Phase:** 8 (Styles Overhaul) +**Priority:** HIGH +**Effort:** 12-16 hours +**Risk:** Medium (significant UI changes) +**Dependencies:** STYLE-001, STYLE-002 + +--- + +## Background + +### Current State + +- Property panel shows all CSS properties in a flat list +- No progressive disclosure (beginners see same UI as experts) +- Style variants exist but aren't prominently featured +- Token system exists but requires manual typing + +### Target State + +- Variant picker is front-and-center for styled elements +- Token overrides available in collapsible section +- Manual controls preserved but de-emphasized +- Visual indicators show when elements use system styles vs custom + +--- + +## The Three Levels + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ │ +│ LEVEL 1: VARIANT PICKER [Default View] │ +│ "Just pick Primary, Secondary, Ghost..." │ +│ • Single dropdown │ +│ • Visual previews │ +│ • 80% of users, 80% of the time │ +│ │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ LEVEL 2: TOKEN OVERRIDES [Expanded] │ +│ "Use Primary but change the radius to Large" │ +│ • Override specific properties with tokens │ +│ • Stay systematic, theme-aware │ +│ • Designers building design systems │ +│ │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ LEVEL 3: MANUAL VALUES [Advanced] │ +│ "I need exactly 17px padding and this hex color" │ +│ • Full CSS control │ +│ • Chrome DevTools-style interface │ +│ • "You're on your own" │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Property Panel Redesign + +### Default View (Button Example) + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ BUTTON │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ CONTENT │ +│ ├─ Label: [Sign Up ] │ +│ └─ Icon: [None ▼] Position: [Left ▼] │ +│ │ +│ STYLE │ +│ ├─ Variant: [Primary ▼] │ +│ │ ┌────────────────────────────────┐ │ +│ │ │ ● Primary ████████████ │ │ +│ │ │ Secondary ████████████ │ │ +│ │ │ Outline ░░░░░░░░░░░░ │ │ +│ │ │ Ghost ············ │ │ +│ │ │ Destructive ████████████ │ │ +│ │ │ Link ____________ │ │ +│ │ │ ──────────────────────────────│ │ +│ │ │ + Create Variant │ │ +│ │ └────────────────────────────────┘ │ +│ │ │ +│ └─ Size: [Medium ▼] (sm / md / lg / xl) │ +│ │ +│ BEHAVIOR │ +│ ├─ Disabled: [ ] │ +│ └─ Loading: [ ] │ +│ │ +│ ▶ Style Overrides │ +│ ▶ Layout │ +│ ▶ Advanced │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Expanded: Style Overrides (Level 2) + +``` +│ ▼ Style Overrides │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ Override properties while staying on-system │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ Background │ +│ [From Variant ▼] ───────────────────────────────────────── │ +│ │ ┌────────────────────────────────┐ │ +│ │ │ ● From Variant (--primary) │ │ +│ │ │ ───────────────────────────── │ │ +│ │ │ --primary │ │ +│ │ │ --primary-hover │ │ +│ │ │ --secondary │ │ +│ │ │ --destructive │ │ +│ │ │ --muted │ │ +│ │ │ --surface │ │ +│ │ │ --background │ │ +│ │ │ ───────────────────────────── │ │ +│ │ │ Custom Value... │ ← Escape hatch │ +│ │ └────────────────────────────────┘ │ +│ │ +│ Text Color │ +│ [From Variant ▼] │ +│ │ +│ Border Color │ +│ [--border ▼] ← Overriding variant │ +│ ⚠️ Overriding variant default │ +│ │ +│ Border Radius │ +│ [--radius-lg ▼] ← Overriding variant │ +│ ⚠️ Overriding variant default │ +│ │ +│ Padding │ +│ [From Variant ▼] │ +│ │ +│ Shadow │ +│ [From Variant ▼] │ +│ │ +│ [Reset All Overrides] │ +│ │ +``` + +When user selects "Custom Value...": + +``` +│ Background │ +│ [Custom ▼] [#a3f7c2 ] [🎨] │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ ⚠️ Custom value won't update when theme changes │ │ +│ │ [Save as Token] [Keep Custom] │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +``` + +### Expanded: Layout (Partially Level 3) + +``` +│ ▼ Layout │ +│ │ +│ WIDTH │ +│ [Auto ▼] [ ] │ +│ │ ● Auto (fit content) │ +│ │ Full (100%) │ +│ │ Fixed │ +│ │ Token → [Select Token ▼] │ +│ │ +│ HEIGHT │ +│ [Auto ▼] [ ] │ +│ │ +│ ALIGNMENT │ +│ ┌─────────────────────────────────────┐ │ +│ │ [⬉] [⬆] [⬈] Align Self │ │ +│ │ [⬅] [·] [➡] │ │ +│ │ [⬋] [⬇] [⬊] │ │ +│ └─────────────────────────────────────┘ │ +│ │ +│ SPACING │ +│ Margin: [Token ▼] [--space-md ▼] │ +│ Padding: [Variant ▼] │ +│ │ +``` + +### Expanded: Advanced (Level 3) + +``` +│ ▼ Advanced │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ ⚠️ Manual values bypass the style system │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ POSITION │ +│ Position: [Relative ▼] │ +│ ┌─────────────────────────────────────┐ │ +│ │ Top: [ ] │ │ +│ │ Left: [ ] Right: [ ] │ │ +│ │ Bottom: [ ] │ │ +│ └─────────────────────────────────────┘ │ +│ │ +│ BOX MODEL │ +│ ┌─────────────────────────────────────┐ │ +│ │ Margin │ │ +│ │ ┌─────────────────────────────┐ │ │ +│ │ │ Border │ │ │ +│ │ │ ┌─────────────────────┐ │ │ │ +│ │ │ │ Padding │ │ │ │ +│ │ │ │ ┌─────────────┐ │ │ │ │ +│ │ │ │ │ Content │ │ │ │ │ +│ │ │ │ └─────────────┘ │ │ │ │ +│ │ │ └─────────────────────┘ │ │ │ +│ │ └─────────────────────────────┘ │ │ +│ └─────────────────────────────────────┘ │ +│ [Edit Individual Values] │ +│ │ +│ EFFECTS │ +│ Opacity: [1.0 ] ────────○ │ +│ Cursor: [Pointer ▼] │ +│ Overflow: [Visible ▼] │ +│ Z-Index: [ ] │ +│ │ +│ TRANSFORM │ +│ Rotate: [0° ] │ +│ Scale: [1 ] │ +│ Translate X: [0 ] │ +│ Translate Y: [0 ] │ +│ │ +│ TRANSITIONS │ +│ Property: [all ▼] │ +│ Duration: [--duration-200 ▼] │ +│ Easing: [--ease-out ▼] │ +│ │ +│ CUSTOM CSS │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ /* Any valid CSS */ │ │ +│ │ backdrop-filter: blur(8px); │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +``` + +--- + +## Visual Indicators + +### On-System vs Custom Indicators + +Show users when elements are "on system" vs have custom values: + +**In the Property Panel Header:** + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ BUTTON [Using System ✓] │ +├─────────────────────────────────────────────────────────────────┤ + +vs. + +┌─────────────────────────────────────────────────────────────────┐ +│ BUTTON [⚡ 2 Custom Values] │ +├─────────────────────────────────────────────────────────────────┤ +``` + +**In the Style Section:** + +``` +│ STYLE │ +│ ├─ Variant: [Primary ▼] (2 overrides) │ + ^^^^^^^^^^^^^ subtle indicator +``` + +**On Individual Properties:** + +``` +│ Border Radius │ +│ [--radius-lg ▼] ← Override indicator │ +│ ⚠️ Overriding variant │ +``` + +### In the Canvas (Optional) + +Small indicator on selected element showing style status: + +``` +┌────────────────────────┐ +│ │ +│ [ Sign Up ] │ ← Normal (using system) +│ │ +└────────────────────────┘ + +┌────────────────────────┐ +│ ⚡ │ ← Has custom values +│ [ Sign Up ] │ +│ │ +└────────────────────────┘ +``` + +--- + +## Implementation + +### Phase 1: Panel Structure Refactor (4-5 hrs) + +**Files to modify:** + +``` +packages/noodl-editor/src/editor/src/views/panels/propertyeditor/ +├── PropertyEditor.tsx # Main panel refactor +├── sections/ +│ ├── ContentSection.tsx # Node-specific content +│ ├── StyleSection.tsx # Variant picker + size +│ ├── StyleOverridesSection.tsx # Level 2 overrides +│ ├── LayoutSection.tsx # Layout controls +│ ├── AdvancedSection.tsx # Level 3 manual controls +│ └── BehaviorSection.tsx # Disabled, loading, etc. +├── PropertyEditor.module.scss +└── index.ts +``` + +**Section Architecture:** + +```typescript +interface PropertyPanelSection { + id: string; + title: string; + icon?: IconName; + defaultExpanded: boolean; + render: (node: NodeModel) => React.ReactNode; + isApplicable: (nodeType: string) => boolean; +} + +const sections: PropertyPanelSection[] = [ + { id: 'content', title: 'Content', defaultExpanded: true, ... }, + { id: 'style', title: 'Style', defaultExpanded: true, ... }, + { id: 'behavior', title: 'Behavior', defaultExpanded: true, ... }, + { id: 'style-overrides', title: 'Style Overrides', defaultExpanded: false, ... }, + { id: 'layout', title: 'Layout', defaultExpanded: false, ... }, + { id: 'advanced', title: 'Advanced', defaultExpanded: false, ... }, +]; +``` + +### Phase 2: Style Section Components (3-4 hrs) + +**Files to create:** + +``` +packages/noodl-core-ui/src/components/propertyeditor/ +├── VariantPicker/ +│ ├── VariantPicker.tsx +│ ├── VariantPicker.module.scss +│ ├── VariantOption.tsx # Single variant option with preview +│ └── index.ts +├── SizePicker/ +│ ├── SizePicker.tsx # sm/md/lg/xl buttons +│ └── SizePicker.module.scss +├── TokenOverrideRow/ +│ ├── TokenOverrideRow.tsx # Single property override +│ ├── TokenOverrideRow.module.scss +│ └── index.ts +``` + +### Phase 3: Token Picker Integration (2-3 hrs) + +Connect TokenPicker (from STYLE-001) to override rows: + +```typescript +interface TokenOverrideRowProps { + property: string; // e.g., 'backgroundColor' + label: string; // e.g., 'Background' + variantValue: string; // Value from variant + currentValue: string | null; // Override value (null = use variant) + tokenCategory: TokenCategory; // Filter tokens shown + onChange: (value: string | null) => void; +} + +function TokenOverrideRow({ + property, + label, + variantValue, + currentValue, + tokenCategory, + onChange +}: TokenOverrideRowProps) { + const isOverridden = currentValue !== null; + + return ( +
+ + { + if (val === variantValue) { + onChange(null); // Reset to variant + } else { + onChange(val); + } + }} + placeholder="From Variant" + showVariantDefault={variantValue} + /> + {isOverridden && ( + + ⚠️ Overriding variant + + )} +
+ ); +} +``` + +### Phase 4: Advanced Section (Legacy Panel) (2-3 hrs) + +Preserve existing functionality in collapsible advanced section: + +```typescript +// Wrap existing property controls in Advanced section +function AdvancedSection({ node }: { node: NodeModel }) { + return ( + + {/* Position controls */} + + + {/* Box model (existing) */} + + + {/* Effects */} + + + {/* Transform */} + + + {/* Custom CSS */} + + + ); +} +``` + +### Phase 5: Polish & Indicators (2-3 hrs) + +1. Add override count to Style section header +2. Add custom values indicator to panel header +3. Add canvas indicator (optional) +4. Implement "Reset All Overrides" functionality +5. Add animations for section expand/collapse + +--- + +## Node-Specific Panel Configurations + +Different nodes show different sections: + +```typescript +const panelConfigs: Record = { + 'net.noodl.visual.button': { + sections: ['content', 'style', 'behavior', 'style-overrides', 'layout', 'advanced'], + contentFields: ['label', 'icon', 'iconPosition'], + styleOptions: { showVariants: true, showSizes: true }, + }, + + 'net.noodl.visual.text': { + sections: ['content', 'style', 'layout', 'advanced'], + contentFields: ['text'], + styleOptions: { showVariants: true, showSizes: false }, + }, + + 'net.noodl.visual.group': { + sections: ['style', 'layout', 'advanced'], + contentFields: [], + styleOptions: { showVariants: true, showSizes: false }, + }, + + 'net.noodl.visual.image': { + sections: ['content', 'style', 'layout', 'advanced'], + contentFields: ['source', 'alt'], + styleOptions: { showVariants: true, showSizes: false }, + }, +}; +``` + +--- + +## Testing Strategy + +### Unit Tests + +- Section rendering based on node type +- Override state management +- Token picker selection +- Reset functionality + +### Integration Tests + +- Select variant → styles apply +- Override property → indicator appears +- Reset overrides → returns to variant +- Expand/collapse sections → state persists + +### Manual Testing Checklist + +- [ ] Select Button, see variant picker in Style section +- [ ] Change variant, see immediate visual update +- [ ] Expand Style Overrides, override a property +- [ ] See "2 overrides" indicator appear +- [ ] Click Reset All Overrides +- [ ] Expand Advanced section, verify all legacy controls work +- [ ] Use custom CSS field +- [ ] Select Group, verify appropriate sections shown +- [ ] Select logic node (non-visual), verify no style sections + +--- + +## Success Criteria + +- [ ] Property panel reorganized into collapsible sections +- [ ] Variant picker prominently displayed for styled elements +- [ ] Token overrides section works correctly +- [ ] Advanced section preserves all legacy functionality +- [ ] Override indicators show where variants are overridden +- [ ] "Reset All Overrides" works correctly +- [ ] Panel adapts to different node types + +--- + +## Backward Compatibility + +The existing property panel functionality must be preserved: + +1. All existing CSS properties remain editable in Advanced section +2. Projects with manual styling continue to work +3. No forced migration to new system +4. Advanced section provides identical control to old panel + +--- + +## Dependencies + +**Blocked By:** +- STYLE-001 (Token System) - needs TokenPicker component +- STYLE-002 (Element Configs) - needs variant definitions + +**Blocks:** +- STYLE-005 (Smart Suggestions) - builds on panel structure + +--- + +*Last Updated: January 2026* diff --git a/dev-docs/tasks/phase-8-styles-overhaul/STYLE-005-suggestions/README.md b/dev-docs/tasks/phase-8-styles-overhaul/STYLE-005-suggestions/README.md new file mode 100644 index 0000000..1ea6ef8 --- /dev/null +++ b/dev-docs/tasks/phase-8-styles-overhaul/STYLE-005-suggestions/README.md @@ -0,0 +1,593 @@ +# STYLE-005: Smart Style Suggestions + +## Overview + +Implement gentle nudges that help users systematize their styling. When users repeatedly use the same custom values or create elements with many overrides, suggest saving them as tokens or variants. + +**Phase:** 8 (Styles Overhaul) +**Priority:** MEDIUM (polish feature) +**Effort:** 8-10 hours +**Risk:** Low +**Dependencies:** STYLE-001, STYLE-002, STYLE-004 + +--- + +## Background + +### The Problem + +Users often start with custom values (especially beginners), then realize they've used the same hex color in 15 places. Changing it requires finding and updating all 15 instances. + +### The Solution + +Non-intrusive suggestions that help users "graduate" to systematic styling: + +1. **Repeated Value Detection**: "You've used #3b82f6 in 5 elements. Save as token?" +2. **Custom Variant Detection**: "This button has 4 custom values. Save as new variant?" +3. **Inconsistency Detection**: "These buttons use similar but different colors. Unify them?" + +--- + +## Suggestion Types + +### Type 1: Repeated Color + +Triggered when the same hex color appears in 3+ elements. + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 💡 STYLE SUGGESTION [×] │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ You've used ■ #3b82f6 in 5 elements. │ +│ │ +│ Save as a token to update all at once? │ +│ │ +│ Token name: [--brand-blue ] │ +│ │ +│ Elements using this color: │ +│ • Button "Sign Up" (background) │ +│ • Button "Learn More" (background) │ +│ • Text "Welcome" (color) │ +│ • + 2 more │ +│ │ +│ [Create Token & Update All] [Ignore] [Don't Suggest Again] │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Type 2: Repeated Spacing + +Triggered when the same spacing value appears repeatedly. + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 💡 STYLE SUGGESTION [×] │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ You're using 24px padding in 8 elements. │ +│ │ +│ This matches --space-6 from your tokens. │ +│ Switch to the token for consistent theming? │ +│ │ +│ [Switch to Token] [Keep Manual Values] [Don't Suggest] │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Type 3: Custom Variant Candidate + +Triggered when an element has 3+ property overrides. + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 💡 STYLE SUGGESTION [×] │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ This button has 4 custom properties that could be a variant: │ +│ │ +│ • Background: #22c55e (custom) │ +│ • Text color: #ffffff │ +│ • Border radius: 9999px │ +│ • Padding: 12px 32px │ +│ │ +│ Preview: ┌──────────────────┐ │ +│ │ [ Success ] │ │ +│ └──────────────────┘ │ +│ │ +│ [Save as "success" Variant] [Keep as Custom] │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Type 4: Similar Values (Inconsistency) + +Triggered when near-identical values exist (e.g., #3b82f6 and #3b81f5). + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 💡 STYLE SUGGESTION [×] │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Found similar but different colors: │ +│ │ +│ ■ #3b82f6 used in 4 elements │ +│ ■ #3b81f5 used in 2 elements │ +│ ■ #3a82f6 used in 1 element │ +│ │ +│ These look like they should be the same color. │ +│ Unify them? │ +│ │ +│ Unify to: [■ #3b82f6 ▼] │ +│ │ +│ [Unify All] [Ignore] [Don't Suggest] │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Type 5: Off-System Element + +Triggered when selecting an element with multiple custom values. + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 💡 This element uses 6 custom values [×] │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Custom values won't update when you change your theme. │ +│ │ +│ Options: │ +│ • [Map to Tokens] - Replace values with matching tokens │ +│ • [Save as Variant] - Create a reusable variant │ +│ • [Keep Custom] - I know what I'm doing │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Detection Logic + +### Style Analyzer Service + +```typescript +interface StyleAnalyzer { + // Analyze entire project for patterns + analyzeProject(): StyleAnalysisResult; + + // Analyze single element + analyzeElement(nodeId: string): ElementAnalysisResult; + + // Get suggestions for current context + getSuggestions(context: AnalysisContext): StyleSuggestion[]; +} + +interface StyleAnalysisResult { + repeatedColors: RepeatedValue[]; + repeatedSpacing: RepeatedValue[]; + variantCandidates: VariantCandidate[]; + inconsistencies: Inconsistency[]; +} + +interface RepeatedValue { + value: string; + property: string; + count: number; + elements: ElementReference[]; + matchingToken?: string; // If value matches existing token +} + +interface VariantCandidate { + nodeId: string; + nodeType: string; + overrides: PropertyOverride[]; + suggestedName?: string; +} + +interface Inconsistency { + type: 'color' | 'spacing' | 'typography'; + values: { value: string; count: number }[]; + suggestedUnification: string; +} +``` + +### Detection Thresholds + +```typescript +const THRESHOLDS = { + // Minimum occurrences before suggesting token + repeatedValueMinCount: 3, + + // Minimum overrides before suggesting variant + variantCandidateMinOverrides: 3, + + // Color similarity threshold (0-100, lower = more similar) + colorSimilarityThreshold: 5, + + // Spacing similarity threshold (in px) + spacingSimilarityThreshold: 2, +}; +``` + +### Color Similarity Detection + +```typescript +function areColorsSimilar(color1: string, color2: string): boolean { + const rgb1 = hexToRgb(color1); + const rgb2 = hexToRgb(color2); + + // Calculate Euclidean distance in RGB space + const distance = Math.sqrt( + Math.pow(rgb1.r - rgb2.r, 2) + + Math.pow(rgb1.g - rgb2.g, 2) + + Math.pow(rgb1.b - rgb2.b, 2) + ); + + return distance < THRESHOLDS.colorSimilarityThreshold; +} +``` + +--- + +## Implementation + +### Phase 1: Analysis Engine (3-4 hrs) + +**Files to create:** + +``` +packages/noodl-editor/src/editor/src/services/ +├── StyleAnalyzer/ +│ ├── StyleAnalyzer.ts # Main analyzer service +│ ├── ColorAnalyzer.ts # Color-specific analysis +│ ├── SpacingAnalyzer.ts # Spacing analysis +│ ├── VariantAnalyzer.ts # Variant candidate detection +│ ├── types.ts # TypeScript interfaces +│ └── index.ts +``` + +**Analysis Pipeline:** + +```typescript +class StyleAnalyzer { + private project: ProjectModel; + private tokenSystem: StyleTokensModel; + + analyzeProject(): StyleAnalysisResult { + const allNodes = this.project.getAllVisualNodes(); + const styleValues = this.extractAllStyleValues(allNodes); + + return { + repeatedColors: this.findRepeatedColors(styleValues), + repeatedSpacing: this.findRepeatedSpacing(styleValues), + variantCandidates: this.findVariantCandidates(allNodes), + inconsistencies: this.findInconsistencies(styleValues), + }; + } + + private extractAllStyleValues(nodes: NodeModel[]): StyleValueMap { + const values: StyleValueMap = { + colors: new Map(), + spacing: new Map(), + typography: new Map(), + }; + + for (const node of nodes) { + // Extract color values + for (const prop of COLOR_PROPERTIES) { + const value = node.getStyleValue(prop); + if (value && !value.startsWith('var(')) { + this.addToMap(values.colors, value, node, prop); + } + } + + // Extract spacing values + for (const prop of SPACING_PROPERTIES) { + const value = node.getStyleValue(prop); + if (value && !value.startsWith('var(')) { + this.addToMap(values.spacing, value, node, prop); + } + } + } + + return values; + } +} +``` + +### Phase 2: Suggestion UI Components (2-3 hrs) + +**Files to create:** + +``` +packages/noodl-core-ui/src/components/ +├── StyleSuggestions/ +│ ├── SuggestionBanner.tsx # Inline suggestion banner +│ ├── SuggestionBanner.module.scss +│ ├── SuggestionModal.tsx # Full suggestion dialog +│ ├── SuggestionModal.module.scss +│ ├── CreateTokenForm.tsx # Token creation mini-form +│ ├── CreateVariantForm.tsx # Variant creation mini-form +│ └── index.ts +``` + +**SuggestionBanner Component:** + +```typescript +interface SuggestionBannerProps { + suggestion: StyleSuggestion; + onAccept: () => void; + onDismiss: () => void; + onNeverShow: () => void; +} + +function SuggestionBanner({ + suggestion, + onAccept, + onDismiss, + onNeverShow +}: SuggestionBannerProps) { + return ( +
+ +
+

{suggestion.message}

+ {suggestion.preview && ( +
{suggestion.preview}
+ )} +
+
+ + + +
+
+ ); +} +``` + +### Phase 3: Integration Points (2-3 hrs) + +**Where suggestions appear:** + +1. **Property Panel**: Banner at top when element has suggestions +2. **Floating Toast**: Project-wide suggestions (periodic) +3. **Style Tokens Panel**: Suggestions for repeated values + +**Integration in Property Panel:** + +```typescript +// In PropertyEditor.tsx +function PropertyEditor({ node }: { node: NodeModel }) { + const suggestions = useStyleSuggestions(node); + const [dismissedSuggestions, setDismissed] = useState>(new Set()); + + const activeSuggestion = suggestions.find( + s => !dismissedSuggestions.has(s.id) + ); + + return ( +
+ {activeSuggestion && ( + handleAccept(activeSuggestion)} + onDismiss={() => setDismissed(prev => new Set([...prev, activeSuggestion.id]))} + onNeverShow={() => handleNeverShow(activeSuggestion.type)} + /> + )} + + {/* Rest of property panel */} +
+ ); +} +``` + +### Phase 4: Action Handlers (2-3 hrs) + +**Implementing suggestion actions:** + +```typescript +class SuggestionActionHandler { + // Create token from repeated value + async createTokenFromValue( + value: string, + tokenName: string, + elements: ElementReference[] + ): Promise { + // 1. Create the token + await StyleTokensModel.addToken({ + name: tokenName, + value: value, + category: this.inferCategory(value), + }); + + // 2. Update all elements to use the token + for (const ref of elements) { + const node = ProjectModel.getNode(ref.nodeId); + node.setStyleValue(ref.property, `var(${tokenName})`); + } + + // 3. Track for analytics + Analytics.track('suggestion_accepted', { type: 'create_token' }); + } + + // Create variant from element + async createVariantFromElement( + nodeId: string, + variantName: string + ): Promise { + const node = ProjectModel.getNode(nodeId); + const overrides = this.extractOverrides(node); + + // 1. Create the variant + await ElementConfigModel.addVariant(node.nodeType, variantName, overrides); + + // 2. Apply variant to element (clears overrides) + node.setVariant(variantName); + + Analytics.track('suggestion_accepted', { type: 'create_variant' }); + } + + // Unify similar values + async unifyValues( + values: string[], + targetValue: string, + elements: ElementReference[] + ): Promise { + for (const ref of elements) { + if (values.includes(ref.value)) { + const node = ProjectModel.getNode(ref.nodeId); + node.setStyleValue(ref.property, targetValue); + } + } + + Analytics.track('suggestion_accepted', { type: 'unify_values' }); + } +} +``` + +--- + +## User Preferences + +Allow users to control suggestion behavior: + +```typescript +interface StyleSuggestionPreferences { + enabled: boolean; + + // Per-type controls + showRepeatedColorSuggestions: boolean; + showRepeatedSpacingSuggestions: boolean; + showVariantSuggestions: boolean; + showInconsistencySuggestions: boolean; + + // Frequency + frequency: 'always' | 'sometimes' | 'rarely'; + + // Dismissed suggestions (persisted) + dismissedTypes: Set; + dismissedSpecific: Set; // Specific suggestion IDs +} +``` + +**Settings UI:** + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ STYLE SUGGESTIONS │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ [x] Enable style suggestions │ +│ │ +│ Suggest when: │ +│ [x] Same color used multiple times │ +│ [x] Same spacing used multiple times │ +│ [x] Element has many custom values │ +│ [x] Similar values might be inconsistent │ +│ │ +│ Frequency: [Sometimes ▼] │ +│ ● Always - Show all suggestions │ +│ ○ Sometimes - Show important suggestions │ +│ ○ Rarely - Only show critical suggestions │ +│ │ +│ [Reset Dismissed Suggestions] │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Timing & Triggers + +### When to analyze: + +1. **On element selection**: Check selected element for suggestions +2. **On property change**: Re-analyze if custom value entered +3. **Periodic background**: Full project scan every 5 minutes (if idle) +4. **On project open**: Initial analysis + +### Debouncing: + +```typescript +// Don't spam suggestions +const SUGGESTION_COOLDOWN = 30000; // 30 seconds between suggestions + +class SuggestionScheduler { + private lastSuggestionTime = 0; + + shouldShowSuggestion(): boolean { + const now = Date.now(); + if (now - this.lastSuggestionTime < SUGGESTION_COOLDOWN) { + return false; + } + this.lastSuggestionTime = now; + return true; + } +} +``` + +--- + +## Testing Strategy + +### Unit Tests + +- Color similarity detection +- Repeated value detection +- Variant candidate identification +- Action handlers + +### Integration Tests + +- Suggestion appears when threshold met +- Accept action creates token/variant +- Dismiss persists across sessions +- Preferences respected + +### Manual Testing Checklist + +- [ ] Add same hex color to 3+ elements → suggestion appears +- [ ] Accept "Create Token" → token created, elements updated +- [ ] Dismiss suggestion → doesn't reappear +- [ ] Click "Don't Suggest Again" → type permanently hidden +- [ ] Create element with 4+ overrides → variant suggestion appears +- [ ] Disable suggestions in settings → no suggestions appear + +--- + +## Success Criteria + +- [ ] Repeated color detection works +- [ ] Repeated spacing detection works +- [ ] Variant candidate detection works +- [ ] Similar value detection works +- [ ] Accept actions work correctly +- [ ] Dismiss actions persist +- [ ] User preferences respected +- [ ] Non-intrusive UX (not spammy) + +--- + +## Dependencies + +**Blocked By:** +- STYLE-001 (Token System) - suggestions create tokens +- STYLE-002 (Element Configs) - suggestions create variants +- STYLE-004 (Property Panel) - suggestions display location + +**Blocks:** +- None (final task in Phase 8) + +--- + +*Last Updated: January 2026* diff --git a/dev-docs/tasks/phase-8-styles-overhaul/WIZARD-001-project-creation/README.md b/dev-docs/tasks/phase-8-styles-overhaul/WIZARD-001-project-creation/README.md new file mode 100644 index 0000000..a1f72b4 --- /dev/null +++ b/dev-docs/tasks/phase-8-styles-overhaul/WIZARD-001-project-creation/README.md @@ -0,0 +1,863 @@ +# WIZARD-001: Project Creation Wizard + +## Overview + +Create a guided project setup experience that transforms "blank canvas anxiety" into "ready to build in 60 seconds." The wizard integrates style presets, backend configuration, GitHub connection, deployment setup, and AI scaffolding into a streamlined flow. + +**Phase:** 8 (Styles Overhaul) or standalone +**Priority:** HIGH (major UX improvement) +**Effort:** 20-28 hours +**Risk:** Medium (integrates multiple systems) +**Dependencies:** STYLE-003 (Presets), GIT-004A (GitHub OAuth), DEPLOY-001, AI-004 + +--- + +## Background + +### Current State + +Creating a new Noodl project: + +1. Click "New Project" +2. Enter name +3. Get blank canvas +4. Manually configure everything: styling, backend, git, deployment... + +### Target State + +A Replit/Vercel-style wizard: + +1. Choose how to start (Quick/Guided/AI) +2. Pick style preset (or describe your app) +3. Configure backend +4. Connect GitHub +5. Set up deployment +6. (Optional) AI generates scaffold +7. **Start building with everything ready** + +--- + +## The Three Entry Modes + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ CREATE NEW PROJECT │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ How would you like to start? │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ ⚡ QUICK START │ │ +│ │ Blank project with Modern preset. │ │ +│ │ Configure everything later. │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ 🛠️ GUIDED SETUP │ │ +│ │ Walk through style, backend, GitHub, and deployment │ │ +│ │ options step by step. │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ ✨ AI PROJECT BUILDER │ │ +│ │ Describe what you want to build. AI sets up │ │ +│ │ everything and generates starter components. │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Guided Setup Flow + +### Step 1: Project Basics + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ NEW PROJECT Step 1/6 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ PROJECT NAME │ +│ [My Awesome App ] │ +│ │ +│ DESCRIPTION (optional) │ +│ [A task management tool for small teams ] │ +│ │ +│ 💡 Tip: A good description helps AI generate better │ +│ components if you enable AI scaffolding later. │ +│ │ +│ │ +│ │ +│ [Next: Style Preset →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Step 2: Style Preset + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ STYLE PRESET Step 2/6 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Choose a visual style for your project: │ +│ │ +│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ +│ │ Modern │ │ Minimal │ │ Playful │ │ Corp │ │ Soft │ │ +│ │ │ │ │ │ │ │ │ │ │ │ +│ │ ┌─────┐ │ │ ┌─────┐ │ │ ┌─────┐ │ │ ┌─────┐ │ │ ┌─────┐ │ │ +│ │ │ btn │ │ │ │ btn │ │ │ │ btn │ │ │ │ btn │ │ │ │ btn │ │ │ +│ │ └─────┘ │ │ └─────┘ │ │ └─────┘ │ │ └─────┘ │ │ └─────┘ │ │ +│ │ ─────── │ │ ─────── │ │ ─────── │ │ ─────── │ │ ─────── │ │ +│ │ ─────── │ │ ─────── │ │ ─────── │ │ ─────── │ │ ─────── │ │ +│ └────●────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ +│ Selected │ +│ │ +│ "Clean and professional with subtle depth" │ +│ │ +│ [x] I'll customize colors and fonts later │ +│ │ +│ [← Back] [Next: Backend →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Step 3: Backend & Data + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ BACKEND & DATA Step 3/6 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Does your app need to store data? │ +│ │ +│ ○ NO BACKEND │ +│ Frontend only - static content, no user data │ +│ │ +│ ● LOCAL BACKEND (Recommended for starting) │ +│ SQLite database that works offline. │ +│ Zero configuration. Sync to cloud later. │ +│ ✓ Free ✓ No account needed ✓ Works offline │ +│ │ +│ ○ CLOUD BACKEND │ +│ Connect to an existing backend service: │ +│ ┌─────────────────────────────────────────────────────┐ │ +│ │ [Supabase ▼] │ │ +│ │ • Supabase (Postgres + Auth + Realtime) │ │ +│ │ • Pocketbase (Self-hosted, simple) │ │ +│ │ • Firebase (Google ecosystem) │ │ +│ │ • Directus (Headless CMS) │ │ +│ │ • Custom REST API │ │ +│ │ • Custom GraphQL API │ │ +│ └─────────────────────────────────────────────────────┘ │ +│ │ +│ ○ DOCKER │ +│ Spin up Postgres/MySQL in a local container. │ +│ For developers who want full database control. │ +│ │ +│ [← Back] [Next: Authentication →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Step 4: Authentication (Conditional) + +Only shown if backend selected: + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ AUTHENTICATION Step 4/6 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Does your app need user login? │ +│ │ +│ ○ NO AUTHENTICATION │ +│ Public app - anyone can access everything │ +│ │ +│ ● EMAIL + PASSWORD │ +│ Traditional signup/login with email verification │ +│ │ +│ ○ MAGIC LINK │ +│ Passwordless - users click a link sent to email │ +│ │ +│ ○ SOCIAL LOGIN │ +│ Sign in with Google, GitHub, etc. │ +│ ┌─────────────────────────────────────────────────────┐ │ +│ │ [x] Google [x] GitHub [ ] Apple [ ] Microsoft │ │ +│ └─────────────────────────────────────────────────────┘ │ +│ │ +│ ○ I'LL CONFIGURE LATER │ +│ Skip for now, add authentication later │ +│ │ +│ [x] Generate login/signup UI components │ +│ │ +│ [← Back] [Next: GitHub →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Step 5: Version Control + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ VERSION CONTROL Step 5/6 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Connect your project to GitHub for backup and collaboration. │ +│ │ +│ ○ SKIP FOR NOW │ +│ I'll set up Git later │ +│ │ +│ ● CONNECT TO GITHUB │ +│ │ +│ ┌─────────────────────────────────────────────────────┐ │ +│ │ [🔗 Sign in with GitHub] │ │ +│ └─────────────────────────────────────────────────────┘ │ +│ │ +│ ─────────── After signing in ─────────── │ +│ │ +│ Repository: │ +│ ● Create new repository │ +│ Name: [my-awesome-app ] │ +│ Visibility: [Private ▼] │ +│ │ +│ ○ Use existing repository │ +│ ┌─────────────────────────────────────────────────────┐ │ +│ │ my-org/existing-repo │ │ +│ │ my-org/another-project │ │ +│ │ personal/side-project │ │ +│ └─────────────────────────────────────────────────────┘ │ +│ │ +│ ○ Paste repository URL │ +│ [https://github.com/... ] │ +│ │ +│ [← Back] [Next: Deployment →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Step 6: Deployment (Conditional) + +Only shown if GitHub connected: + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ DEPLOYMENT Step 6/6 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Set up automatic deployment when you push to GitHub. │ +│ │ +│ ○ SKIP FOR NOW │ +│ I'll deploy manually or set this up later │ +│ │ +│ ● AUTO-DEPLOY ON PUSH │ +│ │ +│ Platform: │ +│ ● Vercel (Recommended for React) │ +│ [🔗 Connect Vercel Account] │ +│ │ +│ ○ Netlify │ +│ [🔗 Connect Netlify Account] │ +│ │ +│ ○ GitHub Pages (Static sites only) │ +│ No account needed - uses GitHub Actions │ +│ │ +│ ○ Cloudflare Pages │ +│ [🔗 Connect Cloudflare Account] │ +│ │ +│ Options: │ +│ [x] Create preview deployments for pull requests │ +│ [x] Show deployment status in Noodl dashboard │ +│ │ +│ [← Back] [Next: Review →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Step 7: AI Setup (Optional) + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ AI ASSISTANT Optional │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Let AI help you get started faster. │ +│ │ +│ ○ SKIP AI FEATURES │ +│ I'll build everything manually │ +│ │ +│ ● ENABLE AI ASSISTANT │ +│ │ +│ API Key: │ +│ [sk-ant-•••••••••••••••••••••••••••••] [Verify ✓] │ +│ Don't have one? [Get API key from Anthropic →] │ +│ │ +│ What should AI generate? │ +│ │ +│ [x] Starter components based on project description │ +│ AI will create basic UI structure and navigation │ +│ │ +│ [x] Database schema (if backend selected) │ +│ AI will suggest tables and fields based on your │ +│ project description │ +│ │ +│ [ ] Sample data │ +│ Populate database with realistic test data │ +│ │ +│ ┌─────────────────────────────────────────────────────┐ │ +│ │ 💰 Estimated cost: ~$0.05 - $0.15 (one-time) │ │ +│ │ Based on project complexity │ │ +│ │ [?] How is this calculated? │ │ +│ └─────────────────────────────────────────────────────┘ │ +│ │ +│ [← Back] [Next: Review →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Final Step: Review & Create + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ REVIEW & CREATE │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Project: "My Awesome App" │ +│ A task management tool for small teams │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ CONFIGURATION SUMMARY │ │ +│ ├─────────────────────────────────────────────────────────┤ │ +│ │ Style: Modern preset (blue theme) [Edit] │ │ +│ │ Backend: Local SQLite [Edit] │ │ +│ │ Auth: Email + Password [Edit] │ │ +│ │ GitHub: my-org/my-awesome-app (new) [Edit] │ │ +│ │ Deployment: Vercel (auto-deploy) [Edit] │ │ +│ │ AI: Generate components + schema [Edit] │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ COST ESTIMATE │ │ +│ ├─────────────────────────────────────────────────────────┤ │ +│ │ Monthly: │ │ +│ │ • Style system ─────────────────────── Free │ │ +│ │ • Local SQLite ─────────────────────── Free │ │ +│ │ • GitHub (private repo) ────────────── Free │ │ +│ │ • Vercel (hobby tier) ──────────────── Free │ │ +│ │ ───────── │ │ +│ │ Total: $0/month │ │ +│ │ │ │ +│ │ One-time: │ │ +│ │ • AI scaffold generation ───────────── ~$0.08 │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ [ ] Remember these settings for future projects │ +│ │ +│ [← Back] [Create Project →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Creation Progress + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ CREATING "MY AWESOME APP" │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ ✓ Creating project structure │ +│ ✓ Applying Modern style preset │ +│ ✓ Setting up SQLite database │ +│ ✓ Configuring authentication │ +│ ● Generating components with AI... │ +│ ├─ Analyzing project description │ +│ ├─ Creating navigation structure │ +│ └─ Building task management components │ +│ ○ Generating database schema │ +│ ○ Creating GitHub repository │ +│ ○ Configuring Vercel deployment │ +│ ○ Initial commit and push │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ AI is generating: TaskList component │ │ +│ │ ████████████████████░░░░░░░░░░░░░░░░░░░░ 45% │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ [View Details] [Cancel] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## AI Project Builder Mode + +When user selects "AI Project Builder": + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ AI PROJECT BUILDER │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Describe what you want to build: │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ A project management app where teams can create │ │ +│ │ projects, add tasks with due dates and priorities, │ │ +│ │ assign tasks to team members, and track progress │ │ +│ │ with a kanban board view. Users should be able to │ │ +│ │ comment on tasks and get notifications. │ │ +│ │ │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ Examples: │ +│ • "A recipe app where users can save and organize recipes" │ +│ • "An invoice generator for freelancers" │ +│ • "A booking system for a hair salon" │ +│ │ +│ API Key: [sk-ant-•••••••••••••] [Verify ✓] │ +│ │ +│ [Analyze & Suggest →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +After analysis: + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ AI SUGGESTIONS │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Based on your description, here's what I recommend: │ +│ │ +│ PROJECT TYPE: Web Application (Dashboard) │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ STYLE │ │ +│ │ Recommended: Modern │ │ +│ │ A clean, professional look suits project management │ │ +│ │ [Change ▼] │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ BACKEND │ │ +│ │ Recommended: Local SQLite → Supabase │ │ +│ │ Start local, sync to cloud when ready for team use │ │ +│ │ [Change ▼] │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ AUTHENTICATION │ │ +│ │ Recommended: Email + Password │ │ +│ │ Team members need accounts to be assigned tasks │ │ +│ │ [Change ▼] │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ SUGGESTED DATABASE SCHEMA │ │ +│ │ │ │ +│ │ 📁 users (id, email, name, avatar, role) │ │ +│ │ 📁 projects (id, name, description, owner_id) │ │ +│ │ 📁 tasks (id, title, status, priority, assignee_id...) │ │ +│ │ 📁 comments (id, task_id, author_id, content) │ │ +│ │ 📁 notifications (id, user_id, type, read, data) │ │ +│ │ │ │ +│ │ [View Full Schema] [Edit Schema] │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ COMPONENTS TO GENERATE │ │ +│ │ │ │ +│ │ [x] Dashboard layout with sidebar navigation │ │ +│ │ [x] Project list and project detail views │ │ +│ │ [x] Task list with filtering and sorting │ │ +│ │ [x] Kanban board view │ │ +│ │ [x] Task detail with comments │ │ +│ │ [x] User profile and settings │ │ +│ │ [x] Login/Signup pages │ │ +│ │ [ ] Notification center │ │ +│ │ [ ] Team management │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ Estimated AI cost: ~$0.12 │ +│ │ +│ [← Back] [Customize More] [Create Project →] │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Implementation + +### Phase 1: Wizard Framework (6-8 hrs) + +**Files to create:** + +``` +packages/noodl-editor/src/editor/src/views/ +├── ProjectWizard/ +│ ├── ProjectWizard.tsx # Main wizard container +│ ├── ProjectWizard.module.scss +│ ├── WizardContext.tsx # Shared state +│ ├── WizardNavigation.tsx # Step indicators +│ ├── steps/ +│ │ ├── EntryModeStep.tsx # Quick/Guided/AI selection +│ │ ├── ProjectBasicsStep.tsx # Name, description +│ │ ├── StylePresetStep.tsx # Preset selection +│ │ ├── BackendStep.tsx # Backend configuration +│ │ ├── AuthenticationStep.tsx # Auth options +│ │ ├── GitHubStep.tsx # Version control +│ │ ├── DeploymentStep.tsx # Deployment setup +│ │ ├── AISetupStep.tsx # AI configuration +│ │ ├── ReviewStep.tsx # Summary & create +│ │ └── CreationProgressStep.tsx # Progress display +│ └── index.ts +``` + +**Wizard State:** + +```typescript +interface WizardState { + // Basics + projectName: string; + description: string; + + // Style + stylePreset: string; + + // Backend + backendType: 'none' | 'local' | 'cloud' | 'docker'; + cloudProvider?: 'supabase' | 'pocketbase' | 'firebase' | 'directus' | 'custom'; + cloudConfig?: Record; + + // Auth + authType: 'none' | 'email' | 'magic-link' | 'social' | 'later'; + socialProviders?: string[]; + generateAuthUI: boolean; + + // GitHub + gitHubEnabled: boolean; + gitHubRepo?: { + type: 'new' | 'existing' | 'url'; + name?: string; + visibility?: 'public' | 'private'; + url?: string; + }; + + // Deployment + deploymentEnabled: boolean; + deploymentPlatform?: 'vercel' | 'netlify' | 'github-pages' | 'cloudflare'; + previewDeployments: boolean; + + // AI + aiEnabled: boolean; + aiApiKey?: string; + aiGenerateComponents: boolean; + aiGenerateSchema: boolean; + aiGenerateSampleData: boolean; +} + +interface WizardContextValue { + state: WizardState; + updateState: (partial: Partial) => void; + currentStep: number; + goToStep: (step: number) => void; + nextStep: () => void; + prevStep: () => void; + canProceed: boolean; + createProject: () => Promise; +} +``` + +### Phase 2: Integration Hooks (6-8 hrs) + +**Files to create:** + +``` +packages/noodl-editor/src/editor/src/views/ProjectWizard/ +├── hooks/ +│ ├── useStylePresets.ts # Preset loading and preview +│ ├── useGitHubSetup.ts # GitHub OAuth and repo management +│ ├── useDeploymentSetup.ts # Vercel/Netlify integration +│ ├── useAIScaffold.ts # AI generation orchestration +│ └── useProjectCreation.ts # Final project creation +``` + +**Integration Points:** + +```typescript +// useGitHubSetup.ts +function useGitHubSetup() { + const [isAuthenticated, setAuthenticated] = useState(false); + const [repos, setRepos] = useState([]); + + const authenticate = async () => { + // Uses GIT-004A OAuth flow + const token = await GitHubOAuth.authenticate(); + setAuthenticated(true); + const userRepos = await GitHubClient.listRepos(token); + setRepos(userRepos); + }; + + const createRepo = async (name: string, visibility: 'public' | 'private') => { + // Uses GIT-004A repo creation + return await GitHubClient.createRepo({ name, private: visibility === 'private' }); + }; + + return { isAuthenticated, repos, authenticate, createRepo }; +} +``` + +### Phase 3: AI Builder Mode (4-6 hrs) + +**Files to create:** + +``` +packages/noodl-editor/src/editor/src/views/ProjectWizard/ +├── ai/ +│ ├── AIProjectAnalyzer.ts # Analyze description +│ ├── AISchemaGenerator.ts # Generate database schema +│ ├── AIComponentGenerator.ts # Generate components +│ ├── AIPrompts.ts # Prompt templates +│ └── types.ts +``` + +**AI Analysis Flow:** + +```typescript +interface AIProjectAnalysis { + projectType: 'webapp' | 'ecommerce' | 'content' | 'custom'; + suggestedPreset: string; + suggestedBackend: BackendConfig; + suggestedAuth: AuthConfig; + schema: DatabaseSchema; + components: ComponentSuggestion[]; + estimatedCost: number; +} + +async function analyzeProject(description: string): Promise { + const prompt = buildAnalysisPrompt(description); + const response = await anthropic.complete(prompt); + return parseAnalysisResponse(response); +} +``` + +### Phase 4: Creation Orchestration (4-6 hrs) + +**Files to create:** + +``` +packages/noodl-editor/src/editor/src/views/ProjectWizard/ +├── creation/ +│ ├── ProjectCreator.ts # Main orchestrator +│ ├── steps/ +│ │ ├── CreateProjectStructure.ts +│ │ ├── ApplyStylePreset.ts +│ │ ├── SetupBackend.ts +│ │ ├── SetupAuthentication.ts +│ │ ├── GenerateAIComponents.ts +│ │ ├── GenerateAISchema.ts +│ │ ├── CreateGitHubRepo.ts +│ │ ├── ConfigureDeployment.ts +│ │ └── InitialCommit.ts +│ └── types.ts +``` + +**Creation Pipeline:** + +```typescript +class ProjectCreator { + private steps: CreationStep[] = []; + private progress: CreationProgress; + + constructor(config: WizardState) { + // Build step list based on config + this.steps.push(new CreateProjectStructure(config)); + this.steps.push(new ApplyStylePreset(config.stylePreset)); + + if (config.backendType !== 'none') { + this.steps.push(new SetupBackend(config)); + } + + if (config.authType !== 'none') { + this.steps.push(new SetupAuthentication(config)); + } + + if (config.aiEnabled && config.aiGenerateSchema) { + this.steps.push(new GenerateAISchema(config)); + } + + if (config.aiEnabled && config.aiGenerateComponents) { + this.steps.push(new GenerateAIComponents(config)); + } + + if (config.gitHubEnabled) { + this.steps.push(new CreateGitHubRepo(config.gitHubRepo!)); + + if (config.deploymentEnabled) { + this.steps.push(new ConfigureDeployment(config)); + } + + this.steps.push(new InitialCommit()); + } + } + + async execute(onProgress: (progress: CreationProgress) => void): Promise { + for (const step of this.steps) { + this.progress = { + currentStep: step.name, + completed: this.steps.indexOf(step), + total: this.steps.length + }; + onProgress(this.progress); + + await step.execute(); + } + + return this.project; + } +} +``` + +--- + +## Dependencies + +### Required Before WIZARD-001: + +| Dependency | Task | Status | Notes | +| ------------- | ----------- | -------- | --------------------------- | +| Style Presets | STYLE-003 | Required | Preset selector integration | +| GitHub OAuth | GIT-004A | Required | GitHub connection step | +| Deployment | DEPLOY-001 | Optional | Can be added later | +| AI Scaffold | AI-004 | Optional | Can be added later | +| Local Backend | BACKEND-001 | Optional | Can default to "none" | + +### Can Work Incrementally: + +The wizard can ship with partial functionality: + +**V1 (Minimum):** + +- Entry mode selection +- Project basics +- Style preset +- Review & create + +**V2 (Add Backend):** + +- Backend step +- Authentication step + +**V3 (Add Git):** + +- GitHub step +- Deployment step + +**V4 (Add AI):** + +- AI builder mode +- AI setup step + +--- + +## Testing Strategy + +### Unit Tests + +- Wizard state management +- Step validation logic +- Creation pipeline ordering +- AI prompt generation + +### Integration Tests + +- Full wizard flow completion +- GitHub OAuth integration +- Deployment configuration +- Project creation with all options + +### Manual Testing Checklist + +- [ ] Quick Start creates project with Modern preset +- [ ] Guided flow navigates all steps correctly +- [ ] Style presets show visual previews +- [ ] Backend options configure correctly +- [ ] GitHub OAuth connects successfully +- [ ] Repository creation works +- [ ] Deployment configuration applies +- [ ] AI analysis generates reasonable suggestions +- [ ] AI schema generation works +- [ ] Progress display updates correctly +- [ ] Created project has all configured features + +--- + +## Success Criteria + +- [ ] Three entry modes work (Quick/Guided/AI) +- [ ] All guided steps functional +- [ ] Style preset applies correctly +- [ ] Backend configuration works +- [ ] GitHub integration functional +- [ ] Deployment setup works +- [ ] AI builder generates reasonable scaffolds +- [ ] Progress display accurate +- [ ] Created projects fully configured +- [ ] User can skip any optional step + +--- + +## Future Enhancements + +### Templates Library + +Pre-built project templates: + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ START FROM TEMPLATE │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ +│ │ Dashboard │ │ E-commerce│ │ Blog │ │ Landing │ │ +│ │ │ │ │ │ │ │ Page │ │ +│ │ 📊 │ │ 🛒 │ │ 📝 │ │ 🚀 │ │ +│ └───────────┘ └───────────┘ └───────────┘ └───────────┘ │ +│ │ +│ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ +│ │ Booking │ │ Social │ │ CRM │ │ Custom │ │ +│ │ System │ │ App │ │ │ │ │ │ +│ │ 📅 │ │ 👥 │ │ 📇 │ │ ⚡ │ │ +│ └───────────┘ └───────────┘ └───────────┘ └───────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Settings Presets + +Remember wizard settings: + +```typescript +interface WizardPreset { + name: string; + settings: Partial; +} + +// "My Standard Setup" +const preset: WizardPreset = { + name: 'My Standard Setup', + settings: { + stylePreset: 'modern', + backendType: 'local', + authType: 'email', + gitHubEnabled: true, + deploymentPlatform: 'vercel' + } +}; +``` + +### Team Templates + +Shared templates within organizations: + +- Admin creates standard project setup +- Team members start new projects from org template +- Ensures consistency across team projects + +--- + +_Last Updated: January 2026_ diff --git a/packages/noodl-editor/src/editor/src/views/SidePanel/SidePanel.tsx b/packages/noodl-editor/src/editor/src/views/SidePanel/SidePanel.tsx index 4e56d8a..55d9da1 100644 --- a/packages/noodl-editor/src/editor/src/views/SidePanel/SidePanel.tsx +++ b/packages/noodl-editor/src/editor/src/views/SidePanel/SidePanel.tsx @@ -63,6 +63,25 @@ export function SidePanel() { group ); + // --- + // Listen for node selection changes to force PropertyEditor recreation + // This ensures the panel updates when switching between different nodes + SidebarModel.instance.on( + SidebarModelEvent.nodeSelected, + () => { + const panelId = 'PropertyEditor'; + setPanels((prev) => { + const component = SidebarModel.instance.getPanelComponent(panelId); + if (component) { + // Force recreation with new node props + prev[panelId] = React.createElement(component); + } + return prev; + }); + }, + group + ); + // --- // Support Hot reload on all panels SidebarModel.instance.on(SidebarModelEvent.HotReload, () => {