mirror of
https://github.com/The-Low-Code-Foundation/OpenNoodl.git
synced 2026-03-08 01:53:30 +01:00
Added sprint protocol
This commit is contained in:
@@ -1839,3 +1839,23 @@ grep -r "var(--theme-spacing" packages/noodl-core-ui/src --include="*.scss"
|
||||
---
|
||||
|
||||
[Rest of the previous learnings content continues...]
|
||||
|
||||
---
|
||||
|
||||
## STYLE-001: UndoQueue requires UndoActionGroup class instances (2026-02-18)
|
||||
|
||||
**Context:** Building StyleTokensModel with undo support.
|
||||
**Discovery:** `UndoQueue.push()` requires `new UndoActionGroup({ label, do, undo })` — NOT a plain `{ label, do, undo }` object. The TypeScript error was clear but the fix isn't obvious from the class name alone.
|
||||
**Fix:** `UndoQueue.instance.push(new UndoActionGroup({ label: '...', do: () => {}, undo: () => {} }))`
|
||||
**Location:** `packages/noodl-editor/src/editor/src/models/undo-queue-model.ts`
|
||||
|
||||
## STYLE-001: Design token persistence pattern (2026-02-18)
|
||||
|
||||
**Context:** Implementing per-project design token persistence in StyleTokensModel.
|
||||
**Discovery:** Only custom overrides are stored in project metadata — never defaults. Defaults live in `DefaultTokens.ts` and are merged at load time. This keeps `project.json` lean and lets defaults be updated without migrations.
|
||||
**Location:** `StyleTokensModel._store()` uses `ProjectModel.instance.setMetaData('designTokens', data)`
|
||||
|
||||
## STYLE-001: DesignTokenPanel/ColorsTab pre-existed (2026-02-18)
|
||||
|
||||
**Context:** Adding a new "Tokens" tab to the DesignTokenPanel.
|
||||
**Discovery:** `DesignTokenPanel/components/ColorsTab/` already existed before this work. The new "Tokens" tab was added alongside it. Always check what pre-exists before creating new panel components.
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
# SPRINT-001: Parallel Development Protocol
|
||||
## Richard & Dishant — Dual Cline Branch Strategy
|
||||
|
||||
**Sprint:** 001
|
||||
**Branch Base:** `cline-dev`
|
||||
**Developer Branches:** `cline-dev-richard` / `cline-dev-dishant`
|
||||
**Date Created:** 2026-02-18
|
||||
**Status:** 🟡 Active
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This sprint runs two independent Cline sessions in parallel — one per developer — each operating on its own branch derived from `cline-dev`. The goal is to maximise throughput across remaining phases while avoiding merge conflicts and keeping both agents informed of each other's progress.
|
||||
|
||||
> **Note on Phase 11:** Phase 11 does not yet have formal task documentation. Dishant should check the dev docs for any phase 11 content before beginning, and raise it for scoping if it is missing.
|
||||
|
||||
---
|
||||
|
||||
## Sprint 1 Task Assignment
|
||||
|
||||
| Developer | Primary Phases | If Time Permits |
|
||||
|-----------|---------------|-----------------|
|
||||
| **Richard** | Phase 9 (Styles Overhaul), Phase 6 (UBA System) | Phase 5 (Multi-Target Deployment) |
|
||||
| **Dishant** | Phase 10 (AI-Powered Development), Phase 11 | Phase 7 (Code Export) |
|
||||
|
||||
**Rationale for split:** Phases 9 and 6 share some UI pattern heritage from Phase 3, making Richard's work self-contained. Phases 10 and 11 build on each other and are cleanly separable from the styles/UBA work, making Dishant's scope independent.
|
||||
|
||||
---
|
||||
|
||||
## Branch Setup
|
||||
|
||||
### One-Time Setup (done by Richard or together)
|
||||
|
||||
```bash
|
||||
# Starting from cline-dev
|
||||
git checkout cline-dev
|
||||
git pull origin cline-dev
|
||||
|
||||
# Create developer branches
|
||||
git checkout -b cline-dev-richard
|
||||
git push origin cline-dev-richard
|
||||
|
||||
git checkout cline-dev
|
||||
git checkout -b cline-dev-dishant
|
||||
git push origin cline-dev-dishant
|
||||
```
|
||||
|
||||
Each developer (and their Cline) then works exclusively on their own branch. **Never commit directly to `cline-dev` during the sprint.**
|
||||
|
||||
---
|
||||
|
||||
## Document Conflict Prevention
|
||||
|
||||
Certain shared documents are high-risk for merge conflicts when both branches touch the same files simultaneously. The following strategy prevents this.
|
||||
|
||||
### High-Risk Shared Documents
|
||||
|
||||
| Document | Risk | Strategy |
|
||||
|----------|------|----------|
|
||||
| `PROGRESS.md` in each phase | Both Clines update task status | See below — use developer-specific update files |
|
||||
| `.clinerules` | Both Clines may refine shared rules | Each Cline appends to its own section only |
|
||||
| Phase `README.md` files | Cross-phase architectural notes | Only the assigned developer's Cline touches these |
|
||||
| Any shared `CHANGELOG.md` | Concurrent entries | Use timestamped entries with developer prefix |
|
||||
|
||||
### PROGRESS.md Conflict Strategy
|
||||
|
||||
Instead of both Clines writing to the same `PROGRESS.md`, each phase gets a companion update file:
|
||||
|
||||
```
|
||||
dev-docs/tasks/phase-9-styles-overhaul/
|
||||
PROGRESS.md ← read-only during sprint (not touched)
|
||||
PROGRESS-richard.md ← Richard's Cline writes here only
|
||||
|
||||
dev-docs/tasks/phase-10-ai-powered-development/
|
||||
PROGRESS.md ← read-only during sprint (not touched)
|
||||
PROGRESS-dishant.md ← Dishant's Cline writes here only
|
||||
```
|
||||
|
||||
**Template for developer-specific PROGRESS file:**
|
||||
|
||||
```markdown
|
||||
# Phase X Progress — [Developer Name]
|
||||
**Branch:** cline-dev-[name]
|
||||
**Last Updated:** YYYY-MM-DD
|
||||
|
||||
## Completed This Sprint
|
||||
|
||||
| Task | Name | Completed | Notes |
|
||||
|------|------|-----------|-------|
|
||||
| TASK-001 | Name | YYYY-MM-DD | |
|
||||
|
||||
## In Progress
|
||||
|
||||
| Task | Name | Started | Blocker |
|
||||
|------|------|---------|---------|
|
||||
|
||||
## Decisions & Learnings
|
||||
|
||||
- [Date] Decision or learning that the other developer should know about
|
||||
```
|
||||
|
||||
After the sprint, both `PROGRESS-richard.md` and `PROGRESS-dishant.md` are merged into the main `PROGRESS.md` by hand before merging branches.
|
||||
|
||||
### .clinerules Strategy
|
||||
|
||||
Add a clearly delimited section to `.clinerules` for each developer. Cline only modifies content inside its own section:
|
||||
|
||||
```
|
||||
# ===== RICHARD (cline-dev-richard) =====
|
||||
[Richard's Cline rules here]
|
||||
# ===== END RICHARD =====
|
||||
|
||||
# ===== DISHANT (cline-dev-dishant) =====
|
||||
[Dishant's Cline rules here]
|
||||
# ===== END DISHANT =====
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cline Workflow: Before Each Task
|
||||
|
||||
At the start of every task session, Cline **must** perform the following cross-branch sync check before writing any code.
|
||||
|
||||
### Pre-Task Protocol
|
||||
|
||||
```bash
|
||||
# 1. Confirm which branch you are on
|
||||
git branch --show-current
|
||||
# Expected: cline-dev-richard OR cline-dev-dishant
|
||||
|
||||
# 2. Fetch all remote branches (no checkout)
|
||||
git fetch origin
|
||||
|
||||
# 3. View commits on the OTHER branch since your last check
|
||||
# Richard checks Dishant's branch:
|
||||
git log origin/cline-dev-dishant --oneline --since="24 hours ago"
|
||||
# Dishant checks Richard's branch:
|
||||
git log origin/cline-dev-richard --oneline --since="24 hours ago"
|
||||
|
||||
# 4. Check the other developer's PROGRESS file for learnings
|
||||
# (read only — no edits to the other developer's files)
|
||||
|
||||
# 5. Evaluate: should you merge or just note?
|
||||
```
|
||||
|
||||
### Merge Decision Criteria
|
||||
|
||||
Cline should recommend a merge from the other branch if **any** of the following are true:
|
||||
|
||||
- The other branch has introduced a shared utility, hook, or component that this branch will also need
|
||||
- The other branch has resolved an infrastructure issue (build errors, TypeScript config, Webpack) that would block this branch too
|
||||
- The other branch has changed a shared type definition or interface
|
||||
- More than 2 tasks have been completed on the other branch since the last sync
|
||||
|
||||
If none of the above apply, Cline should **note the other branch's progress** in its session context and continue without merging. Add a comment to the current task's notes like:
|
||||
|
||||
```
|
||||
// Cross-branch awareness: Dishant completed STRUCT-001 on 2026-02-18.
|
||||
// No merge needed — no shared dependencies with this task.
|
||||
```
|
||||
|
||||
### Performing a Selective Merge
|
||||
|
||||
If a merge is warranted, use cherry-pick for specific commits rather than a full branch merge, to avoid pulling in in-progress work:
|
||||
|
||||
```bash
|
||||
# Cherry-pick a specific commit from the other branch
|
||||
git cherry-pick <commit-hash>
|
||||
|
||||
# Or merge only a specific file from the other branch
|
||||
git checkout origin/cline-dev-dishant -- path/to/specific/file.ts
|
||||
```
|
||||
|
||||
Only do a full branch merge if the other developer explicitly marks a task as "safe to merge" in their PROGRESS file.
|
||||
|
||||
---
|
||||
|
||||
## Cline Workflow: After Each Task
|
||||
|
||||
At the end of every completed task session, Cline **must** push its work so the other agent can see it.
|
||||
|
||||
### Post-Task Protocol
|
||||
|
||||
```bash
|
||||
# 1. Update your developer-specific PROGRESS file
|
||||
# (e.g., PROGRESS-richard.md or PROGRESS-dishant.md)
|
||||
|
||||
# 2. Stage and commit all changes
|
||||
git add -A
|
||||
git commit -m "feat(phase-X): [task name] — [brief description]
|
||||
|
||||
Task: TASK-ID
|
||||
Branch: cline-dev-[name]
|
||||
Cross-branch notes: [anything the other developer should know, or 'none']"
|
||||
|
||||
# 3. Push to your branch
|
||||
git push origin cline-dev-[name]
|
||||
|
||||
# 4. If this task introduced a shared type, utility, or resolved an infrastructure
|
||||
# issue, add a note to your PROGRESS file under 'Decisions & Learnings'
|
||||
# so the other Cline picks it up on their next pre-task check
|
||||
```
|
||||
|
||||
### Commit Message Convention
|
||||
|
||||
```
|
||||
feat(phase-9): STYLE-001 token system foundation
|
||||
|
||||
Task: STYLE-001
|
||||
Branch: cline-dev-richard
|
||||
Cross-branch notes: Introduced shared DesignToken type in noodl-core-ui/src/types/tokens.ts — Dishant may want to cherry-pick if phase 10 UI components need it
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Communication Between Cline Sessions
|
||||
|
||||
Because the two Clines cannot talk directly, all inter-agent communication happens through git commits and the `PROGRESS-[developer].md` files. The conventions below make this reliable.
|
||||
|
||||
### Flagging Something for the Other Developer
|
||||
|
||||
In your PROGRESS file's "Decisions & Learnings" section:
|
||||
|
||||
```markdown
|
||||
## Decisions & Learnings
|
||||
|
||||
- **[2026-02-18] FOR DISHANT:** Resolved EventDispatcher/React 19 incompatibility
|
||||
in phase 9. Fix is in `packages/noodl-editor/src/editor/src/utils/EventDispatcher.ts`.
|
||||
If you hit this in phase 10, cherry-pick commit `abc1234`.
|
||||
```
|
||||
|
||||
### Flagging a Potential Conflict
|
||||
|
||||
If your work is about to touch a file that might also be touched by the other branch, add a warning comment at the top of the file:
|
||||
|
||||
```typescript
|
||||
// SPRINT-001 NOTE (richard, 2026-02-18): Modifying this file on cline-dev-richard.
|
||||
// Dishant — check cross-branch diff before editing this file on cline-dev-dishant.
|
||||
```
|
||||
|
||||
Remove these comments before the final sprint merge.
|
||||
|
||||
---
|
||||
|
||||
## End-of-Sprint Merge Protocol
|
||||
|
||||
When both developers are done (or at end of sprint day):
|
||||
|
||||
```bash
|
||||
# 1. Both developers ensure their branch is fully pushed and PROGRESS files updated
|
||||
|
||||
# 2. On cline-dev, merge Richard's branch first (or whichever finished stable work first)
|
||||
git checkout cline-dev
|
||||
git merge cline-dev-richard --no-ff -m "sprint-001: merge richard's branch (phase 9, 6)"
|
||||
|
||||
# 3. Resolve any conflicts, then merge Dishant's branch
|
||||
git merge cline-dev-dishant --no-ff -m "sprint-001: merge dishant's branch (phase 10, 11)"
|
||||
|
||||
# 4. Consolidate PROGRESS files
|
||||
# Manually merge PROGRESS-richard.md and PROGRESS-dishant.md into each phase's PROGRESS.md
|
||||
# Then delete the developer-specific files
|
||||
|
||||
# 5. Remove any SPRINT-001 NOTE comments left in code
|
||||
|
||||
# 6. Push cline-dev
|
||||
git push origin cline-dev
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference Card for Cline
|
||||
|
||||
> Copy this into Cline's context at the start of each session.
|
||||
|
||||
```
|
||||
SPRINT-001 PARALLEL DEV RULES
|
||||
==============================
|
||||
My branch: cline-dev-[richard|dishant]
|
||||
Other branch: cline-dev-[dishant|richard]
|
||||
|
||||
BEFORE EACH TASK:
|
||||
1. git fetch origin
|
||||
2. git log origin/cline-dev-[other] --oneline --since="24 hours ago"
|
||||
3. Read their PROGRESS-[other].md for learnings
|
||||
4. Decide: cherry-pick needed? (shared util / infra fix / shared types / 2+ tasks)
|
||||
5. If yes: cherry-pick specific commits only
|
||||
6. If no: note awareness and continue
|
||||
|
||||
AFTER EACH TASK:
|
||||
1. Update PROGRESS-[mine].md
|
||||
2. git add -A && git commit -m "feat(phase-X): [task] ..."
|
||||
3. git push origin cline-dev-[mine]
|
||||
4. Flag shared changes in PROGRESS-[mine].md under 'Decisions & Learnings'
|
||||
|
||||
FILES I OWN (richard): phase-9, phase-6, (phase-5 if time)
|
||||
FILES I OWN (dishant): phase-10, phase-11, (phase-7 if time)
|
||||
SHARED FILES: .clinerules (my section only), PROGRESS.md (don't touch — use PROGRESS-[mine].md)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase Reference
|
||||
|
||||
| Phase | Name | Assigned To |
|
||||
|-------|------|-------------|
|
||||
| Phase 5 | Multi-Target Deployment | Richard (if time) |
|
||||
| Phase 6 | UBA System | Richard |
|
||||
| Phase 7 | Code Export | Dishant (if time) |
|
||||
| Phase 9 | Styles Overhaul | Richard |
|
||||
| Phase 10 | AI-Powered Development | Dishant |
|
||||
| Phase 11 | *(check docs — scope TBC)* | Dishant |
|
||||
|
||||
---
|
||||
|
||||
*This document lives in `dev-docs/sprints/SPRINT-001-parallel-dev-protocol.md`*
|
||||
*Update the sprint status header when the sprint closes.*
|
||||
@@ -25,7 +25,7 @@
|
||||
| TASK-001B | Launcher Fixes | 🟢 Complete | All 4 subtasks implemented |
|
||||
| TASK-002 | GitHub Integration | 🟢 Complete | OAuth + basic features done |
|
||||
| TASK-002B | GitHub Advanced Integration | 🟡 In Progress | Part 1: GIT-004A-C done. Part 2: GIT-005-011 docs created |
|
||||
| TASK-002C | GitHub Clone & Connect | 🟡 In Progress | Clone from launcher flow |
|
||||
| TASK-002C | GitHub Clone & Connect | <EFBFBD> Complete | All 3 subtasks done (Clone, Connect, Push/Pull) |
|
||||
| TASK-003 | Shared Component System | 🔴 Not Started | Prefab system refactor |
|
||||
| TASK-004 | AI Project Creation | 🔴 Not Started | AI scaffolding feature |
|
||||
| TASK-005 | Deployment Automation | 🔴 Not Started | Planning docs only, no implementation |
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
# Phase 9: Styles Overhaul - Progress Tracker
|
||||
|
||||
**Last Updated:** 2026-01-07
|
||||
**Last Updated:** 2026-02-18
|
||||
**Overall Status:** 🟡 In Progress
|
||||
|
||||
---
|
||||
|
||||
## Quick Summary
|
||||
|
||||
| Metric | Value |
|
||||
| ----------------- | ----------- |
|
||||
| Total Major Tasks | 7 |
|
||||
| Completed | 0 |
|
||||
| In Progress | 1 (CLEANUP) |
|
||||
| Not Started | 6 |
|
||||
| **Progress** | **~15%** |
|
||||
| Metric | Value |
|
||||
| ----------------- | -------- |
|
||||
| Total Major Tasks | 7 |
|
||||
| Completed | 0 |
|
||||
| In Progress | 3 |
|
||||
| Not Started | 4 |
|
||||
| **Progress** | **~35%** |
|
||||
|
||||
> **Note:** Significant foundational work completed in CLEANUP-SUBTASKS (000A-000G).
|
||||
> Major feature tasks (STYLE-001 to STYLE-005, WIZARD-001) remain not started.
|
||||
> STYLE-001 and STYLE-002 are in progress. STYLE-003 to STYLE-005 and WIZARD-001 not started.
|
||||
|
||||
---
|
||||
|
||||
@@ -24,15 +24,15 @@
|
||||
|
||||
### Major Feature Tasks
|
||||
|
||||
| Task | Name | Status | Notes |
|
||||
| ---------- | ------------------------ | -------------- | ----------------------------- |
|
||||
| STYLE-001 | Token System Enhancement | 🔴 Not Started | Design tokens system |
|
||||
| STYLE-002 | Element Configs/Variants | 🔴 Not Started | Component styling system |
|
||||
| STYLE-003 | Style Presets System | 🔴 Not Started | Pre-built style presets |
|
||||
| STYLE-004 | Property Panel UX | 🔴 Not Started | Improved styling UX |
|
||||
| STYLE-005 | Smart Style Suggestions | 🔴 Not Started | AI-assisted suggestions |
|
||||
| WIZARD-001 | Project Creation Wizard | 🔴 Not Started | Guided project setup |
|
||||
| CLEANUP-\* | Legacy Color Cleanup | 🟡 In Progress | 7/8 subtasks complete (87.5%) |
|
||||
| Task | Name | Status | Notes |
|
||||
| ---------- | ------------------------ | -------------- | ----------------------------------------------- |
|
||||
| STYLE-001 | Token System Enhancement | 🟡 In Progress | Phase 1+2 done; Phase 3+4 TBD |
|
||||
| STYLE-002 | Element Configs/Variants | 🟡 In Progress | Phase 1+2+3 done; prop panel wiring → STYLE-004 |
|
||||
| STYLE-003 | Style Presets System | ✅ Complete | 5 presets, PresetSelector UI, launcher wiring |
|
||||
| STYLE-004 | Property Panel UX | 🟡 In Progress | Phase 1 done (variant+size picker wired) |
|
||||
| STYLE-005 | Smart Style Suggestions | 🔴 Not Started | AI-assisted suggestions |
|
||||
| WIZARD-001 | Project Creation Wizard | 🔴 Not Started | Guided project setup |
|
||||
| CLEANUP-\* | Legacy Color Cleanup | 🟡 In Progress | 7/8 subtasks complete (87.5%) |
|
||||
|
||||
---
|
||||
|
||||
@@ -65,6 +65,27 @@ Foundation work to remove hardcoded colors and establish token infrastructure.
|
||||
|
||||
---
|
||||
|
||||
## STYLE-001 Progress
|
||||
|
||||
| Phase | Description | Status |
|
||||
| ------- | -------------------------------- | -------------- |
|
||||
| Phase 1 | Token Data Structure | 🟢 Complete |
|
||||
| Phase 2 | Context & Panel Enhancement | 🟢 Complete |
|
||||
| Phase 3 | TokenPicker Component | 🔴 Not Started |
|
||||
| Phase 4 | CSS Variable Injection (preview) | 🔴 Not Started |
|
||||
|
||||
## STYLE-002 Progress
|
||||
|
||||
| Phase | Description | Status |
|
||||
| ------- | ---------------------------------------- | ----------------------- |
|
||||
| Phase 1 | Config system (types, registry, configs) | 🟢 Complete |
|
||||
| Phase 2 | Node creation hook + Text bug fix | 🟢 Complete |
|
||||
| Phase 3 | VariantSelector UI component | 🟢 Complete |
|
||||
| Phase 4 | Property panel wiring | 🔴 Deferred → STYLE-004 |
|
||||
| Phase 5 | State styles (hover/focus/disabled) | 🔴 Deferred → STYLE-004 |
|
||||
|
||||
---
|
||||
|
||||
## Status Legend
|
||||
|
||||
- 🔴 **Not Started** - Work has not begun
|
||||
@@ -77,6 +98,8 @@ Foundation work to remove hardcoded colors and establish token infrastructure.
|
||||
|
||||
| Date | Update |
|
||||
| ---------- | -------------------------------------------------------------- |
|
||||
| 2026-02-18 | STYLE-002 Phase 1+2+3: ElementConfigs system + VariantSelector |
|
||||
| 2026-02-18 | STYLE-001 Phase 1+2: Token system + DesignTokenPanel |
|
||||
| 2026-01-07 | Audit: Updated PROGRESS.md to reflect actual completion status |
|
||||
| 2025-12-31 | Completed TASK-000F (Buttons) and TASK-000G (Dialogs/Panels) |
|
||||
| 2025-12-30 | Completed TASK-000A through TASK-000E (Token/Color foundation) |
|
||||
@@ -106,11 +129,18 @@ The foundational cleanup work (000A-000G) has established:
|
||||
- Typography and spacing token system
|
||||
- Modern visual polish on core UI components
|
||||
|
||||
STYLE-001 (Phases 1+2): Full Tailwind-inspired token system with DesignTokenPanel.
|
||||
|
||||
STYLE-002 (Phases 1+2+3): ElementConfig system for default node styling on creation,
|
||||
VariantSelector UI component, Text node flex bug fix.
|
||||
|
||||
### What's Remaining:
|
||||
|
||||
- **TASK-000H:** Final polish on Migration Wizard
|
||||
- **STYLE-001 to STYLE-005:** Major feature work (enhanced token system, element configs, presets, property panel UX, AI suggestions)
|
||||
- **STYLE-001 Phase 3+4:** TokenPicker component, CSS injection into preview iframe
|
||||
- **STYLE-002 Phase 4+5:** Property panel wiring, state style application
|
||||
- **STYLE-003 to STYLE-005:** Style presets, property panel UX, AI suggestions
|
||||
- **WIZARD-001:** Project creation wizard
|
||||
|
||||
See CLEANUP-SUBTASKS/ folder for detailed changelogs of completed work.
|
||||
See STYLE-\* folders for README specs of upcoming feature work.
|
||||
See STYLE-\* folders for README specs and changelogs.
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
# STYLE-001: Token System Enhancement - Changelog
|
||||
|
||||
## 2026-02-18 - Phase 1 & 2 Complete
|
||||
|
||||
### Phase 1: Token Data Structure
|
||||
|
||||
#### New Files
|
||||
|
||||
**`packages/noodl-editor/src/editor/src/models/StyleTokensModel/`**
|
||||
|
||||
- **`TokenCategories.ts`** — TypeScript types for the design token system:
|
||||
|
||||
- `TokenCategory` union type (13 categories: color-semantic, color-palette, spacing, typography-_, border-_, shadow, animation-\*)
|
||||
- `StyleToken`, `StyleTokenRecord`, `StyleTokensData` interfaces
|
||||
- `TOKEN_CATEGORIES` metadata map (label, description, group)
|
||||
- `TOKEN_CATEGORY_GROUPS` ordered display groups
|
||||
|
||||
- **`DefaultTokens.ts`** — Full Tailwind-inspired default token set:
|
||||
|
||||
- ~24 semantic colors (primary, secondary, destructive, muted, accent, surface, border, ring)
|
||||
- ~90 palette colors (gray, blue, red, green, amber, purple at 10 shades each)
|
||||
- ~32 spacing tokens (0–128px numeric scale + semantic aliases xs/sm/md/lg/xl/2xl/3xl)
|
||||
- 10 font sizes, 9 font weights, 6 line heights, 6 letter spacings, 3 font families
|
||||
- 8 border radii, 5 border widths
|
||||
- 7 shadow scales
|
||||
- 8 animation durations + 5 easing functions
|
||||
- **Only overrides stored in project.json** — defaults never persisted
|
||||
|
||||
- **`TokenResolver.ts`** — CSS `var()` reference resolution:
|
||||
|
||||
- Resolves chained references (e.g. `--space-xs` → `var(--space-1)` → `4px`)
|
||||
- LRU-style cache with targeted invalidation
|
||||
- `generateCss()` for `:root { ... }` CSS block generation
|
||||
- Max depth protection against circular references
|
||||
|
||||
- **`StyleTokensModel.ts`** — Main model class:
|
||||
|
||||
- Extends `Model` (EventDispatcher-compatible)
|
||||
- `getTokens()`, `getTokensByCategory()`, `getTokensByGroup()`, `getTokensGrouped()`
|
||||
- `setToken()`, `addCustomToken()`, `deleteCustomToken()`, `resetAllToDefaults()` — all undo-aware
|
||||
- `generateCss()`, `exportCustomTokensJson()`, `importCustomTokensJson()`
|
||||
- Persists only custom overrides under `designTokens` metadata key
|
||||
- Auto-reloads on `ProjectModel.importComplete` / `ProjectModel.instanceHasChanged`
|
||||
- Properly uses `new UndoActionGroup(...)` for undo stack integration
|
||||
|
||||
- **`index.ts`** — Clean public exports
|
||||
|
||||
### Phase 2: Context & Panel Enhancement
|
||||
|
||||
#### Modified
|
||||
|
||||
- **`ProjectDesignTokenContext.tsx`** — Enhanced with:
|
||||
- `designTokens: StyleTokenRecord[]` — live token array, re-renders on `tokensChanged`
|
||||
- `styleTokensModel: StyleTokensModel | null` — model instance for direct interaction
|
||||
- Uses `useEventListener` hook (correct pattern, no direct `.on()`)
|
||||
- Backward compatible — existing `staticColors`, `dynamicColors`, `textStyles` unchanged
|
||||
|
||||
#### New
|
||||
|
||||
- **`DesignTokenPanel.tsx`** — Replaced basic 2-tab panel with proper structure:
|
||||
- New "Tokens" tab (primary) + legacy "Colors" tab preserved
|
||||
- **`components/DesignTokensTab/`** — Tokens tab:
|
||||
|
||||
- Groups all tokens by display category (Colors, Spacing, Typography, Borders, Effects, Animation)
|
||||
- Collapsible sections per group via `CollapsableSection`
|
||||
- Shows "N overrides" banner with "Reset all" when tokens are customised
|
||||
|
||||
- **`components/TokenCategorySection/`** — Per-group token list:
|
||||
- Color swatches for color tokens
|
||||
- Spacing bars for spacing tokens (proportional width)
|
||||
- Border radius preview boxes
|
||||
- Shadow preview boxes
|
||||
- Font size "Aa" previews
|
||||
- Override indicator (highlighted name) with reset button (↺) on hover
|
||||
- SCSS using design tokens throughout (no hardcoded values)
|
||||
|
||||
---
|
||||
|
||||
## What's Still Pending
|
||||
|
||||
### Phase 3: TokenPicker Component (STYLE-001)
|
||||
|
||||
- Reusable `<TokenPicker>` dropdown for use in property panels
|
||||
- Currently `onTokenChange` prop exists but inline editing not yet wired
|
||||
- Will be built as part of STYLE-002/STYLE-004 integration
|
||||
|
||||
### Phase 4: CSS Variable Injection (STYLE-001)
|
||||
|
||||
- `StyleTokensModel.generateCss()` is ready
|
||||
- Need to inject into preview iframe when tokens change
|
||||
- Requires investigation of preview server injection point in `noodl-viewer-react`
|
||||
|
||||
---
|
||||
|
||||
_Started: 2026-02-18_
|
||||
@@ -0,0 +1,113 @@
|
||||
# STYLE-002: Element Configs & Variants - Changelog
|
||||
|
||||
## 2026-02-18 - Phase 1, 2 & 3 Complete
|
||||
|
||||
---
|
||||
|
||||
### Phase 1: Config System Architecture
|
||||
|
||||
#### New Files
|
||||
|
||||
**`packages/noodl-editor/src/editor/src/models/ElementConfigs/`**
|
||||
|
||||
- **`ElementConfigTypes.ts`** — TypeScript interfaces for the config system:
|
||||
|
||||
- `StateStyles` — hover/active/focus/disabled/placeholder style maps
|
||||
- `VariantConfig` — base styles + optional `states` object
|
||||
- `SizePresets` — named size override maps
|
||||
- `ElementConfig` — full config for a node type (defaults + sizes + variants)
|
||||
- `ResolvedVariant` — base styles + states after stripping the `states` key
|
||||
|
||||
- **`ElementConfigRegistry.ts`** — Singleton registry:
|
||||
|
||||
- `register(config)` — add a config
|
||||
- `get(nodeType)` / `has(nodeType)` / `getAll()` — lookup
|
||||
- `getVariantNames(nodeType)` — returns `string[]` of available variant names
|
||||
- `resolveVariant(nodeType, variantName)` → `ResolvedVariant | undefined`
|
||||
- `applyDefaults(node, typeName)` — stamps defaults + initial variant onto a node's `parameters`
|
||||
- `applyVariant(node, typeName, variantName)` — stamps a variant's base styles + updates `_variant` marker
|
||||
- All built-in configs auto-registered on module load
|
||||
|
||||
- **`configs/ButtonConfig.ts`** — Button (`net.noodl.controls.button`):
|
||||
|
||||
- Variants: primary, secondary, outline, ghost, destructive, link
|
||||
- Size presets: sm, md, lg, xl
|
||||
- Interaction states: hover, active, disabled per variant
|
||||
|
||||
- **`configs/GroupConfig.ts`** — Group (`net.noodl.visual.group`):
|
||||
|
||||
- Variants: default, card, section, inset, flex-row, flex-col, centered
|
||||
|
||||
- **`configs/TextConfig.ts`** — Text node:
|
||||
|
||||
- **BUG FIX**: defaults now include `width: auto`, `flexShrink: 1`, `flexGrow: 0`, `minWidth: 0`
|
||||
(previously: implicit `width: 100%` caused Text elements to push siblings off-screen in row layouts)
|
||||
- Variants: body, heading-1 through heading-6, muted, label, small, code, lead, blockquote
|
||||
|
||||
- **`configs/TextInputConfig.ts`** — TextInput (`net.noodl.controls.textinput`):
|
||||
|
||||
- Variants: default (with focus ring), error
|
||||
|
||||
- **`configs/CheckboxConfig.ts`** — Checkbox (`net.noodl.controls.checkbox`):
|
||||
|
||||
- Variant: default
|
||||
|
||||
- **`configs/index.ts`** — barrel export
|
||||
- **`index.ts`** — public module export
|
||||
|
||||
---
|
||||
|
||||
### Phase 2: Node Creation Integration
|
||||
|
||||
#### Modified
|
||||
|
||||
- **`views/NodePicker/NodePicker.utils.ts`** — Added `ElementConfigRegistry.applyDefaults(node, type.name)` call in `createNodeFunction`, immediately after `NodeGraphNode.fromJSON(...)`. This is the **single entry point for all user-initiated node creation** — no changes needed to NodeGraphModel or project loading paths.
|
||||
|
||||
- Safe for existing projects: defaults only stamp properties not already set
|
||||
- No-op for node types without a registered config
|
||||
- Works for root nodes, child nodes, and auto-attach-to-root paths
|
||||
|
||||
---
|
||||
|
||||
### Phase 3: VariantSelector UI Component
|
||||
|
||||
#### New Files
|
||||
|
||||
**`packages/noodl-core-ui/src/components/inputs/VariantSelector/`**
|
||||
|
||||
- **`VariantSelector.tsx`** — Controlled dropdown component:
|
||||
|
||||
- Props: `variants: string[]`, `currentVariant: string | undefined`, `onVariantChange: (name) => void`, `disabled?`, `label?`
|
||||
- Keyboard accessible (Escape to close)
|
||||
- Closes on outside click
|
||||
- Formats variant names for display (`heading-1` → `Heading 1`)
|
||||
- Active variant shown with checkmark + primary color highlight
|
||||
|
||||
- **`VariantSelector.module.scss`** — Styled with design tokens exclusively (no hardcoded colors)
|
||||
|
||||
- **`index.ts`** — barrel export
|
||||
|
||||
---
|
||||
|
||||
### What's Pending
|
||||
|
||||
#### Property Panel Integration (STYLE-004)
|
||||
|
||||
Wiring `VariantSection` into the property editor requires understanding the legacy `TypeView.js` / `propertyeditor.ts` system. The `VariantSelector` component is built and ready — integration is scoped to STYLE-004 which covers Property Panel UX overhaul.
|
||||
|
||||
#### State Styles (Phase 4)
|
||||
|
||||
`StateStyles` (hover, focus, active, disabled) are defined in all configs and stored in `ResolvedVariant.states`. Applying them at runtime requires investigation of the existing visual states system in `noodl-viewer-react`. Scoped to STYLE-004.
|
||||
|
||||
---
|
||||
|
||||
## Key Discoveries
|
||||
|
||||
- **NodePicker.utils.ts is the sole user-initiated node creation path** — all `addRoot`/`addChild` calls with `{ undo: true, label: 'create' }` flow through `createNodeFunction`. No need to touch NodeGraphModel.
|
||||
- **NodeGraphNode.parameters is a plain object** — not getter/setter based. The registry uses direct `node.parameters[key]` access.
|
||||
- **Loading vs creation differentiation**: when loading from JSON, `NodeGraphNode.fromJSON` pre-populates parameters before `addRoot` is called. The `applyDefaults` guard (`if param === undefined`) ensures existing project nodes aren't affected.
|
||||
- **Text node width issue**: the `defaultCss` in `text.js` only has `{ position: 'relative', display: 'flex' }`. The width issue comes from dimension port defaults. Stamping `width: auto` + flex props via `applyDefaults` fixes it for newly created nodes.
|
||||
|
||||
---
|
||||
|
||||
_Started: 2026-02-18_
|
||||
@@ -0,0 +1,66 @@
|
||||
# STYLE-003: Style Presets — CHANGELOG
|
||||
|
||||
## 2026-02-18 — Implementation Complete
|
||||
|
||||
### New files created
|
||||
|
||||
**Data layer (noodl-editor)**
|
||||
|
||||
- `models/StylePresets/StylePresetTypes.ts` — `StylePreset` and `PresetPreview` interfaces
|
||||
- `models/StylePresets/presets/ModernPreset.ts` — Default (clean blue, 8px radius, soft shadows)
|
||||
- `models/StylePresets/presets/MinimalPreset.ts` — Monochromatic, 2–4px radius, no shadows
|
||||
- `models/StylePresets/presets/PlayfulPreset.ts` — Purple/pink, very rounded (16px), tinted shadows
|
||||
- `models/StylePresets/presets/EnterprisePreset.ts` — Dark navy, conservative 4px radius, barely-there shadows
|
||||
- `models/StylePresets/presets/SoftPreset.ts` — Indigo, 12px radius, ultra-light shadows
|
||||
- `models/StylePresets/presets/index.ts` — barrel
|
||||
- `models/StylePresets/StylePresetsModel.ts` — `getAllPresets`, `getPreset`, `getDefaultPreset`, `setPendingPresetId`, `consumePendingPreset`
|
||||
- `models/StylePresets/index.ts` — public surface
|
||||
|
||||
**UI layer (noodl-core-ui)**
|
||||
|
||||
- `components/StylePresets/PresetCard.tsx` — Mini mockup card with primary swatch, text lines, surface strip
|
||||
- `components/StylePresets/PresetCard.module.scss` — Card styles with selection ring
|
||||
- `components/StylePresets/PresetSelector.tsx` — Horizontal grid + description below selected
|
||||
- `components/StylePresets/PresetSelector.module.scss`
|
||||
- `components/StylePresets/index.ts` — barrel
|
||||
|
||||
### Modified files
|
||||
|
||||
**`models/StyleTokensModel/StyleTokensModel.ts`**
|
||||
|
||||
- Added `applyPreset(tokens)` public method — bulk-sets tokens without undo
|
||||
- Added `_applyAndClearPendingPreset()` private method — called from `_bindListeners` reload path
|
||||
- Added `consumePendingPreset` import and call in the `reload` closure
|
||||
|
||||
**`preview/launcher/Launcher/components/CreateProjectModal/CreateProjectModal.tsx`**
|
||||
|
||||
- Added `presets?: PresetDisplayInfo[]` prop
|
||||
- Added `selectedPresetId` local state (default `'modern'`)
|
||||
- Renders `<PresetSelector>` when presets provided
|
||||
- Extended `onConfirm` signature to include `presetId: string`
|
||||
|
||||
**`pages/ProjectsPage/ProjectsPage.tsx`**
|
||||
|
||||
- Added `getAllPresets`, `setPendingPresetId` imports
|
||||
- Added `STYLE_PRESETS` module-level constant
|
||||
- Updated `handleCreateProjectConfirm(name, location, presetId)` to call `setPendingPresetId(presetId)`
|
||||
- Passes `presets={STYLE_PRESETS}` to `<CreateProjectModal>`
|
||||
- Error path clears pending preset via `setPendingPresetId(null)`
|
||||
|
||||
### Architecture — pending preset flow
|
||||
|
||||
```
|
||||
User picks preset → CreateProjectModal.onConfirm(name, loc, presetId)
|
||||
→ ProjectsPage.handleCreateProjectConfirm
|
||||
→ setPendingPresetId(presetId) // stored in module-level var
|
||||
→ LocalProjectsModel.newProject(...)
|
||||
→ route to editor
|
||||
→ StyleTokensModel._bindListeners reload fires (ProjectModel.instanceHasChanged)
|
||||
→ _applyAndClearPendingPreset()
|
||||
→ consumePendingPreset() reads + clears _pendingPresetId
|
||||
→ applyPreset(preset.tokens)
|
||||
→ setToken() x N → _store() → ProjectModel.instance.setMetaData('designTokens', ...)
|
||||
→ tokens persisted to project.json
|
||||
```
|
||||
|
||||
Modern preset has `tokens: {}` so it is a no-op (defaults already apply).
|
||||
@@ -0,0 +1,115 @@
|
||||
# STYLE-004: Property Panel UX — Changelog
|
||||
|
||||
## Session: 2026-02-18
|
||||
|
||||
### Summary
|
||||
|
||||
Completed STYLE-004 Phase 1: Property panel wiring for the ElementConfig variant and size system.
|
||||
This closes the STYLE-002 Phase 4 + Phase 5 deferred items.
|
||||
|
||||
---
|
||||
|
||||
### New Files
|
||||
|
||||
#### `noodl-core-ui/src/components/propertyeditor/SizePicker/`
|
||||
|
||||
- **`SizePicker.tsx`** — Segmented control component for selecting a size preset (sm / md / lg / xl).
|
||||
Renders only the sizes defined in the node's ElementConfig. All styling via design tokens.
|
||||
- **`SizePicker.module.scss`** — Styles for the segmented control. No hardcoded colors.
|
||||
- **`index.ts`** — Barrel export.
|
||||
|
||||
#### `noodl-core-ui/src/components/propertyeditor/ElementStyleSection/`
|
||||
|
||||
- **`ElementStyleSection.tsx`** — Property panel section that combines VariantSelector and SizePicker.
|
||||
Renders at the top of the panel for any node with an ElementConfig registered.
|
||||
Props-driven and dumb — the legacy `propertyeditor.ts` manages undo via callbacks.
|
||||
- **`ElementStyleSection.module.scss`** — Section layout and header styling. Design tokens throughout.
|
||||
- **`index.ts`** — Barrel export.
|
||||
|
||||
---
|
||||
|
||||
### Modified Files
|
||||
|
||||
#### `ElementConfigRegistry.ts`
|
||||
|
||||
Added two new public API methods:
|
||||
|
||||
```typescript
|
||||
// Apply a named size preset's styles to a node (stamps CSS properties + _size marker)
|
||||
ElementConfigRegistry.applySize(node, typeName, sizeName)
|
||||
|
||||
// Return the size names defined in the config, in definition order
|
||||
ElementConfigRegistry.getSizeNames(nodeType) → string[]
|
||||
```
|
||||
|
||||
#### `propertyeditor/propertyeditor.html`
|
||||
|
||||
Added `<div class="element-style-section"></div>` slot between `.variants` and `.visual-states`.
|
||||
|
||||
#### `propertyeditor/propertyeditor.ts`
|
||||
|
||||
- Imported `ElementStyleSection` from `@noodl-core-ui/components/propertyeditor/ElementStyleSection`
|
||||
- Imported `ElementConfigRegistry`
|
||||
- Added fields: `elementStyleRoot: Root | null`, `_elementStyleGroup: Record<string, never>`
|
||||
- Added methods:
|
||||
- `renderElementStyleSection()` — mounts/updates the React root; reads `_variant` and `_size` from
|
||||
`this.model.parameters`; guards on `ElementConfigRegistry.has(typeName)`
|
||||
- `onElementVariantChange(variantName)` — resolves variant styles, batches into `UndoActionGroup`,
|
||||
calls `this.model.setParameter()` for each property, pushes to `UndoQueue`, then re-renders
|
||||
- `onElementSizeChange(sizeName)` — same pattern for size preset styles
|
||||
- Updated `render()`: subscribes to `['modelParameterUndo', 'modelParameterRedo']` to re-render
|
||||
the section after undo/redo; calls `renderElementStyleSection()`
|
||||
|
||||
---
|
||||
|
||||
### Test File
|
||||
|
||||
**`tests/models/ElementConfigRegistry.test.ts`**
|
||||
|
||||
Covers:
|
||||
|
||||
- `applyVariant` — stamps styles, excludes `states`, handles unknown types/variants
|
||||
- `applySize` — stamps size presets, handles no-sizes configs, unknown sizes
|
||||
- `getSizeNames` — returns correct keys in order, handles missing sizes
|
||||
- `getVariantNames` — returns all variant names
|
||||
- `resolveVariant` — returns baseStyles + states, excludes `states` from baseStyles
|
||||
- `applyDefaults` — stamps defaults + default variant, does not overwrite pre-existing values
|
||||
|
||||
---
|
||||
|
||||
### Architecture Notes
|
||||
|
||||
**Why callbacks instead of direct undo in the component:**
|
||||
The `ElementStyleSection` is intentionally dumb. Undo grouping requires `UndoActionGroup` +
|
||||
`UndoQueue` — both are editor-specific and not part of `noodl-core-ui`. Keeping undo logic in
|
||||
`propertyeditor.ts` lets the React component stay portable.
|
||||
|
||||
**Why \_variant and \_size in parameters:**
|
||||
These are special marker keys that don't map to real CSS properties. They allow the property panel
|
||||
to re-render the picker with the correct selection state across sessions. `applyDefaults` already
|
||||
persisted `_variant`; `_size` is the same pattern added by STYLE-004.
|
||||
|
||||
**Undo/redo re-render:**
|
||||
`propertyeditor.ts` subscribes to `['modelParameterUndo', 'modelParameterRedo']` on the node model
|
||||
using a stable `_elementStyleGroup` object. This ensures the picker UI stays in sync after undo.
|
||||
|
||||
---
|
||||
|
||||
### What's NOT done (explicitly deferred)
|
||||
|
||||
- **Full panel restructure** (ContentSection, LayoutSection, AdvancedSection, etc.) — future work
|
||||
- **TokenOverrideRow / token picker** — blocked on STYLE-001 Phase 3 (TokenPicker component)
|
||||
- **Override indicators** (badge showing "2 custom values") — future iteration
|
||||
- **Canvas indicator** — optional, deferred
|
||||
|
||||
---
|
||||
|
||||
### Success Criteria Status
|
||||
|
||||
- [x] VariantSelector appears in property panel for registered element types (Button, Text, Group, TextInput, Checkbox)
|
||||
- [x] Variant change applies correct styles with full undo support
|
||||
- [x] SizePicker appears for types with sizes defined (Button)
|
||||
- [x] Size change applies correct preset styles with full undo support
|
||||
- [x] Undo/redo restores picker state correctly
|
||||
- [x] Non-registered node types (logic nodes) show no ElementStyleSection
|
||||
- [x] Unit tests pass for all registry operations
|
||||
Reference in New Issue
Block a user