From 0340a4d4bc59e9e125310fd9c2d85343c6c8ede6 Mon Sep 17 00:00:00 2001 From: Michael Czechowski Date: Thu, 15 Jan 2026 15:53:05 +0100 Subject: [PATCH] feat: implement reference/cheatsheet pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add reference page container to index.html with tab navigation - Create comprehensive cheatsheets for CSS properties, selectors, flexbox, grid, and HTML elements - Add showReferencePage function with CodeMirror syntax highlighting - Add reference_view analytics tracking - Style reference tables, lists, and navigation with responsive design Routes: #reference/css, #reference/selectors, #reference/flexbox, #reference/grid, #reference/html 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- src/app.js | 505 ++++++++++++++++++++++++++++++++++++++++++++++++- src/index.html | 16 ++ src/main.css | 157 +++++++++++++++ 3 files changed, 676 insertions(+), 2 deletions(-) diff --git a/src/app.js b/src/app.js index 67c4360..ed7ce1c 100644 --- a/src/app.js +++ b/src/app.js @@ -115,6 +115,11 @@ const elements = { sectionProgressText: document.getElementById("section-progress-text"), sectionIntro: document.getElementById("section-intro"), + // Reference page elements + referencePage: document.getElementById("reference-page"), + referenceNav: document.getElementById("reference-nav"), + referenceBody: document.getElementById("reference-body"), + // Left panel instructionsSection: document.querySelector(".instructions"), editorSection: document.querySelector(".editor-section"), @@ -1282,6 +1287,445 @@ const sectionContent = { ` }; +// ================= REFERENCE CHEATSHEET CONTENT ================= + +const referenceContent = { + css: ` +

CSS Properties Reference

+

Quick reference for commonly used CSS properties. Click any property to see syntax and examples.

+ +
+

Colors & Backgrounds

+ + + + + + + + + +
PropertyValuesExample
colornamed, hex, rgb(), hsl()color: steelblue;
backgroundcolor, image, gradientbackground: #f0f0f0;
background-colorcolor valuebackground-color: white;
background-imageurl(), gradientbackground-image: url(bg.png);
opacity0 to 1opacity: 0.8;
+
+ +
+

Typography

+ + + + + + + + + + + + +
PropertyValuesExample
font-familyfont name, genericfont-family: system-ui, sans-serif;
font-sizepx, rem, em, %font-size: 1rem;
font-weightnormal, bold, 100-900font-weight: 600;
line-heightnumber, length, %line-height: 1.5;
text-alignleft, center, right, justifytext-align: center;
text-decorationnone, underline, line-throughtext-decoration: none;
text-transformnone, uppercase, lowercase, capitalizetext-transform: uppercase;
letter-spacinglengthletter-spacing: 0.05em;
+
+ +
+

Box Model

+ + + + + + + + + + + + +
PropertyValuesExample
widthlength, %, auto, fit-contentwidth: 100%;
heightlength, %, autoheight: 200px;
max-widthlength, %, nonemax-width: 600px;
paddinglength (1-4 values)padding: 1rem 2rem;
marginlength, auto (1-4 values)margin: 0 auto;
borderwidth style colorborder: 1px solid gray;
border-radiuslength (1-4 values)border-radius: 8px;
box-sizingcontent-box, border-boxbox-sizing: border-box;
+
+ +
+

Layout

+ + + + + + + + + + +
PropertyValuesExample
displayblock, inline, flex, grid, nonedisplay: flex;
positionstatic, relative, absolute, fixed, stickyposition: relative;
top/right/bottom/leftlength, %, autotop: 0; left: 50%;
z-indexinteger, autoz-index: 10;
overflowvisible, hidden, scroll, autooverflow: auto;
floatnone, left, rightfloat: left;
+
+ +
+

Visual Effects

+ + + + + + + + + +
PropertyValuesExample
box-shadowx y blur spread colorbox-shadow: 0 4px 8px rgba(0,0,0,0.1);
text-shadowx y blur colortext-shadow: 1px 1px 2px gray;
transformtranslate, rotate, scaletransform: translateY(-2px);
transitionproperty duration easingtransition: all 0.3s ease;
cursorpointer, default, text, grabcursor: pointer;
+
+ `, + + selectors: ` +

CSS Selectors Reference

+

Selectors determine which HTML elements your styles apply to. More specific selectors override less specific ones.

+ +
+

Basic Selectors

+ + + + + + + + + + +
SelectorDescriptionExample
elementAll elements of typep { ... }
.classElements with class.btn { ... }
#idElement with ID#header { ... }
*All elements* { box-sizing: border-box; }
[attr]Elements with attribute[disabled] { ... }
[attr="value"]Attribute equals value[type="text"] { ... }
+
+ +
+

Combinators

+ + + + + + + + + +
SelectorDescriptionExample
A BB inside A (descendant)nav a { ... }
A > BB direct child of Aul > li { ... }
A + BB immediately after Ah2 + p { ... }
A ~ BB after A (sibling)h2 ~ p { ... }
A, BA or B (grouping)h1, h2, h3 { ... }
+
+ +
+

Pseudo-classes

+ + + + + + + + + + + + + +
SelectorDescriptionExample
:hoverMouse over elementa:hover { color: blue; }
:focusElement has focusinput:focus { outline: 2px solid; }
:activeBeing clickedbutton:active { transform: scale(0.98); }
:first-childFirst child elementli:first-child { ... }
:last-childLast child elementli:last-child { ... }
:nth-child(n)nth child (1-based)tr:nth-child(odd) { ... }
:not(sel)Elements not matching:not(.hidden) { ... }
:checkedChecked inputsinput:checked { ... }
:disabledDisabled form elementsbutton:disabled { opacity: 0.5; }
+
+ +
+

Pseudo-elements

+ + + + + + + + + + +
SelectorDescriptionExample
::beforeInsert before content.icon::before { content: "→"; }
::afterInsert after content.link::after { content: "↗"; }
::first-letterFirst letter of textp::first-letter { font-size: 2em; }
::first-lineFirst line of textp::first-line { font-weight: bold; }
::placeholderInput placeholder textinput::placeholder { color: gray; }
::selectionSelected/highlighted text::selection { background: yellow; }
+
+ +
+

Specificity (Highest to Lowest)

+
    +
  1. Inline styles - style="..." attribute (1000 points)
  2. +
  3. ID selectors - #id (100 points)
  4. +
  5. Class/pseudo-class/attribute - .class, :hover, [attr] (10 points)
  6. +
  7. Element/pseudo-element - div, ::before (1 point)
  8. +
  9. Universal selector - * (0 points)
  10. +
+
+ `, + + flexbox: ` +

Flexbox Reference

+

Flexbox is a one-dimensional layout system. Apply display: flex to a container, and its children become flex items.

+ +
+

Container Properties

+ + + + + + + + + + + +
PropertyValuesDescription
displayflex, inline-flexEnable flex container
flex-directionrow, row-reverse, column, column-reverseMain axis direction
flex-wrapnowrap, wrap, wrap-reverseAllow items to wrap
justify-contentflex-start, flex-end, center, space-between, space-around, space-evenlyMain axis alignment
align-itemsstretch, flex-start, flex-end, center, baselineCross axis alignment
align-contentstretch, flex-start, flex-end, center, space-between, space-aroundMulti-line alignment
gaplengthSpace between items
+
+ +
+

Item Properties

+ + + + + + + + + + +
PropertyValuesDescription
flex-grownumber (default: 0)How much item grows
flex-shrinknumber (default: 1)How much item shrinks
flex-basislength, autoInitial size before grow/shrink
flexgrow shrink basisShorthand (e.g., flex: 1)
align-selfauto, flex-start, flex-end, center, stretchOverride align-items
orderinteger (default: 0)Visual order of item
+
+ +
+

Common Patterns

+
+
/* Center horizontally and vertically */
+.center {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+/* Space items evenly */
+.navbar {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+/* Equal-width columns */
+.columns {
+  display: flex;
+  gap: 1rem;
+}
+.columns > * {
+  flex: 1;
+}
+
+/* Sticky footer */
+.page {
+  display: flex;
+  flex-direction: column;
+  min-height: 100vh;
+}
+.main { flex: 1; }
+
+
+ `, + + grid: ` +

CSS Grid Reference

+

CSS Grid is a two-dimensional layout system for complex row and column layouts. Apply display: grid to a container.

+ +
+

Container Properties

+ + + + + + + + + + + + +
PropertyValuesDescription
displaygrid, inline-gridEnable grid container
grid-template-columnstrack sizesDefine column widths
grid-template-rowstrack sizesDefine row heights
gaplengthSpace between cells
justify-itemsstart, end, center, stretchHorizontal alignment in cells
align-itemsstart, end, center, stretchVertical alignment in cells
justify-contentstart, end, center, space-between, space-aroundHorizontal grid alignment
align-contentstart, end, center, space-between, space-aroundVertical grid alignment
+
+ +
+

Track Sizing

+ + + + + + + + + + + +
ValueDescriptionExample
px, rem, %Fixed or relative sizes200px 1rem 50%
frFraction of available space1fr 2fr 1fr
autoSize to contentauto 1fr auto
minmax(min, max)Size rangeminmax(100px, 1fr)
repeat(n, size)Repeat n timesrepeat(3, 1fr)
repeat(auto-fill, ...)Fill available spacerepeat(auto-fill, minmax(200px, 1fr))
repeat(auto-fit, ...)Fill and stretchrepeat(auto-fit, minmax(200px, 1fr))
+
+ +
+

Item Properties

+ + + + + + + + + +
PropertyValuesDescription
grid-columnstart / endColumn span
grid-rowstart / endRow span
grid-arearow-start / col-start / row-end / col-endShorthand for both
justify-selfstart, end, center, stretchHorizontal alignment
align-selfstart, end, center, stretchVertical alignment
+
+ +
+

Common Patterns

+
+
/* 3 equal columns */
+.grid {
+  display: grid;
+  grid-template-columns: repeat(3, 1fr);
+  gap: 1rem;
+}
+
+/* Responsive auto-fill */
+.responsive {
+  display: grid;
+  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
+  gap: 1rem;
+}
+
+/* Holy grail layout */
+.layout {
+  display: grid;
+  grid-template-columns: 200px 1fr 200px;
+  grid-template-rows: auto 1fr auto;
+  min-height: 100vh;
+}
+
+/* Span multiple cells */
+.wide {
+  grid-column: 1 / -1; /* Full width */
+}
+.tall {
+  grid-row: span 2; /* 2 rows */
+}
+
+
+ `, + + html: ` +

HTML Elements Reference

+

Semantic HTML elements that describe their meaning to browsers and assistive technologies.

+ +
+

Document Structure

+ + + + + + + + + + + + +
ElementPurposeExample
<html>Root element<html lang="en">
<head>Document metadataContains title, meta, links
<body>Document contentAll visible content
<header>Introductory contentLogo, nav, title
<nav>Navigation linksMain site navigation
<main>Main content (one per page)Primary page content
<footer>Footer contentCopyright, links
<aside>Sidebar/tangential contentRelated links, ads
+
+ +
+

Content Sectioning

+ + + + + + + + + +
ElementPurposeExample
<article>Self-contained contentBlog post, comment
<section>Thematic groupingChapter, tab panel
<h1>-<h6>Headings (hierarchy)One h1 per page, nest others
<p>ParagraphBlock of text
<div>Generic containerWhen no semantic element fits
+
+ +
+

Text Content

+ + + + + + + + + + + + +
ElementPurposeExample
<a>Hyperlink<a href="url">Link</a>
<strong>Important text (bold)<strong>Warning</strong>
<em>Emphasized text (italic)<em>really</em>
<code>Inline code<code>const x</code>
<pre>Preformatted textCode blocks
<span>Generic inline containerStyling inline text
<br>Line breakAddress, poem lines
<hr>Thematic breakScene change, topic shift
+
+ +
+

Lists

+ + + + + + + + + + +
ElementPurposeExample
<ul>Unordered listBulleted items
<ol>Ordered listNumbered steps
<li>List itemInside ul or ol
<dl>Description listTerm/definition pairs
<dt>Description termThe term being defined
<dd>Description detailsDefinition of the term
+
+ +
+

Forms

+ + + + + + + + + + + + +
ElementPurposeKey Attributes
<form>Form containeraction, method
<input>Input fieldtype, name, required, placeholder
<textarea>Multi-line textrows, cols, name
<select>Dropdown menuname, multiple
<option>Select optionvalue, selected
<button>Clickable buttontype (submit/button/reset)
<label>Input labelfor (matches input id)
<fieldset>Group form controlsWith legend for title
+
+ +
+

Media

+ + + + + + + + + + +
ElementPurposeKey Attributes
<img>Imagesrc, alt (required), width, height
<figure>Self-contained mediaContains img + figcaption
<figcaption>Figure captionDescription of figure
<video>Video playersrc, controls, autoplay
<audio>Audio playersrc, controls
<picture>Responsive imagesContains source + img
+
+ +
+

Tables

+ + + + + + + + + + + +
ElementPurposeNotes
<table>Table containerFor tabular data only
<thead>Table header groupContains header rows
<tbody>Table body groupContains data rows
<tfoot>Table footer groupSummary row
<tr>Table rowContains cells
<th>Header cellscope="col" or "row"
<td>Data cellcolspan, rowspan for spanning
+
+ ` +}; + // ================= URL ROUTING & PAGE SWITCHING ================= function initRouter() { @@ -1314,8 +1758,7 @@ function handleRoute(shouldUpdateUrl = true) { showSectionPage(route.sectionId); break; case RouteType.REFERENCE: - // Reference pages - TODO: implement later - showLandingPage(); + showReferencePage(route.refId); break; case RouteType.LESSON: navigateToLesson(route.moduleId, route.lessonIndex, shouldUpdateUrl); @@ -1333,6 +1776,7 @@ function handleRoute(shouldUpdateUrl = true) { function hideAllPages() { elements.landingPage?.classList.add("hidden"); elements.sectionPage?.classList.add("hidden"); + elements.referencePage?.classList.add("hidden"); elements.gameLayout?.classList.add("hidden"); } @@ -1420,6 +1864,63 @@ function showSectionPage(sectionId) { if (elements.sectionProgressText) elements.sectionProgressText.textContent = `${completed} of ${total} lessons complete`; } +/** + * Show reference/cheatsheet page + */ +function showReferencePage(refId) { + hideAllPages(); + elements.referencePage?.classList.remove("hidden"); + + // Default to CSS if no refId + const activeRef = refId || "css"; + + // Track reference page view + track("reference_view", { ref: activeRef }); + + // Update nav highlighting + const navLinks = elements.referenceNav?.querySelectorAll(".ref-nav-link"); + navLinks?.forEach((link) => { + link.classList.toggle("active", link.dataset.ref === activeRef); + }); + + // Load reference content + if (elements.referenceBody && referenceContent[activeRef]) { + elements.referenceBody.innerHTML = referenceContent[activeRef]; + // Highlight code blocks + highlightReferenceCodeBlocks(); + } else if (elements.referenceBody) { + elements.referenceBody.innerHTML = `

Reference for "${activeRef}" coming soon...

`; + } +} + +/** + * Highlight code blocks in reference pages with CodeMirror + */ +function highlightReferenceCodeBlocks() { + // Clean up previous views + sectionCodeViews.forEach((view) => view.destroy()); + sectionCodeViews = []; + + const codeBlocks = elements.referenceBody?.querySelectorAll("pre code"); + codeBlocks?.forEach((block) => { + const code = block.textContent; + const isHtml = block.classList.contains("language-html"); + const parent = block.parentElement; + + parent.innerHTML = ""; + parent.classList.add("cm-code-block"); + + const view = new EditorView({ + state: EditorState.create({ + doc: code, + extensions: [isHtml ? html() : css(), oneDark, readOnlyTheme, EditorState.readOnly.of(true), EditorView.editable.of(false)] + }), + parent + }); + sectionCodeViews.push(view); + }); +} + /** * Show lesson UI (game layout) */ diff --git a/src/index.html b/src/index.html index 43c412c..aef4a7a 100644 --- a/src/index.html +++ b/src/index.html @@ -135,6 +135,22 @@ + + +
diff --git a/src/main.css b/src/main.css index de0c7ba..5d9d840 100644 --- a/src/main.css +++ b/src/main.css @@ -1999,6 +1999,163 @@ input:checked + .toggle-slider::before { font-weight: 500; } +/* ================= REFERENCE PAGES ================= */ +.reference-page { + flex: 1; + overflow-y: auto; + background: var(--bg-color); +} + +.reference-content { + max-width: 900px; + margin: 0 auto; + padding: var(--spacing-lg); +} + +.reference-nav { + display: flex; + flex-wrap: wrap; + gap: var(--spacing-sm); + padding: var(--spacing-md); + background: var(--panel-bg); + border-radius: var(--border-radius-md); + margin-bottom: var(--spacing-lg); + position: sticky; + top: 0; + z-index: 10; + box-shadow: var(--shadow); +} + +.ref-nav-link { + padding: var(--spacing-xs) var(--spacing-sm); + border-radius: var(--border-radius-sm); + text-decoration: none; + color: var(--text-color); + font-size: 0.9rem; + font-weight: 500; + transition: background 0.2s, color 0.2s; +} + +.ref-nav-link:hover { + background: var(--hover-bg); +} + +.ref-nav-link.active { + background: var(--primary-color); + color: white; +} + +.reference-body h1 { + font-size: 1.75rem; + margin-bottom: var(--spacing-sm); + color: var(--primary-dark); +} + +.ref-intro { + font-size: 1rem; + color: var(--light-text); + margin-bottom: var(--spacing-lg); + line-height: 1.6; +} + +.ref-section { + margin-bottom: var(--spacing-xl); +} + +.ref-section h2 { + font-size: 1.2rem; + margin-bottom: var(--spacing-md); + color: var(--text-color); + border-bottom: 2px solid var(--border-color); + padding-bottom: var(--spacing-xs); +} + +.ref-table { + width: 100%; + border-collapse: collapse; + font-size: 0.9rem; + background: var(--panel-bg); + border-radius: var(--border-radius-md); + overflow: hidden; + box-shadow: var(--shadow); +} + +.ref-table thead { + background: var(--hover-bg); +} + +.ref-table th, +.ref-table td { + padding: var(--spacing-sm) var(--spacing-md); + text-align: left; + border-bottom: 1px solid var(--border-color); +} + +.ref-table th { + font-weight: 600; + color: var(--text-color); +} + +.ref-table tr:last-child td { + border-bottom: none; +} + +.ref-table tr:hover { + background: var(--hover-bg); +} + +.ref-table code { + background: var(--code-bg); + padding: 0.15rem 0.4rem; + border-radius: 4px; + font-size: 0.85em; + color: var(--primary-dark); +} + +.ref-list { + background: var(--panel-bg); + border-radius: var(--border-radius-md); + padding: var(--spacing-md) var(--spacing-md) var(--spacing-md) var(--spacing-xl); + box-shadow: var(--shadow); +} + +.ref-list li { + padding: var(--spacing-xs) 0; + line-height: 1.6; +} + +.ref-list code { + background: var(--code-bg); + padding: 0.15rem 0.4rem; + border-radius: 4px; + font-size: 0.85em; +} + +/* Reference page code blocks */ +.reference-body .code-block { + margin: var(--spacing-md) 0; +} + +/* Responsive reference tables */ +@media (max-width: 600px) { + .ref-table { + font-size: 0.8rem; + } + + .ref-table th, + .ref-table td { + padding: var(--spacing-xs) var(--spacing-sm); + } + + .reference-nav { + position: static; + } + + .ref-nav-link { + font-size: 0.8rem; + } +} + /* ================= UTILITY ================= */ .hidden { display: none !important;