Worksheet Components
Worksheet components implement the WorksheetComponent subtrait, which pins the associated types for trait object usage.
WorksheetComponent Subtrait
Section titled “WorksheetComponent Subtrait”trait WorksheetComponent: Component<Metadata = (), Output = WorksheetElement> { fn id(&self) -> &'static str; fn name(&self) -> &'static str; fn description(&self) -> &'static str; fn icon(&self) -> &'static str;}Child metadata is () — worksheet components do not receive spatial metadata from their placement. Each component compiles to a single WorksheetElement. A blanket impl covers any TypedComponent with matching types, so you only implement TypedComponent.
Built-in Components
Section titled “Built-in Components”| Component | Key | Description |
|---|---|---|
SheetHeaderComponent | "sheet_header" | Page header with title, class name, name/date fields |
SectionHeadingComponent | "section_heading" | Section divider with title and colored accent |
QuestionComponent | "question" | Question with prompt, answer area, type, difficulty |
GoalsComponent | "goals" | Success criteria checklist |
AnswerGridComponent | "answer_grid" | Grid of answer options in columns |
ActivityComponent | "activity" | Free-form activity content |
Compile Flow
Section titled “Compile Flow”Each component implements TypedComponent and receives a typed properties struct:
#[derive(modality_core::ComponentProperties)]pub struct QuestionProps { #[property(key = "questionText", name = "Question")] pub question_text: String,
#[property(key = "questionNumber", name = "Number", default = "1")] pub question_number: i32,
#[property(key = "questionType", name = "Type")] pub question_type: QuestionType,
#[property(name = "Answers", description = "JSON-encoded answer options")] pub answers: String,
#[property(key = "answerBoxHeight", name = "Answer Box Height", default = "80")] pub answer_box_height: f64,
// ...}
impl TypedComponent for QuestionComponent { type Properties = QuestionProps; type Metadata = (); type Output = WorksheetElement;
fn id() -> &'static str { "question" } fn name() -> &'static str { "Question" } fn description() -> &'static str { "Question with prompt, answers, and answer area" } fn icon() -> &'static str { "help_outline" }
fn compile(&self, props: &QuestionProps, _meta: &()) -> Result<WorksheetElement, CompileError> { Ok(WorksheetElement::Question(QuestionElement { /* ... */ })) }}The blanket Component impl handles HashMap extraction automatically — TypedComponent::compile() always receives typed props.
Component Registration
Section titled “Component Registration”Components register via inventory::submit! and are resolved by key:
inventory::submit!(WorksheetComponentEntry(&QuestionComponent));Related
Section titled “Related”- Overview — struct, types, compilation flow
- Intents — all dispatchable commands
Component— the core trait all components implementProperties— property schema and value system- Typed Component Properties RFC — design rationale for typed component properties