0010 Components, versions, variants and style templates
- Status: accepted (2026-10-29)
Decision
Section titled “Decision”- Components. Every element type is a component (
@astrolabe/components,ComponentManifest,ComponentDefinition), graded or not, so blocks such as images and callouts fit the same model. Tags stayastl-*. The built-ins are listed once, indefinitions.ts,elements.ts,editors.tsandmanifests.ts. - Versions.
manifest.versionis the element format version, written asvin every view. A breaking change bumps it and addsComponentDefinition.migrations[n](source n to n + 1); players keep rendering every older view version, because stored views are immutable. - Variants.
manifest.variants { default, values }(or null) and the publicvariantattribute derived from it (variantAttribute). A variant changes presentation and student-side behaviour only (a resizable gap, a select with a search box), never grading: every variant of a source grades the same. The engine validates the value like any enum, elements render it, the authoring kit offers it. Adding a variant is not breaking; removing one or changing the default is. - Style templates.
StyleTemplate(corestyle.ts): a named, versioned look made of token overrides (all themes, then light and dark) and::part()declarations per component tag. Hosts register templates (trusted, like their own CSS); exercises refer to them by name withstyle-templateon<astl-doc>or on a component. The closest wins: component, then document, then the player's default. Templates never apply in thehctheme or under forced colours, and built-in templates are contrast-checked in light and dark. - Author-written CSS inside exercises stays out until there is a CSS sanitiser.
Consequences
Section titled “Consequences”A new built-in touches its folder and four list lines. Looks are chosen per exercise or per component without forking components, and accessibility themes always win. Templates cannot restyle internals that a component does not expose as a part.