Skip to content

Commit 2664926

Browse files
committed
Add "Anatomy" page with friendly error structural breakdown
1 parent 8905c8d commit 2664926

3 files changed

Lines changed: 479 additions & 0 deletions

File tree

docs/anatomy.html

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<title>Anatomy of a Friendly Error Message</title>
8+
<link rel="stylesheet" href="styles.css">
9+
</head>
10+
11+
<body>
12+
<div class="anatomy">
13+
<a class="anatomy__back" href="index.html">← Demo</a>
14+
15+
<header class="anatomy__header">
16+
<h1>Anatomy of a Friendly Error Message</h1>
17+
</header>
18+
19+
<div class="anatomy__main">
20+
21+
<div class="anatomy__left">
22+
<!-- Traceback that triggered the error -->
23+
<div class="anatomy__context">
24+
<span class="anatomy__context-label">Error / Trace:</span>
25+
<div class="anatomy__context-code">
26+
<div>Traceback (most recent call last):</div>
27+
<div>&nbsp;&nbsp;File "main.py", line 2, in &lt;module&gt;</div>
28+
<div>&nbsp;&nbsp;&nbsp;&nbsp;print("Hello, " + nme)</div>
29+
<div>NameError: name 'nme' is not defined</div>
30+
</div>
31+
</div>
32+
33+
<div class="anatomy__card">
34+
35+
<!-- Stage 1: Title + Summary -->
36+
<div class="anatomy__zone" data-zone="1">
37+
<div class="anatomy__zone-head">
38+
<div class="anatomy__zone-badge">1</div>
39+
<div class="anatomy__zone-tag">Explain &amp; Suggest - Title &amp; Summary</div>
40+
</div>
41+
<div class="anatomy__zone-body">
42+
<div class="pfem__title">This variable doesn't exist yet</div>
43+
<div class="pfem__summary">Your code uses the variable "<em>nme</em>", but it hasn't been created yet.
44+
Check line 2. If you meant to print the text <em>nme</em>, put it in double quotes.</div>
45+
</div>
46+
</div>
47+
48+
<!-- Stage 2: Why -->
49+
<div class="anatomy__zone" data-zone="2">
50+
<div class="anatomy__zone-head">
51+
<div class="anatomy__zone-badge">2</div>
52+
<div class="anatomy__zone-tag">Hint &amp; Direct - Why it happened</div>
53+
</div>
54+
<div class="anatomy__zone-body">
55+
<div class="pfem__why">Without speech marks Python treats <em>nme</em> as a variable, and this variable
56+
does not exist yet.</div>
57+
</div>
58+
</div>
59+
60+
<!-- Stage 3: Steps -->
61+
<div class="anatomy__zone" data-zone="3">
62+
<div class="anatomy__zone-head">
63+
<div class="anatomy__zone-badge">3</div>
64+
<div class="anatomy__zone-tag">Hint &amp; Direct - What to do</div>
65+
</div>
66+
<div class="anatomy__zone-body">
67+
<ul class="pfem__steps">
68+
<li>If it is meant to be text, put speech marks around <em>nme</em>.</li>
69+
<li>If it is meant to be a variable, make it first (for example: <code>nme = 0</code>).</li>
70+
<li>Check spelling and capital letters.</li>
71+
</ul>
72+
</div>
73+
</div>
74+
75+
<!-- Stage 4: Patch -->
76+
<div class="anatomy__zone" data-zone="4">
77+
<div class="anatomy__zone-head">
78+
<div class="anatomy__zone-badge">4</div>
79+
<div class="anatomy__zone-tag">Solve - Suggested fix</div>
80+
</div>
81+
<div class="anatomy__zone-body">
82+
<pre class="pfem__patch">nme = 0
83+
print("Hello, " + nme)</pre>
84+
</div>
85+
</div>
86+
87+
</div>
88+
</div>
89+
90+
<div class="anatomy__right">
91+
<!-- Stage description -->
92+
<div class="anatomy__desc">
93+
<div class="anatomy__desc-panel" data-zone="1">
94+
<div class="anatomy__desc-title">Step 1 - Explain &amp; Suggest</div>
95+
<div class="anatomy__desc-text">Explain the error in plain English and why the code can't run. Use
96+
highlighting to draw attention to the relevant line. Suggest which aspect the learner should review - a
97+
typo, a missing definition, a syntax issue - <em>posed as a suggestion</em>, not a directive.</div>
98+
</div>
99+
<div class="anatomy__desc-panel" data-zone="2">
100+
<div class="anatomy__desc-title">Step 2a - Hint &amp; Direct (hint)</div>
101+
<div class="anatomy__desc-text">Provide more specific detail about <strong>why</strong> the error happens.
102+
Give the learner something concrete to reason about before directing them to act.</div>
103+
</div>
104+
<div class="anatomy__desc-panel" data-zone="3">
105+
<div class="anatomy__desc-title">Step 2b - Hint &amp; Direct (direct)</div>
106+
<div class="anatomy__desc-text">Direct the learner - don't suggest. Tell them exactly what to change:
107+
<em>"You need to change X at line Y."</em> Be specific and action-oriented.
108+
</div>
109+
</div>
110+
<div class="anatomy__desc-panel" data-zone="4">
111+
<div class="anatomy__desc-title">Step 3 - Solve</div>
112+
<div class="anatomy__desc-text">Provide a working <strong>solution</strong> with a brief explanation of what
113+
it corrects and why. A last resort - enough to unblock without handing the answer over too early.</div>
114+
</div>
115+
</div>
116+
117+
<div class="anatomy__controls">
118+
<button type="button" class="anatomy__btn anatomy__btn--primary" id="reveal-btn">Next stage
119+
&rarr;</button>
120+
<button type="button" class="anatomy__btn anatomy__btn--secondary" id="show-all-btn">Show all stages</button>
121+
<button type="button" class="anatomy__btn anatomy__btn--ghost" id="reset-btn">Reset</button>
122+
</div>
123+
</div>
124+
125+
</div>
126+
</div>
127+
128+
<script>
129+
const TOTAL = 4;
130+
let revealed = 1;
131+
132+
const zones = [...document.querySelectorAll('.anatomy__zone')];
133+
const descPanels = [...document.querySelectorAll('.anatomy__desc-panel')];
134+
const revealBtn = document.getElementById('reveal-btn');
135+
const showAllBtn = document.getElementById('show-all-btn');
136+
const resetBtn = document.getElementById('reset-btn');
137+
138+
function update(next, animate = false) {
139+
revealed = Math.max(1, Math.min(TOTAL, next));
140+
141+
zones.forEach((z, i) => {
142+
const n = i + 1;
143+
const wasRevealed = z.classList.contains('is-revealed');
144+
z.classList.toggle('is-revealed', n <= revealed);
145+
if (animate && n <= revealed && !wasRevealed) {
146+
z.classList.add('just-revealed');
147+
z.addEventListener('animationend', () => z.classList.remove('just-revealed'), { once: true });
148+
}
149+
});
150+
151+
descPanels.forEach((p) => {
152+
p.classList.toggle('is-active', parseInt(p.dataset.zone) === revealed);
153+
});
154+
155+
revealBtn.disabled = revealed >= TOTAL;
156+
revealBtn.textContent = revealed >= TOTAL ? 'All stages revealed' : 'Next stage →';
157+
showAllBtn.disabled = revealed >= TOTAL;
158+
}
159+
160+
revealBtn.addEventListener('click', () => update(revealed + 1, true));
161+
showAllBtn.addEventListener('click', () => update(TOTAL, true));
162+
resetBtn.addEventListener('click', () => update(1));
163+
164+
update(1);
165+
</script>
166+
</body>
167+
168+
</html>

docs/index.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
</div>
2727

2828
<h1>Python Friendly Error Messages - Demo</h1>
29+
<p class="demo__nav">
30+
<a href="anatomy.html" class="demo__nav-link">Anatomy of a friendly error message →</a>
31+
</p>
2932

3033
<div class="demo__table-page" id="demo-container">
3134
Loading demo...

0 commit comments

Comments
 (0)