Context
Screenplay's screen/layout constructs are (mostly) platform-agnostic, but
nothing in the language currently expresses which platforms/sizes an app
targets, or which component package(s) (PrimeReact, internal widget
libraries, etc.) a build should resolve widget names against. Needed to
support web/mobile/desktop from one model, and to let vendor + internal
packages layer predictably.
Proposal
ui profile Desktop
target platform web
target size expanded
packages
core // built-in vocabulary: button, table, form, title...
PrimeReact
Internal.Widgets // company package, layered on top
ui profile Mobile
target platform ios, android
target size compact
target size uses named size classes (compact / regular /
expanded, Apple/Material-style) as the primary vocabulary rather than
raw pixel breakpoints — size classes transfer across platforms (a
narrow browser window and a compact phone are "the same" class); raw
breakpoints are CSS-flavored and don't mean anything on native. Raw
breakpoints could exist as a web-only escape hatch, not the default.
- A
screen never declares which profile it targets — profile selection
is a build/Stage concern. The same screen resolves against different
package chains per build, keeping Level 1/2 genuinely portable.
Component name resolution
Same mechanic as existing name resolution (Queue.All vs. bare All):
screen InvoiceDetails
section summary
button "Cancel" // core — always resolves
section trend
Internal.Widgets.TrendChart bind data // not in core, must qualify
core is the built-in, always-present package/fallback.
- Package declaration order in
packages is override priority — a later
package's Button shadows an earlier one's on name collision, so
"extensions on top of a base" only need to define what they override.
- A name matching two active packages equally well produces the same
class of warning as an ambiguous query (named candidates, not a silent
pick) — no new diagnostic category, reuse the existing one.
Open questions
- Should
target size support both width and height classes at the
profile level, or is that purely a layout-time concern (see the layout
arrangements issue)? Leaning toward layout owning the two-axis
(width × height) size-class matrix, with ui profile only stating the
platform's typical/default class.
Dependencies
Root of the screen work alongside Cratis/Scene#1 — the size-class and package vocabulary everything else layers on.
Blocks
Part of the screen work — build order and full dependency map: Cratis/Scene#7
Implementation notes — verified current state
ui profile is application-level, not module-level: the proposal states a screen never declares which profile it targets and that profile selection is a build/Stage concern. Add it to ApplicationSyntax in Source/DotNET/Screenplay/Syntax/ApplicationSyntax.cs, whose current shape is:
public record ApplicationSyntax(
IEnumerable<ImportSyntax> Imports,
IEnumerable<ConceptSyntax> Concepts,
IEnumerable<PolicySyntax> Policies,
IEnumerable<ModuleSyntax> Modules,
SourceLocation Location,
DomainSyntax? Domain = null,
IEnumerable<PersonaSyntax>? Personas = null,
IEnumerable<SeedSyntax>? Seeds = null,
AuthenticationSyntax? Authentication = null,
IEnumerable<TypeSyntax>? Types = null) : SyntaxNode(Location);
Add as a trailing optional parameter so existing positional construction keeps compiling.
The "ambiguous name" diagnostic this reuses lives in Diagnostics/DiagnosticCodes.cs; the highest allocated code today is SP0034, so new codes start at SP0035.
Context
Screenplay's screen/layout constructs are (mostly) platform-agnostic, but
nothing in the language currently expresses which platforms/sizes an app
targets, or which component package(s) (PrimeReact, internal widget
libraries, etc.) a build should resolve widget names against. Needed to
support web/mobile/desktop from one model, and to let vendor + internal
packages layer predictably.
Proposal
target sizeuses named size classes (compact/regular/expanded, Apple/Material-style) as the primary vocabulary rather thanraw pixel breakpoints — size classes transfer across platforms (a
narrow browser window and a compact phone are "the same" class); raw
breakpoints are CSS-flavored and don't mean anything on native. Raw
breakpoints could exist as a web-only escape hatch, not the default.
screennever declares which profile it targets — profile selectionis a build/Stage concern. The same screen resolves against different
package chains per build, keeping Level 1/2 genuinely portable.
Component name resolution
Same mechanic as existing name resolution (
Queue.Allvs. bareAll):coreis the built-in, always-present package/fallback.packagesis override priority — a laterpackage's
Buttonshadows an earlier one's on name collision, so"extensions on top of a base" only need to define what they override.
class of warning as an ambiguous query (named candidates, not a silent
pick) — no new diagnostic category, reuse the existing one.
Open questions
target sizesupport both width and height classes at theprofile level, or is that purely a layout-time concern (see the layout
arrangements issue)? Leaning toward layout owning the two-axis
(width × height) size-class matrix, with
ui profileonly stating theplatform's typical/default class.
Dependencies
Root of the screen work alongside Cratis/Scene#1 — the size-class and package vocabulary everything else layers on.
Blocks
flowvs.freeform#95 — layout arrangement, which reuses the size-class vocabularytheme, with declared package compatibility #96 —theme, which declares compatibility against the package chainui profilepackage resolution engine Scene#3 — the package resolution engine that implements thisui profileintoScene.Modelui profileand theme configuration UI StudioIssues#160 —ui profileand theme configuration UIPart of the screen work — build order and full dependency map: Cratis/Scene#7
Implementation notes — verified current state
ui profileis application-level, not module-level: the proposal states ascreennever declares which profile it targets and that profile selection is a build/Stage concern. Add it toApplicationSyntaxinSource/DotNET/Screenplay/Syntax/ApplicationSyntax.cs, whose current shape is:Add as a trailing optional parameter so existing positional construction keeps compiling.
The "ambiguous name" diagnostic this reuses lives in
Diagnostics/DiagnosticCodes.cs; the highest allocated code today is SP0034, so new codes start at SP0035.