4.8 KiB
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 legacypropertyeditor.tsmanages 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:
// 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
ElementStyleSectionfrom@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_variantand_sizefromthis.model.parameters; guards onElementConfigRegistry.has(typeName)onElementVariantChange(variantName)— resolves variant styles, batches intoUndoActionGroup, callsthis.model.setParameter()for each property, pushes toUndoQueue, then re-rendersonElementSizeChange(sizeName)— same pattern for size preset styles
- Updated
render(): subscribes to['modelParameterUndo', 'modelParameterRedo']to re-render the section after undo/redo; callsrenderElementStyleSection()
Test File
tests/models/ElementConfigRegistry.test.ts
Covers:
applyVariant— stamps styles, excludesstates, handles unknown types/variantsapplySize— stamps size presets, handles no-sizes configs, unknown sizesgetSizeNames— returns correct keys in order, handles missing sizesgetVariantNames— returns all variant namesresolveVariant— returns baseStyles + states, excludesstatesfrom baseStylesapplyDefaults— 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
- VariantSelector appears in property panel for registered element types (Button, Text, Group, TextInput, Checkbox)
- Variant change applies correct styles with full undo support
- SizePicker appears for types with sizes defined (Button)
- Size change applies correct preset styles with full undo support
- Undo/redo restores picker state correctly
- Non-registered node types (logic nodes) show no ElementStyleSection
- Unit tests pass for all registry operations