feat: extend references and enhance analytics tracking
Reference pages: - Add Transitions & Animations section (transition-*, animation-*) - Add CSS Variables section (--*, var(), :root) - Add Interactive Elements section (<details>, <summary>, <dialog>, <progress>, <meter>, <datalist>) Analytics tracking (Umami v2): - Add lesson_nav tracking for next/prev navigation - Add lesson_select tracking for sidebar lesson clicks - Add reset_code tracking for code resets - Add help_open tracking for help dialog - Add sidebar_open tracking for menu opens - Add share_open and share_copy tracking for sharing 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
55
src/app.js
55
src/app.js
@@ -195,6 +195,7 @@ let currentMode = "css";
|
|||||||
let sidebarTrigger = null;
|
let sidebarTrigger = null;
|
||||||
|
|
||||||
function openSidebar() {
|
function openSidebar() {
|
||||||
|
track("sidebar_open");
|
||||||
// Store trigger element for focus return
|
// Store trigger element for focus return
|
||||||
sidebarTrigger = document.activeElement;
|
sidebarTrigger = document.activeElement;
|
||||||
|
|
||||||
@@ -444,6 +445,7 @@ function selectLesson(moduleId, lessonIndex) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lessonEngine.setLessonByIndex(lessonIndex);
|
lessonEngine.setLessonByIndex(lessonIndex);
|
||||||
|
track("lesson_select", { module: moduleId, lesson: lessonIndex });
|
||||||
|
|
||||||
// Show lesson UI
|
// Show lesson UI
|
||||||
showLessonUI();
|
showLessonUI();
|
||||||
@@ -687,6 +689,7 @@ function nextLesson() {
|
|||||||
const success = lessonEngine.nextLesson();
|
const success = lessonEngine.nextLesson();
|
||||||
if (success) {
|
if (success) {
|
||||||
const newState = lessonEngine.getCurrentState();
|
const newState = lessonEngine.getCurrentState();
|
||||||
|
track("lesson_nav", { direction: "next", module: newState.module.id, lesson: newState.lessonIndex });
|
||||||
// Update URL
|
// Update URL
|
||||||
updateHash(newState.module.id, newState.lessonIndex);
|
updateHash(newState.module.id, newState.lessonIndex);
|
||||||
|
|
||||||
@@ -702,6 +705,7 @@ function prevLesson() {
|
|||||||
const success = lessonEngine.previousLesson();
|
const success = lessonEngine.previousLesson();
|
||||||
if (success) {
|
if (success) {
|
||||||
const newState = lessonEngine.getCurrentState();
|
const newState = lessonEngine.getCurrentState();
|
||||||
|
track("lesson_nav", { direction: "prev", module: newState.module.id, lesson: newState.lessonIndex });
|
||||||
// Update URL
|
// Update URL
|
||||||
updateHash(newState.module.id, newState.lessonIndex);
|
updateHash(newState.module.id, newState.lessonIndex);
|
||||||
|
|
||||||
@@ -728,6 +732,7 @@ function resetCode() {
|
|||||||
// Reset editor to initial code for current lesson
|
// Reset editor to initial code for current lesson
|
||||||
lessonEngine.reset();
|
lessonEngine.reset();
|
||||||
const engineState = lessonEngine.getCurrentState();
|
const engineState = lessonEngine.getCurrentState();
|
||||||
|
track("reset_code", { module: engineState.module?.id, lesson: engineState.lessonIndex });
|
||||||
if (codeEditor && engineState.lesson) {
|
if (codeEditor && engineState.lesson) {
|
||||||
codeEditor.setValue(engineState.lesson.initialCode || "");
|
codeEditor.setValue(engineState.lesson.initialCode || "");
|
||||||
}
|
}
|
||||||
@@ -853,6 +858,7 @@ function runCode() {
|
|||||||
// ================= DIALOGS =================
|
// ================= DIALOGS =================
|
||||||
|
|
||||||
function showHelp() {
|
function showHelp() {
|
||||||
|
track("help_open");
|
||||||
elements.helpDialog.showModal();
|
elements.helpDialog.showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -915,6 +921,7 @@ function handleResetCodeClick() {
|
|||||||
// ================= SHARE DIALOG =================
|
// ================= SHARE DIALOG =================
|
||||||
|
|
||||||
function showShareDialog() {
|
function showShareDialog() {
|
||||||
|
track("share_open");
|
||||||
const engineState = lessonEngine.getCurrentState();
|
const engineState = lessonEngine.getCurrentState();
|
||||||
if (engineState.module && engineState.lesson !== null) {
|
if (engineState.module && engineState.lesson !== null) {
|
||||||
const shareUrl = getShareableUrl(engineState.module.id, engineState.lessonIndex);
|
const shareUrl = getShareableUrl(engineState.module.id, engineState.lessonIndex);
|
||||||
@@ -929,6 +936,7 @@ function closeShareDialog() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function copyShareUrl() {
|
async function copyShareUrl() {
|
||||||
|
track("share_copy");
|
||||||
try {
|
try {
|
||||||
await navigator.clipboard.writeText(elements.shareUrlInput.value);
|
await navigator.clipboard.writeText(elements.shareUrlInput.value);
|
||||||
elements.copyFeedback.hidden = false;
|
elements.copyFeedback.hidden = false;
|
||||||
@@ -1370,12 +1378,42 @@ const referenceContent = {
|
|||||||
<tr><td><code>box-shadow</code></td><td>x y blur spread color</td><td><code>box-shadow: 0 4px 8px rgba(0,0,0,0.1);</code></td></tr>
|
<tr><td><code>box-shadow</code></td><td>x y blur spread color</td><td><code>box-shadow: 0 4px 8px rgba(0,0,0,0.1);</code></td></tr>
|
||||||
<tr><td><code>text-shadow</code></td><td>x y blur color</td><td><code>text-shadow: 1px 1px 2px gray;</code></td></tr>
|
<tr><td><code>text-shadow</code></td><td>x y blur color</td><td><code>text-shadow: 1px 1px 2px gray;</code></td></tr>
|
||||||
<tr><td><code>transform</code></td><td>translate, rotate, scale</td><td><code>transform: translateY(-2px);</code></td></tr>
|
<tr><td><code>transform</code></td><td>translate, rotate, scale</td><td><code>transform: translateY(-2px);</code></td></tr>
|
||||||
<tr><td><code>transition</code></td><td>property duration easing</td><td><code>transition: all 0.3s ease;</code></td></tr>
|
|
||||||
<tr><td><code>cursor</code></td><td>pointer, default, text, grab</td><td><code>cursor: pointer;</code></td></tr>
|
<tr><td><code>cursor</code></td><td>pointer, default, text, grab</td><td><code>cursor: pointer;</code></td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section class="ref-section">
|
||||||
|
<h2>Transitions & Animations</h2>
|
||||||
|
<table class="ref-table">
|
||||||
|
<thead><tr><th>Property</th><th>Values</th><th>Example</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td><code>transition</code></td><td>property duration easing</td><td><code>transition: all 0.3s ease;</code></td></tr>
|
||||||
|
<tr><td><code>transition-property</code></td><td>all, none, specific</td><td><code>transition-property: opacity;</code></td></tr>
|
||||||
|
<tr><td><code>transition-duration</code></td><td>time (s, ms)</td><td><code>transition-duration: 0.3s;</code></td></tr>
|
||||||
|
<tr><td><code>transition-timing-function</code></td><td>ease, linear, ease-in-out</td><td><code>transition-timing-function: ease-out;</code></td></tr>
|
||||||
|
<tr><td><code>animation</code></td><td>name duration timing delay</td><td><code>animation: fade 1s ease-in;</code></td></tr>
|
||||||
|
<tr><td><code>animation-name</code></td><td>@keyframes name</td><td><code>animation-name: slide;</code></td></tr>
|
||||||
|
<tr><td><code>animation-duration</code></td><td>time (s, ms)</td><td><code>animation-duration: 2s;</code></td></tr>
|
||||||
|
<tr><td><code>animation-iteration-count</code></td><td>number, infinite</td><td><code>animation-iteration-count: infinite;</code></td></tr>
|
||||||
|
<tr><td><code>animation-fill-mode</code></td><td>none, forwards, backwards, both</td><td><code>animation-fill-mode: forwards;</code></td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="ref-section">
|
||||||
|
<h2>CSS Variables</h2>
|
||||||
|
<table class="ref-table">
|
||||||
|
<thead><tr><th>Syntax</th><th>Description</th><th>Example</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td><code>--name</code></td><td>Define custom property</td><td><code>--primary: steelblue;</code></td></tr>
|
||||||
|
<tr><td><code>var(--name)</code></td><td>Use custom property</td><td><code>color: var(--primary);</code></td></tr>
|
||||||
|
<tr><td><code>var(--name, fallback)</code></td><td>With fallback value</td><td><code>color: var(--accent, blue);</code></td></tr>
|
||||||
|
<tr><td><code>:root { }</code></td><td>Global scope</td><td><code>:root { --gap: 1rem; }</code></td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
|
||||||
<p class="ref-see-also">See also: <a href="#reference/flexbox">Flexbox Reference</a> | <a href="#reference/grid">Grid Reference</a> | <a href="#reference/selectors">Selectors Reference</a></p>
|
<p class="ref-see-also">See also: <a href="#reference/flexbox">Flexbox Reference</a> | <a href="#reference/grid">Grid Reference</a> | <a href="#reference/selectors">Selectors Reference</a></p>
|
||||||
`,
|
`,
|
||||||
|
|
||||||
@@ -1737,6 +1775,21 @@ const referenceContent = {
|
|||||||
</table>
|
</table>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section class="ref-section">
|
||||||
|
<h2>Interactive Elements</h2>
|
||||||
|
<table class="ref-table">
|
||||||
|
<thead><tr><th>Element</th><th>Purpose</th><th>Key Attributes</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td><code><details></code></td><td>Expandable content</td><td>open (default expanded)</td></tr>
|
||||||
|
<tr><td><code><summary></code></td><td>Details toggle label</td><td>First child of details</td></tr>
|
||||||
|
<tr><td><code><dialog></code></td><td>Modal/popup dialog</td><td>open, use showModal()</td></tr>
|
||||||
|
<tr><td><code><progress></code></td><td>Progress bar</td><td>value, max</td></tr>
|
||||||
|
<tr><td><code><meter></code></td><td>Scalar measurement</td><td>value, min, max, low, high</td></tr>
|
||||||
|
<tr><td><code><datalist></code></td><td>Input suggestions</td><td>id (link via input list attr)</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
|
||||||
<p class="ref-see-also">Learn: <a href="#html">HTML Section</a> | Style with: <a href="#reference/css">CSS Properties</a></p>
|
<p class="ref-see-also">Learn: <a href="#html">HTML Section</a> | Style with: <a href="#reference/css">CSS Properties</a></p>
|
||||||
`
|
`
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user