Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions docs/design/mockups/course-pages-explained.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# The course and instructor mockups, explained

Unlike the original four mockups (which preceded the Thymeleaf templates),
these nine pages were added *after* the course UI shipped: they are the
shipped templates frozen as static HTML with sample data, so the prototype
stays a faithful, browsable snapshot of the real interface. The sync happens
at stable UI milestones only, not per merged pull request.

What each page snapshots, and the one thing worth noticing on it:

- **courses.html** (student catalogue): each `course-card` carries the
"You are enrolled" marker inside `course-card__meta`, the state the
controller computes per card.
- **course.html** (course detail): shown in the just-enrolled state, so the
success alert (`role="status"`) and the "Quit this course" form are both
visible. Enroll/quit are POST forms, never links: they change state.
- **lesson.html**: the `<article>` holds what `MarkdownRenderer` outputs.
The instructor authored `# Why lists matter`, but it arrives as an `h2`:
headings are demoted one level at render time so the page keeps exactly
one `h1` (RGAA 9.1, [ADR-0014](../../adr/0014-demote-markdown-headings-in-lesson-rendering.md)).
- **dashboard.html** (updated): the earlier stats-and-progress concept is
gone; the shipped dashboard lists the student's active enrollments with
status and enrollment date. Stats may return later; the mockup tracks what
is real.
- **instructor-courses.html**: the authoring entry point lists all statuses
(Draft, Published, Archived), unlike the student catalogue.
- **instructor-course-editor.html**: one page hosts the edit form, the
publication lifecycle actions (only the transitions the current status
allows are rendered), and lesson management. The per-lesson buttons carry a
`visually-hidden` suffix ("Move up: Loops without tears") so a screen
reader hears which lesson each button acts on, while sighted users read
the row.
- **instructor-lesson-editor.html**: `textarea.form__input` is the Markdown
editor; the hint reminds authors that output is sanitized (ADR-0013).
- **instructor-students.html**: the roster uses the `.table` block with a
`visually-hidden` caption; the Remove action only renders for enrollments
that can still be dropped.
- **error.html**: the styled 404 that replaced the Whitelabel page; 403 and
500 use the same skeleton with different copy.

Shared wiring on every page, inherited from the app templates: skip link
targeting `main#main` with `tabindex="-1"` (explicit focus move), one `h1`,
`aria-current="page"` on the active nav entry, and role-aware nav (the
Instructor entry appears only on instructor pages, where an instructor is
logged in).
68 changes: 68 additions & 0 deletions docs/design/mockups/course.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Course — learn-dev</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:wght@400;700&family=Sora:wght@600;700&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="css/theme-catppuccin.css">
<link rel="stylesheet" href="css/base.css">
</head>
<body>
<a class="skip-link" href="#main">Skip to main content</a>

<header class="site-header">
<div class="site-header__inner">
<a class="site-header__brand" href="home.html">learn<span class="site-header__brand-mark">-dev</span></a>
<nav class="site-header__nav" aria-label="Main">
<ul class="nav__list">
<li><a class="nav__link" href="dashboard.html">Dashboard</a></li>
<li><a class="nav__link" href="courses.html" aria-current="page">Courses</a></li>
<li>
<!-- Logout is a POST in the real app (CSRF); styled as a ghost button -->
<form action="#" method="post">
<button class="button button--ghost" type="submit">Log out</button>
</form>
</li>
</ul>
</nav>
</div>
</header>

<main class="site-main" id="main" tabindex="-1">
<p class="alert alert--success" role="status">
You are enrolled in this course.
</p>

<h1 class="page-title">Python for curious minds</h1>
<p class="course-card__meta">By demo-teacher</p>

<p>Loops, lists, and a taste of the standard library.</p>

<div>
<form action="#" method="post">
<button class="button button--ghost" type="submit">Quit this course</button>
</form>
</div>

<section aria-labelledby="lessons-title">
<h2 id="lessons-title">Lessons</h2>
<ol>
<li><a href="lesson.html">Lists in five minutes</a></li>
<li><a href="lesson.html">Loops without tears</a></li>
</ol>
</section>

<p><a href="courses.html">Back to all courses</a></p>
</main>

<footer class="site-footer">
<div class="site-footer__inner">
<p>learn-dev, an interactive programming learning platform.</p>
<p><a href="https://github.com/ebouchut/learn-dev">Source on GitHub</a></p>
</div>
</footer>
</body>
</html>
58 changes: 58 additions & 0 deletions docs/design/mockups/courses.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Courses — learn-dev</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:wght@400;700&family=Sora:wght@600;700&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="css/theme-catppuccin.css">
<link rel="stylesheet" href="css/base.css">
</head>
<body>
<a class="skip-link" href="#main">Skip to main content</a>

<header class="site-header">
<div class="site-header__inner">
<a class="site-header__brand" href="home.html">learn<span class="site-header__brand-mark">-dev</span></a>
<nav class="site-header__nav" aria-label="Main">
<ul class="nav__list">
<li><a class="nav__link" href="dashboard.html">Dashboard</a></li>
<li><a class="nav__link" href="courses.html" aria-current="page">Courses</a></li>
<li>
<!-- Logout is a POST in the real app (CSRF); styled as a ghost button -->
<form action="#" method="post">
<button class="button button--ghost" type="submit">Log out</button>
</form>
</li>
</ul>
</nav>
</div>
</header>

<main class="site-main" id="main" tabindex="-1">
<h1 class="page-title">Courses</h1>

<ul class="course-list">
<li class="course-card">
<h2 class="course-card__title"><a href="course.html">Python for curious minds</a></h2>
<p class="course-card__meta">By demo-teacher <span>&middot; You are enrolled</span></p>
<p>Loops, lists, and a taste of the standard library.</p>
</li>
<li class="course-card">
<h2 class="course-card__title"><a href="course.html">Git from the ground up</a></h2>
<p class="course-card__meta">By demo-teacher</p>
<p>Commits, branches, and how to think in snapshots.</p>
</li>
</ul>
</main>

<footer class="site-footer">
<div class="site-footer__inner">
<p>learn-dev, an interactive programming learning platform.</p>
<p><a href="https://github.com/ebouchut/learn-dev">Source on GitHub</a></p>
</div>
</footer>
</body>
</html>
43 changes: 43 additions & 0 deletions docs/design/mockups/css/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@ code {
top: 0;
}

/* The skip link moves focus onto main (tabindex="-1"); no ring on a
non-interactive landmark (WCAG 2.4.7 applies to interactive controls) */
main:focus {
outline: none;
}

/* ---------- Site header ---------- */

.site-header {
Expand Down Expand Up @@ -410,6 +416,43 @@ code {
padding: 0.6em 0.8em;
}

/* Markdown editors and long descriptions */
textarea.form__input {
min-height: 8rem;
resize: vertical;
}

/* Action buttons that sit inside a line of text or a list item */
.form--inline {
display: inline;
}

/* ---------- Data tables (e.g. the course roster) ---------- */

.table {
width: 100%;
border-collapse: collapse;
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius);
}

.table th,
.table td {
text-align: left;
padding: var(--space-2) var(--space-3);
border-bottom: 1px solid var(--color-border);
}

.table th {
font-family: var(--font-display);
font-size: var(--font-size-sm);
}

.table tr:last-child td {
border-bottom: 0;
}

.form__input:focus-visible {
outline: 2px solid var(--color-focus);
outline-offset: 1px;
Expand Down
45 changes: 12 additions & 33 deletions docs/design/mockups/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<nav class="site-header__nav" aria-label="Main">
<ul class="nav__list">
<li><a class="nav__link" href="dashboard.html" aria-current="page">Dashboard</a></li>
<li><a class="nav__link" href="courses.html">Courses</a></li>
<li>
<!-- Logout is a POST in the real app (CSRF); styled as a ghost button -->
<form action="#" method="post">
Expand All @@ -30,54 +31,32 @@
</div>
</header>

<main class="site-main" id="main">
<h1 class="page-title reveal">Welcome back, <strong>carol</strong> 👋</h1>
<p class="reveal reveal--2">Here is where you left off.</p>
<main class="site-main" id="main" tabindex="-1">
<h1 class="page-title">Welcome back, <strong>carol</strong> 👋</h1>

<h2 class="visually-hidden" id="stats-title">Your numbers</h2>
<ul class="stats reveal reveal--2" aria-labelledby="stats-title">
<li class="stat-card">
<span class="stat-card__value">3</span>
<span class="stat-card__label">Courses enrolled</span>
</li>
<li class="stat-card">
<span class="stat-card__value">27</span>
<span class="stat-card__label">Lessons completed</span>
</li>
<li class="stat-card">
<span class="stat-card__value">6</span>
<span class="stat-card__label">Day streak</span>
</li>
</ul>

<section aria-labelledby="courses-title" class="reveal reveal--3">
<section aria-labelledby="courses-title">
<h2 id="courses-title">Your courses</h2>

<ul class="course-list">
<li class="course-card">
<h3 class="course-card__title">Java fundamentals</h3>
<p class="course-card__meta">12 of 16 lessons completed</p>
<progress class="course-card__progress" max="16" value="12"
aria-label="Java fundamentals progress: 12 of 16 lessons"></progress>
<h3 class="course-card__title"><a href="course.html">Python for curious minds</a></h3>
<p class="course-card__meta">Enrolled &middot; since 13 July 2026</p>
</li>
<li class="course-card">
<h3 class="course-card__title">SQL and relational databases</h3>
<p class="course-card__meta">9 of 14 lessons completed</p>
<progress class="course-card__progress" max="14" value="9"
aria-label="SQL and relational databases progress: 9 of 14 lessons"></progress>
<h3 class="course-card__title"><a href="course.html">Git from the ground up</a></h3>
<p class="course-card__meta">In progress &middot; since 2 July 2026</p>
</li>
<li class="course-card">
<h3 class="course-card__title">Accessible HTML and CSS</h3>
<p class="course-card__meta">6 of 18 lessons completed</p>
<progress class="course-card__progress" max="18" value="6"
aria-label="Accessible HTML and CSS progress: 6 of 18 lessons"></progress>
<h3 class="course-card__title"><a href="course.html">Accessible HTML and CSS</a></h3>
<p class="course-card__meta">Completed &middot; since 15 June 2026</p>
</li>
</ul>
</section>
</main>

<footer class="site-footer">
<div class="site-footer__inner">
<p>learn-dev an interactive programming learning platform.</p>
<p>learn-dev, an interactive programming learning platform.</p>
<p><a href="https://github.com/ebouchut/learn-dev">Source on GitHub</a></p>
</div>
</footer>
Expand Down
49 changes: 49 additions & 0 deletions docs/design/mockups/error.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page not found — learn-dev</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:wght@400;700&family=Sora:wght@600;700&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="css/theme-catppuccin.css">
<link rel="stylesheet" href="css/base.css">
</head>
<body>
<a class="skip-link" href="#main">Skip to main content</a>

<header class="site-header">
<div class="site-header__inner">
<a class="site-header__brand" href="home.html">learn<span class="site-header__brand-mark">-dev</span></a>
<nav class="site-header__nav" aria-label="Main">
<ul class="nav__list">
<li><a class="nav__link" href="dashboard.html">Dashboard</a></li>
<li><a class="nav__link" href="courses.html">Courses</a></li>
<li>
<!-- Logout is a POST in the real app (CSRF); styled as a ghost button -->
<form action="#" method="post">
<button class="button button--ghost" type="submit">Log out</button>
</form>
</li>
</ul>
</nav>
</div>
</header>

<main class="site-main site-main--narrow" id="main" tabindex="-1">
<h1>Page not found</h1>
<p>The page you are looking for does not exist or has moved.</p>
<p>
<a class="button button--primary" href="home.html">Back to the home page</a>
</p>
</main>

<footer class="site-footer">
<div class="site-footer__inner">
<p>learn-dev, an interactive programming learning platform.</p>
<p><a href="https://github.com/ebouchut/learn-dev">Source on GitHub</a></p>
</div>
</footer>
</body>
</html>
34 changes: 33 additions & 1 deletion docs/design/mockups/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,39 @@ <h2 class="feature-card__title"><a href="register.html">Register</a></h2>
</li>
<li class="feature-card">
<h2 class="feature-card__title"><a href="dashboard.html">Dashboard</a></h2>
<p class="feature-card__text">Stats and course progress (authenticated).</p>
<p class="feature-card__text">The student's courses (authenticated).</p>
</li>
<li class="feature-card">
<h2 class="feature-card__title"><a href="courses.html">Courses</a></h2>
<p class="feature-card__text">Published course catalogue with enrollment marker.</p>
</li>
<li class="feature-card">
<h2 class="feature-card__title"><a href="course.html">Course</a></h2>
<p class="feature-card__text">Detail page, enroll/quit action, lesson list.</p>
</li>
<li class="feature-card">
<h2 class="feature-card__title"><a href="lesson.html">Lesson</a></h2>
<p class="feature-card__text">Rendered Markdown (headings demoted, ADR-0014).</p>
</li>
<li class="feature-card">
<h2 class="feature-card__title"><a href="instructor-courses.html">Instructor: my courses</a></h2>
<p class="feature-card__text">Authoring entry point, all statuses.</p>
</li>
<li class="feature-card">
<h2 class="feature-card__title"><a href="instructor-course-editor.html">Instructor: course editor</a></h2>
<p class="feature-card__text">Form, lifecycle actions, lesson management.</p>
</li>
<li class="feature-card">
<h2 class="feature-card__title"><a href="instructor-lesson-editor.html">Instructor: lesson editor</a></h2>
<p class="feature-card__text">Title and Markdown content form.</p>
</li>
<li class="feature-card">
<h2 class="feature-card__title"><a href="instructor-students.html">Instructor: students</a></h2>
<p class="feature-card__text">Roster table with the remove action.</p>
</li>
<li class="feature-card">
<h2 class="feature-card__title"><a href="error.html">Error page</a></h2>
<p class="feature-card__text">Styled 404; 403 and 500 share the shape.</p>
</li>
</ul>

Expand Down
Loading