Try a lesson

Lets the reader try one Academy lesson: pick a fix and see whether Loom's audit passes it, with the reason.

Organism · beta · v1.0.0 · owner: Site system lead · contract 19 of 20 points (open: figma)

Do and don't

Do: The lesson

Rendered by academy-lesson.ts

Open example: Try a lesson · Do: The lesson Use the full-page example to follow page links.

Real checks on a real lesson.

Do: Results explain

Rendered by academy-lesson.ts

Open example: Try a lesson · Do: Results explain Use the full-page example to follow page links.

Every answer says why.

Don't: A correct answer that teaches the anti-pattern

Rendered by academy-lesson.ts

Open example: Try a lesson · Don't: A correct answer that teaches the anti-pattern Use the full-page example to follow page links.

The passing fix must be the role token, not a primitive (critic, 26 Oct).

Don't: A visible live region

Rendered by academy-lesson.ts

Open example: Try a lesson · Don't: A visible live region Use the full-page example to follow page links.

The result already shows; the live region is for screen readers only.

Rules

RuleWhyCheck
Try a lesson is computed by Loom's code from one Harbor UI lesson whose answers are checked by Loom's audit at build time, not drawn by hand.A showcase is proof only if the product's own code produced what it shows.Automated: scripts/site/interactives/check.ts (recomputes the showcase data and fails on drift)
Each fix's result is computed by Loom's audit at build time.The lesson teaches what the checks enforce.Automated: tests/unit/site-academy.test.ts

API

No props.

Contract details

The full contract: identity, anatomy, variants, states, tokens, layout, motion, accessibility, content, tests

Identity

AspectValue
Idacademy-lesson
LayerOrganisms
Categoryshowcase
OwnerSite system lead
Statusbeta
Version1.0.0
Sourceapps/showcase/site/system/organisms/academy-lesson.ts (private repository; the contract and the render function are this one module)
VersionDateChange
1.0.02026-10-26Try a lesson: computed by Loom's code from one Harbor UI lesson whose answers are checked by Loom's audit at build time.

Use when

  • The Academy page. Why: Trying one lesson shows how the Academy teaches with the system's own rules.

Do not use when

  • To certify anyone. Why: Certificates come from the Academy in the reader's repository, not this sample.

Anatomy

PartWhat it is
rootdiv.al
framediv.al-frame
taskThe task and the seeded code
fixesDisclosure list of fixes, one open at a time
resultPasses / not yet, with the reason
statusVisually hidden live region

Made of: showcase-frame, code-block, control, caption.

Used in: pages directly.

Variants

VariantWhenWhy
fullOn its demo page and its section.The whole experience where the claim is made.

States

StateRendered or not applicable
defaultTask, code and closed fixes
hoverFix labels underline.
focus-visibleThe --focus ring on each fix.
activeNot applicable: Summaries have no pressed state.
disabledNot applicable: Never.
loadingComputed lesson results and native disclosures remain usable while the optional exclusivity/status enhancement loads.
emptyNot applicable: Always has fixes.
errorCaught chunk/initialization failure keeps the native disclosure lesson and computed results readable; no ready result is claimed for failed enhancement.
currentNot applicable: No navigation.
visitedNot applicable: Not links.
expandedOne fix open at a time, with its result.

Tokens

PartToken
result.passed--teal-ink
result.failed--madder-ink
code.ground--term-bg
--academy-lesson-margin-space-8var(--space-8)
--academy-lesson-background-surfacevar(--surface)
--academy-lesson-color-inkvar(--ink)
--academy-lesson-border-linevar(--line)
--academy-lesson-border-radius-radiusvar(--radius)
--academy-lesson-padding-space-6var(--space-6)
--academy-lesson-color-ink-2var(--ink-2)
--academy-lesson-font-type-labelvar(--type-label)
--academy-lesson-margin-space-4var(--space-4)
--academy-lesson-padding-inline-start-space-7var(--space-7)
--academy-lesson-background-term-bgvar(--term-bg)
--academy-lesson-color-term-fgvar(--term-fg)
--academy-lesson-padding-space-5var(--space-5)
--academy-lesson-font-type-figurevar(--type-figure)
--academy-lesson-gap-space-4var(--space-4)
--academy-lesson-padding-space-4var(--space-4)
--academy-lesson-background-surface-2var(--surface-2)
--academy-lesson-outline-focusvar(--focus)
--academy-lesson-color-teal-inkvar(--teal-ink)
--academy-lesson-color-madder-inkvar(--madder-ink)
--academy-lesson-font-type-smallvar(--type-small)
--academy-lesson-margin-top-space-4var(--space-4)
--academy-lesson-padding-space-8var(--space-8)

Layout

AspectValue
breakpointsRequired review at 390, 768, 1024 and 1440 px; execution is not implied by this declaration; columns stack under 768 px and controls fill the row on phones.
wrappingText wraps; code panes scroll inside their own focusable region.
textExpansionJapanese strings come from the i18n tables and wrap; engine output stays English.

Spacing and rhythm

AspectValue
internalInside the Showcase frame's padding, controls and caption at its foot.
externalFull width of its section.
rhythmOne showcase per section, after the section's claim (D-SITE-008).

Motion

AspectValue
NoneOpening a fix shows its result; nothing plays.

Runtime and reuse

  1. stylesheet: /css/site.css. Built Site tokens, core and registered element CSS; preserve modes, focus and responsive rules.

  2. stylesheet: /css/demos.css. Existing legacy demo styles where the rendered specimen uses them.

  3. font: /fonts/. Self-hosted files referenced by Site @font-face, with licences; Japanese locale overrides remain applicable.

  4. Static fallback: Original build-time specimen remains readable before loading and after chunk/initialization failure; enhancement controls retain authored hidden state.

  5. Configured initializer: scripts/site/academy/try-lesson.client.ts#init. The host owns transactional static-markup restoration and runtime state.

  6. Consumer module (imports relative to the configured source root):
    import { createRuntimeHost } from "./src/workflows/runtime-host";
    import { SITE_RUNTIMES } from "./apps/showcase/site/runtime-registry";
    const definition = SITE_RUNTIMES.find(entry => entry.binding.id === "academy-lesson");
    if (!definition || definition.binding.lifecycle.kind !== "managed") throw new Error("Managed runtime binding unavailable");
    const host = createRuntimeHost([definition]);
    export function mountRuntime(container: ParentNode) { return host.mountAll(container); }
  7. After inserting the rendered markup, call mountRuntime(container) for the container holding [data-demo="academy-lesson"]. Retain the returned disposal function and call it before removing, replacing or remounting, including every Storybook args render. The configured host restores captured static markup/attributes on disposal or caught load/initialization failure; retry starts a fresh managed remount.

Accessibility passport

AspectValue
roleregion with a heading, or a figure
nameIts heading or caption
keyboardTab to the controls; Space plays or pauses; arrows move the steps; End shows the last step.
focusControls in reading order; focus never moves on its own.
screenReaderManual frame selection and pause announce their settled content. Explicit Play announces the final settled summary once; autoplay and system interruption/disposal stay silent. Legacy initializers outside the shared player remain explicitly unassessed.
contrastInk on surface 14:1; state dyes only as marks with words.
targetControls are 44 px.

Content

SlotLengthVoice
result1 sentencePasses / Not yet, and why

Good: “Not yet: primitives skip the role. Use --semantic-text so a theme change reaches this text.”

Bad: “Wrong!”

Japanese: The lesson is English; the Academy page says so in Japanese.

Icons and illustrations

None: this element uses no icon or illustration of its own.

Decisions and exceptions

Usage

27 uses across the built pages (measured by npm run site:system).

Tests

AspectValue
unittests/unit/site-system.test.ts: renders every do and don't example through the registry and checks the classes it owns
visualNot yet: there are no screenshot baselines; the Library page is checked for sideways scroll at 1440 px by tests/site/system.spec.ts
a11ytests/site/system.spec.ts: axe (0 serious or critical) on the element's Library page in light and dark
parityscripts/site/system/check.ts: Library examples are rendered by the same render function the site imports

Figma

not-yet: The Loom Site Figma library is the last stage of the plan; this element is not mapped yet.

Open in Storybook

Start with a conversation about your system.

We read your system, show you what we found, and agree with your team what to fix first.