Components 4, and the panel vocabulary Studio's canvas needs - #25
Merged
Conversation
Components 4 owns its own markup, styling and types and drops PrimeReact from underneath, so the packages built on it stop carrying PrimeReact and the ones targeting PrimeReact keep it: - scene.components and scene.blueprint.components take ^4.1.1. - scene.components drops PrimeReact entirely. Its one PrimeReactProvider was in a spec, needed only because Components 3's tooltip bottomed out in a PrimeReact component; Components 4's is its own. primeicons stays as a devDependency because the stories demonstrate the consumer-owned icon-font string Components 4 still accepts. - scene.blueprint.components keeps the PrimeReact peers. It composes blueprint.default's shell, which reaches for PrimeReact directly in five places, and CratisComponentsProvider no longer supplies PrimeReactProvider on its behalf - so its Storybook preview now supplies both providers explicitly rather than relying on hoisting. - scene.primereact and scene.blueprint.default are unchanged: they target PrimeReact deliberately. SceneTooltip wraps its slot in a single element. Components 4 takes one focusable trigger, which it clones to attach its own part attributes, and a Scene slot is a list. The three documented codemods scanned 543 files and changed none - Scene already imported explicit subpaths throughout. Verified: 8 JavaScript workspaces build, 888 specs pass, lint clean, all five Storybooks build, and .NET is 5 projects / 0 warnings / 37 specs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Studio's prototype canvas models arrangement with a WPF-style panel set that Scene had no equivalent for: a screen could say what an element is, but not that five of them sit in a grid. Scene owns the object model, so the vocabulary belongs here. Added to Cratis.Scene.Model and mirrored in @cratis/scene.model: - Canvas, StackPanel, DockPanel, WrapPanel and Grid, on the existing Panel base. - RowDefinition and ColumnDefinition, with GridLength and GridUnitType. - Orientation and Dock. Kept pure, the way Screenplay is. No attributes, no discriminators, no serialization, and no package dependency - Cratis.Scene.Model still has none. Where Studio's model reaches for a ConceptAs<double> these use double, and where it uses a Dimension sentinel for "unbounded" these use double.PositiveInfinity rather than double.MaxValue. Attached properties stay in the Properties bag the model already has - Canvas.Left/Top/Right/Bottom, Grid.Row/Column/RowSpan/ColumnSpan and Dock - because a model with no attached properties of its own is the right place to keep carrying them that way. These render through the existing structural walk: every one satisfies isPanel, so renderElement already reaches them. What they do not yet do is arrange - honouring orientation, spacing, grid tracks and docking is the layout engine's job (#4), which is why this change is vocabulary rather than behavior. Both shape specs cover the new surface: the manifest gains 8 types and 3 enums, and the C# spec asserts the model declares exactly those. Verified: JS build clean, 898 specs pass (up from 888), lint clean, .NET 5 projects / 0 errors / 0 warnings with 37 specs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The panel vocabulary said what an arrangement is; nothing turned it into one. `renderPanel` emitted a bare `div`, so a grid and a stack looked the same. Scene#4 settled which arrangement applies for a size class, not what it looks like - that is the renderer's half, and this is it. - `panelKind` tells the concrete panels apart the way `elementKind` already tells the element kinds apart: by the property each one alone declares, since the model carries no discriminator. A plain Panel matches none of them, which is a real case - a panel that says nothing about arrangement is a grouping. - `panelLayout` maps them to CSS. Grid tracks become `grid-template-*` with star as `fr`, auto as `auto`, absolute as pixels, and a bounded track as `minmax`. Stack and wrap become flex along their orientation. Dock becomes a column whose last child can take what is left. Per-child placement - a grid cell, a docked edge, a wrap panel's item size - is applied by wrapping that child, which the renderer can do because the rendered children arrive in `element.children` order. The mapping lives in Scene.React rather than the model or the engine, because it is the answer for one platform; a native or desktop renderer answers it with its own primitives. Canvas is removed. Absolute placement is already the layout model's job - FreeformArrangement carries an ElementPlacement per element *per size class*, which says strictly more than attached Left/Top coordinates can - and a Canvas panel declared no properties of its own, so nothing could have recognized it at render time either. The rationale sits next to the panels that remain. Verified: 922 specs pass (up from 898), build and lint clean, five Storybooks build, .NET 5 projects / 0 warnings / 37 specs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Added
The panel vocabulary a canvas is drawn in —
Canvas,StackPanel,DockPanel,WrapPanelandGridon the existingPanelbase, withRowDefinition,ColumnDefinition,GridLength,GridUnitType,OrientationandDock. Studio's prototype canvas models arrangement this way and Scene had no equivalent: a screen could say what an element is, but not that five of them sit in a grid.Kept pure, the way Screenplay is — no attributes, no discriminators, no serialization, and
Cratis.Scene.Modelstill has no package dependencies. Attached properties stay in thePropertiesbag the model already has (Canvas.Left,Grid.Row,Dock), because a model with no attached properties of its own is the right place to keep carrying them that way.These render through the existing structural walk — every one satisfies
isPanel, sorenderElementalready reaches them. What they do not yet do is arrange: honouring orientation, spacing, grid tracks and docking is the layout engine's job (Layout engine:flowandfreeformarrangement rendering #4). This change is vocabulary, not behavior.Changed
@cratis/components4. Components 4 owns its own markup, styling and types and no longer sits on PrimeReact, soscene.componentsandscene.blueprint.componentstake^4.1.1and their peer range moves with it — a breaking change for anyone consuming those two packages.scene.componentsno longer depends on PrimeReact at all. Its onePrimeReactProviderwas in a spec, needed only because Components 3's tooltip bottomed out in a PrimeReact component; Components 4 owns its own.primeiconsstays as a Storybook-only devDependency, because the stories demonstrate the consumer-owned icon-font class string that Components 4'sIconstill accepts.scene.blueprint.componentskeeps its PrimeReact peers, and now supplies the provider itself. It composesblueprint.default's shell, which reaches for PrimeReact directly in five places. Until Components 3 that provider came for free becauseCratisComponentsProviderwrappedPrimeReactProvider; under Components 4 it does not, so the Storybook preview declares both providers rather than relying on hoisting.scene.primereactandscene.blueprint.defaultare unchanged — they target PrimeReact deliberately.Fixed
SceneTooltippassed a slot straight toTooltip. Components 4 takes one focusable trigger element, which it clones to attach its own part attributes, and a Scene slot is a list — so it now wraps the slot in a single element rather than failing to type.Both shape specs cover the new surface:
scene-model-shape.jsongains 8 types and 3 enums, and the C# spec asserts the model declares exactly those.The three documented Components codemods scanned 543 files and changed none — Scene already imported explicit subpaths throughout. Note for anyone following the migration guide: they do not run on the current migrator at all.
@cratis/components.migrator@4.1.1fails its own compatibility preflight because the bundled manifest still pins the migrator at4.0.0(Cratis/Components#232, which predicted exactly this recurrence). Pinning@cratis/components.migrator@4.0.0works.Verified: 8 JavaScript workspaces build, 898 specs pass, lint clean, all five Storybooks build, and .NET is 5 projects / 0 errors / 0 warnings with 37 specs passing.
🤖 Generated with Claude Code