D63. Starter blocks for scroll courses: few blocks with presentations, three primitives, three activities (24 Oct 2026)
On this page
Authors used to building courses in Rise 360 expect a legible palette of ready-made blocks. Until now each course wrote its own (medieval-charts wrote six). After research on Rise’s catalogue, authors’ complaints, competitors’ palettes, and the learning and accessibility evidence for each block type, the founder approved a proposal and its leanings (24 Oct 2026). The research and the proposal are kept with the project’s notes.
Weighed:
- Copy Rise’s catalogue: 11 families and about 60 fixed variants. Rise itself switches most variants of a family without losing content, because they are presentations of the same data. A flat catalogue grows without telling authors what each block is for; H5P’s 54 types show a long tail nobody uses. Rejected.
- One “reveal” block and one “question” block holding every form. Their data differ (titled items, ordered items, regions on a picture; options, blanks, pairs), and a schema per type is what agents and the validator read best. Rejected.
- A block per learner action and data shape, its forms a
presentationprop. About ten new blocks and four extended ones cover every Rise variant and what Rise lacks. Chosen.
Conventions
presentation. A block with several forms declares an enum proppresentation, its first value the default. Templates branch withdata-if="presentation == tabs"and expose it as a class on their root (t-panels t-panels--{{presentation}}). Switching it never touches the words. The app shows the values as variants in « Ajouter un bloc » and as a segmented choice in the inspector, with its own French labels: schemas carry no Englishx-enum-labels.- Items. Blocks made of items share one shape where they can:
id(^[a-z0-9-]{1,24}$, stable: visited marks, translations and conversions name it),title,markdown,imageandalt,date. This is what makes « Transformer en… » possible between them. - Focal point.
focus: { "x": 0..1, "y": 0..1 }on an image becomesobject-position: crops on phones keep the subject. - Full bleed. A block’s
widthmay bebleed: edge to edge of the window in scroll presentation, of the slide in slides. A template asks for it from its root withdata-t-bleed(an image band does). Text in a bleed block keeps the content width. - Optional blocks. A block may say
optional: true(a transcript, extra detail). It counts neither for a step that waits for exploration nor forcompleteWhen: "interactions-done". - Less motion. Every movement has a reduced-motion form (a short fade, or none). Nothing pulses or loops.
- No layout shift. Blocks that show one thing at a time (tabs, cards, a carousel, a tour) reserve the room of their tallest item, as activities reserve their tallest feedback.
Primitives (any template)
Hooks the player handles, documented in Components §3 and checked like the others.
| Hook | Behaviour |
|---|---|
data-t-sequence on a container; data-t-item="k" on each item; data-t-prev, data-t-next (buttons); optional data-t-goto="k" (buttons), data-t-position |
One item at a time. The others are hidden. It follows the APG carousel pattern with buttons and never moves by itself. Arrow keys work inside it and a swipe works on touch. It writes data-t-current on the container and aria-current on the goto button. data-t-position receives “2 / 5” from the player’s labels. The container reserves the tallest item’s room. An item is visited once shown, and showing it fires click with its name. |
data-t-card="k" holding data-t-face="front" and data-t-face="back"; data-t-flip="k" (button) |
A flip card. data-t-flipped goes on the card, and the hidden face is inert and aria-hidden. The button’s label comes from the player’s labels (TPGi’s pattern). The card is visited once flipped. Under reduced motion the flip is a cross-fade. |
data-t-zoom (a button holding an <img>) |
Opens the image at full size in the player’s lightbox, a modal dialog with the image’s alt and an optional data-t-caption. Escape closes it and focus returns. Several zoom buttons in one block give previous and next. |
data-t-exclusive on a container of data-t-toggle buttons |
Opening one part closes the others. Escape closes the open part and returns focus to its toggle. data-t-exclusive="popover" also closes it on a click outside. |
<details data-t-details="k"> |
A native disclosure that counts as visited once opened. |
data-t-reveal="k" on an element |
Visited once it has been in view (a timeline’s event, a scrolling step). |
item, flip, details and reveal are controls (docs/components.md, Controls): visited, saved, read by { "visited": … } conditions and by steps that wait for exploration.
Steps that wait for exploration
steps.<n>.opens: "explored": the Continue of step n is shown but locked until every activity of the steps above is answered and every control of their blocks is visited, optional blocks aside. Locked, it says what is left (“2 cards left”, from the player’s labels). This is Rise’s Continue with “complete block above”, with a reason given. In slides, Next is locked the same way.
The blocks
| Type (app name) | Presentations | Main props |
|---|---|---|
statement (« Énoncé ») |
statement (large) · ruled (between two rules) · quote · image (text over an image) |
markdown or textRef; author, role, portrait; image, alt, focus; align |
divider (« Séparateur ») |
line · ornament (the theme’s drawing) · number · space |
size; restart (number) |
image (extended) |
centered · wide · band (edge to edge, cropped) · beside (text beside) · over (text over the image) |
focus, zoom; title, markdown (beside, over); side, share (beside); height (band, over) |
gallery (« Galerie ») |
grid · mosaic · carousel · compare (before/after slider) |
images[] (id, asset, alt, caption, focus); columns; ratio; zoom |
columns (« Colonnes ») |
— | count (2 or 3), widths (equal, wide-start, wide-end), align; slots first, second, third |
text (extended) |
— | aside: a margin note (in the margin on wide windows, after the text on narrow ones) |
accordion (« Panneaux », extended) |
accordion · tabs · cards (flip grid) · stack (cards one at a time) |
items[] (id, title, markdown, image, alt); allowMultiple; prompt (what to think about before revealing); hint (cards’ hint, default true) |
steps (« Étapes ») |
carousel (one at a time) · timeline (« Frise », vertical) · scroll (« Défilé »: a sticky figure while the text scrolls) |
items[] (id, title, markdown, image, alt, date, region); intro, summary (carousel); numbered; figure (replace, build, focus) with figureImage, figureAlt; side |
hotspots (« Image interactive ») |
popover · side · below · tour (the markers in order) |
image, alt, focus; items[] (id, x, y, title, markdown, image, alt); markerStyle (number, icon), icon; prompt |
speech (« Personnage ») |
— | speaker (a speaker of course.json), lines[] (id, markdown), side, kind (speech, thought) |
quiz (extended) |
text · images (picture options) · image (regions placed on one picture) |
image, alt (image); options’ image, alt (images); options’ x, y (image) |
fill-in (« Texte à trous ») |
typed · menus · bank (words to place) |
stem; markdown with blanks `[[answer |
sort (« Classer ») |
pairs · categories · order |
stem; items[] (id, text, image, alt, target), targets[] (id, text, image, alt); feedback; attempts, showCorrectAnswer, scored, weight, objective |
reflection (« Réflexion ») |
text · scale |
prompt; maxLength, rows, model (an expert’s answer to compare with), download; scale (min, max, minLabel, maxLabel) |
screen layout opening (« Ouverture ») |
title · band · split · cover |
image, alt, focus, lead, duration (reading time computed by the build); slots question (a pre-question), body |
Notes.
statement. With anauthorit is a quote in every presentation:<figure>,<blockquote>,<figcaption>. Theimagepresentation is a bleed block over the theme’s scrim, andelabora fitmeasures its contrast against the pixels behind the text.divider. Numbers come from a CSS counter on the screen (decimal-leading-zero). They are decorative: dividers are hidden from screen readers, and a line is an<hr>.accordion.- It keeps its id, so no format migration is needed. The accordion uses
data-t-details. - Tabs become an accordion in containers narrower than 560 px.
- Cards follow the flip primitive. Their front is the title and the image; their back is the text.
- It keeps its id, so no format migration is needed. The accordion uses
steps.- The carousel’s intro and summary are items of the sequence (
intro,summary), so “every item visited” means the end was reached. - The timeline’s events and the scrolling steps are
data-t-reveal. - The scroll presentation keeps native scroll: no scrolljacking. A step is current while it crosses the middle of the window. Without JavaScript or under reduced motion, each step’s image shows with its step.
buildstacks the images as layers;focusmoves over regions offigureImage.
- The carousel’s intro and summary are items of the sequence (
hotspots. Markers are at least 44 px, numbered by default, and never pulse. In containers narrower than 560 px the panels become a numbered list under the image, as Adapt does.tourwalks the markers with the sequence primitive.quizimage. The regions are the options. Screen readers hear neutral names (“Zone 1”, from the labels) until the answer is final, so the picture does not give it away.- Activities.
fill-in,sortandreflectionare behaviours of the player, likequiz(docs/components.md §3, with their hooks): scored, saved, recorded and announced by the player, forkable like a quiz. Templates may not holdinput,selectortextareawithout a hook; the player builds those controls in the hooks.- Scores. A
fill-inscores the share of its blanks right and asortthe share of its items placed right (Moodle’s per-pair rule). Each is correct when all are right. Areflectionis never scored; it counts as answered once saved. - Tap first. Placing works by choosing an item, then where it goes (WCAG 2.5.7). Drag is an extra for fine pointers;
orderalso has move up and move down buttons. - Saved state (suspend data, format v1, new fields):
ffill-in answers,rsort placements,ereflections.tis the dialogues’. The build’s worst case counts a reflection at itsmaxLength, as a persisted string variable. - Updating a published sort. Sort placements are saved by item index, to fit the SCORM 1.2 budget. Reordering a sort’s items, or removing one before others, after learners started misplaces their saved answers on resume: add items at the end, and change the order only in a new version. Fill-in answers are saved by blank, in the same way. « Transformer en… » (
convert_block) never reorders items. - SCORM 1.2 interactions:
- typed blanks:
fill-in; - menus and words to place:
choiceper blank; - pairs and categories:
matching; - order:
sequencing; - reflection text:
fill-in, its first 255 characters; - scale:
likert.
- typed blanks:
- Scores. A
Words, exports and checks
- Translation. Every text prop is
x-translatable. Blanks are translated with their sentence. - Exports. Exports, the client view, the Document and detach render each new type as charts do: as native text. A divider renders as nothing; a gallery renders as images with captions; a sort as its items and targets in a list; a fill-in as the sentence with its answers.
- Checks:
W_ITEMS_MANY: tabs over 7, carousel steps over 7, markers over 8, cards over 12, a gallery carousel over 5;W_TABS_LABEL_LONG: over 24 characters;W_QUOTE_REPEATS: a quote whose text is also in a text block of the screen;W_ACTIVITY_NO_FEEDBACK: a fill-in or sort without incorrect feedback;E_FILLIN_NO_BLANK;E_SORT_TARGET: an item pointing to a target that does not exist, pairs that do not match one to one, an order without items.
Revisit if: authors keep asking for a Rise variant left out (the quote carousel, the checkbox list, the button stack); a presentation’s options grow beyond what one form shows (then a separate block); scroll-driven figures prove hard to set without an agent (then recipes or a figure editor).
Amended on 29 Oct 2026 (no eyebrow over a title): the opening no longer has an eyebrow. The player used to write the section and « Leçon 2 sur 6 » above the title of every opening, or the eyebrow an author gave. The founder, on seeing it in coffee-in-brief and in medieval-charts (« Drawing the sea »):
« Tu peux effectivement supprimer cette règle de sur-titre de D63, car il ne faut pas le systématiser, cela fait très design IA dans les exemples café et “drawing the sea”. En plus, on passe souvent notre regard sur les sur-titres sans les lire parce qu’on est déjà relativement surchargé par tout le contenu en arrivant sur une nouvelle page. Lorsque c’est important, il faudrait de meilleures manières que le sur-titre d’indiquer où on en est : cela peut être le job de l’UI globale du module, ou de numérotations (et indications de chapitre) selon le style du module. Je pense que si on décourage les sur-titres, les agents trouveront des solutions plus intéressantes et naturelles. »
What changed:
- The opening’s head is the title, the lead and the reading time; nothing above the title. The layout hooks
data-t-sectionanddata-t-lessonand the labellessonOfare gone;data-t-durationstays (a reading time is not an eyebrow). - The
eyebrowprop is removed rather than kept as an option: an option would still invite it, and the founder wants it discouraged. It is a narrowing (D64’s revisit if), published as the schemas 0.1.4 with no migration, as nothing is published that uses it (no compatibility before publication). - Where the learner is belongs to the module’s UI (its outline and progress, to be designed), or to a numbering of the course’s own style: the module templates’ part openers set their number in their own way (Flow’s
flow-section, Shapes’part-mark, and two forks of the opening, Clear’sclear-sectionand Organic’sorganic-part, with anumberprop). - The rules agents are given (
AGENTS.md,elabora-course-authoring,elabora-visual-design) say: no line over a title.