Added sprint protocol

This commit is contained in:
Richard Osborne
2026-02-18 15:59:52 +01:00
parent bf07f1cb4a
commit 297dfe0269
249 changed files with 638915 additions and 250 deletions

View File

@@ -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.

View File

@@ -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 (0128px 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_

View File

@@ -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_

View File

@@ -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, 24px 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).

View File

@@ -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