feat: implement reference/cheatsheet pages
- 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)
This commit is contained in:
505
src/app.js
505
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: `
|
||||
<h1>CSS Properties Reference</h1>
|
||||
<p class="ref-intro">Quick reference for commonly used CSS properties. Click any property to see syntax and examples.</p>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Colors & Backgrounds</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Property</th><th>Values</th><th>Example</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>color</code></td><td>named, hex, rgb(), hsl()</td><td><code>color: steelblue;</code></td></tr>
|
||||
<tr><td><code>background</code></td><td>color, image, gradient</td><td><code>background: #f0f0f0;</code></td></tr>
|
||||
<tr><td><code>background-color</code></td><td>color value</td><td><code>background-color: white;</code></td></tr>
|
||||
<tr><td><code>background-image</code></td><td>url(), gradient</td><td><code>background-image: url(bg.png);</code></td></tr>
|
||||
<tr><td><code>opacity</code></td><td>0 to 1</td><td><code>opacity: 0.8;</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Typography</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Property</th><th>Values</th><th>Example</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>font-family</code></td><td>font name, generic</td><td><code>font-family: system-ui, sans-serif;</code></td></tr>
|
||||
<tr><td><code>font-size</code></td><td>px, rem, em, %</td><td><code>font-size: 1rem;</code></td></tr>
|
||||
<tr><td><code>font-weight</code></td><td>normal, bold, 100-900</td><td><code>font-weight: 600;</code></td></tr>
|
||||
<tr><td><code>line-height</code></td><td>number, length, %</td><td><code>line-height: 1.5;</code></td></tr>
|
||||
<tr><td><code>text-align</code></td><td>left, center, right, justify</td><td><code>text-align: center;</code></td></tr>
|
||||
<tr><td><code>text-decoration</code></td><td>none, underline, line-through</td><td><code>text-decoration: none;</code></td></tr>
|
||||
<tr><td><code>text-transform</code></td><td>none, uppercase, lowercase, capitalize</td><td><code>text-transform: uppercase;</code></td></tr>
|
||||
<tr><td><code>letter-spacing</code></td><td>length</td><td><code>letter-spacing: 0.05em;</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Box Model</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Property</th><th>Values</th><th>Example</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>width</code></td><td>length, %, auto, fit-content</td><td><code>width: 100%;</code></td></tr>
|
||||
<tr><td><code>height</code></td><td>length, %, auto</td><td><code>height: 200px;</code></td></tr>
|
||||
<tr><td><code>max-width</code></td><td>length, %, none</td><td><code>max-width: 600px;</code></td></tr>
|
||||
<tr><td><code>padding</code></td><td>length (1-4 values)</td><td><code>padding: 1rem 2rem;</code></td></tr>
|
||||
<tr><td><code>margin</code></td><td>length, auto (1-4 values)</td><td><code>margin: 0 auto;</code></td></tr>
|
||||
<tr><td><code>border</code></td><td>width style color</td><td><code>border: 1px solid gray;</code></td></tr>
|
||||
<tr><td><code>border-radius</code></td><td>length (1-4 values)</td><td><code>border-radius: 8px;</code></td></tr>
|
||||
<tr><td><code>box-sizing</code></td><td>content-box, border-box</td><td><code>box-sizing: border-box;</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Layout</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Property</th><th>Values</th><th>Example</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>display</code></td><td>block, inline, flex, grid, none</td><td><code>display: flex;</code></td></tr>
|
||||
<tr><td><code>position</code></td><td>static, relative, absolute, fixed, sticky</td><td><code>position: relative;</code></td></tr>
|
||||
<tr><td><code>top/right/bottom/left</code></td><td>length, %, auto</td><td><code>top: 0; left: 50%;</code></td></tr>
|
||||
<tr><td><code>z-index</code></td><td>integer, auto</td><td><code>z-index: 10;</code></td></tr>
|
||||
<tr><td><code>overflow</code></td><td>visible, hidden, scroll, auto</td><td><code>overflow: auto;</code></td></tr>
|
||||
<tr><td><code>float</code></td><td>none, left, right</td><td><code>float: left;</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Visual Effects</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Property</th><th>Values</th><th>Example</th></tr></thead>
|
||||
<tbody>
|
||||
<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>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>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
`,
|
||||
|
||||
selectors: `
|
||||
<h1>CSS Selectors Reference</h1>
|
||||
<p class="ref-intro">Selectors determine which HTML elements your styles apply to. More specific selectors override less specific ones.</p>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Basic Selectors</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Selector</th><th>Description</th><th>Example</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>element</code></td><td>All elements of type</td><td><code>p { ... }</code></td></tr>
|
||||
<tr><td><code>.class</code></td><td>Elements with class</td><td><code>.btn { ... }</code></td></tr>
|
||||
<tr><td><code>#id</code></td><td>Element with ID</td><td><code>#header { ... }</code></td></tr>
|
||||
<tr><td><code>*</code></td><td>All elements</td><td><code>* { box-sizing: border-box; }</code></td></tr>
|
||||
<tr><td><code>[attr]</code></td><td>Elements with attribute</td><td><code>[disabled] { ... }</code></td></tr>
|
||||
<tr><td><code>[attr="value"]</code></td><td>Attribute equals value</td><td><code>[type="text"] { ... }</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Combinators</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Selector</th><th>Description</th><th>Example</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>A B</code></td><td>B inside A (descendant)</td><td><code>nav a { ... }</code></td></tr>
|
||||
<tr><td><code>A > B</code></td><td>B direct child of A</td><td><code>ul > li { ... }</code></td></tr>
|
||||
<tr><td><code>A + B</code></td><td>B immediately after A</td><td><code>h2 + p { ... }</code></td></tr>
|
||||
<tr><td><code>A ~ B</code></td><td>B after A (sibling)</td><td><code>h2 ~ p { ... }</code></td></tr>
|
||||
<tr><td><code>A, B</code></td><td>A or B (grouping)</td><td><code>h1, h2, h3 { ... }</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Pseudo-classes</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Selector</th><th>Description</th><th>Example</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>:hover</code></td><td>Mouse over element</td><td><code>a:hover { color: blue; }</code></td></tr>
|
||||
<tr><td><code>:focus</code></td><td>Element has focus</td><td><code>input:focus { outline: 2px solid; }</code></td></tr>
|
||||
<tr><td><code>:active</code></td><td>Being clicked</td><td><code>button:active { transform: scale(0.98); }</code></td></tr>
|
||||
<tr><td><code>:first-child</code></td><td>First child element</td><td><code>li:first-child { ... }</code></td></tr>
|
||||
<tr><td><code>:last-child</code></td><td>Last child element</td><td><code>li:last-child { ... }</code></td></tr>
|
||||
<tr><td><code>:nth-child(n)</code></td><td>nth child (1-based)</td><td><code>tr:nth-child(odd) { ... }</code></td></tr>
|
||||
<tr><td><code>:not(sel)</code></td><td>Elements not matching</td><td><code>:not(.hidden) { ... }</code></td></tr>
|
||||
<tr><td><code>:checked</code></td><td>Checked inputs</td><td><code>input:checked { ... }</code></td></tr>
|
||||
<tr><td><code>:disabled</code></td><td>Disabled form elements</td><td><code>button:disabled { opacity: 0.5; }</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Pseudo-elements</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Selector</th><th>Description</th><th>Example</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>::before</code></td><td>Insert before content</td><td><code>.icon::before { content: "→"; }</code></td></tr>
|
||||
<tr><td><code>::after</code></td><td>Insert after content</td><td><code>.link::after { content: "↗"; }</code></td></tr>
|
||||
<tr><td><code>::first-letter</code></td><td>First letter of text</td><td><code>p::first-letter { font-size: 2em; }</code></td></tr>
|
||||
<tr><td><code>::first-line</code></td><td>First line of text</td><td><code>p::first-line { font-weight: bold; }</code></td></tr>
|
||||
<tr><td><code>::placeholder</code></td><td>Input placeholder text</td><td><code>input::placeholder { color: gray; }</code></td></tr>
|
||||
<tr><td><code>::selection</code></td><td>Selected/highlighted text</td><td><code>::selection { background: yellow; }</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Specificity (Highest to Lowest)</h2>
|
||||
<ol class="ref-list">
|
||||
<li><strong>Inline styles</strong> - <code>style="..."</code> attribute (1000 points)</li>
|
||||
<li><strong>ID selectors</strong> - <code>#id</code> (100 points)</li>
|
||||
<li><strong>Class/pseudo-class/attribute</strong> - <code>.class</code>, <code>:hover</code>, <code>[attr]</code> (10 points)</li>
|
||||
<li><strong>Element/pseudo-element</strong> - <code>div</code>, <code>::before</code> (1 point)</li>
|
||||
<li><strong>Universal selector</strong> - <code>*</code> (0 points)</li>
|
||||
</ol>
|
||||
</section>
|
||||
`,
|
||||
|
||||
flexbox: `
|
||||
<h1>Flexbox Reference</h1>
|
||||
<p class="ref-intro">Flexbox is a one-dimensional layout system. Apply <code>display: flex</code> to a container, and its children become flex items.</p>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Container Properties</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Property</th><th>Values</th><th>Description</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>display</code></td><td>flex, inline-flex</td><td>Enable flex container</td></tr>
|
||||
<tr><td><code>flex-direction</code></td><td>row, row-reverse, column, column-reverse</td><td>Main axis direction</td></tr>
|
||||
<tr><td><code>flex-wrap</code></td><td>nowrap, wrap, wrap-reverse</td><td>Allow items to wrap</td></tr>
|
||||
<tr><td><code>justify-content</code></td><td>flex-start, flex-end, center, space-between, space-around, space-evenly</td><td>Main axis alignment</td></tr>
|
||||
<tr><td><code>align-items</code></td><td>stretch, flex-start, flex-end, center, baseline</td><td>Cross axis alignment</td></tr>
|
||||
<tr><td><code>align-content</code></td><td>stretch, flex-start, flex-end, center, space-between, space-around</td><td>Multi-line alignment</td></tr>
|
||||
<tr><td><code>gap</code></td><td>length</td><td>Space between items</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Item Properties</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Property</th><th>Values</th><th>Description</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>flex-grow</code></td><td>number (default: 0)</td><td>How much item grows</td></tr>
|
||||
<tr><td><code>flex-shrink</code></td><td>number (default: 1)</td><td>How much item shrinks</td></tr>
|
||||
<tr><td><code>flex-basis</code></td><td>length, auto</td><td>Initial size before grow/shrink</td></tr>
|
||||
<tr><td><code>flex</code></td><td>grow shrink basis</td><td>Shorthand (e.g., <code>flex: 1</code>)</td></tr>
|
||||
<tr><td><code>align-self</code></td><td>auto, flex-start, flex-end, center, stretch</td><td>Override align-items</td></tr>
|
||||
<tr><td><code>order</code></td><td>integer (default: 0)</td><td>Visual order of item</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Common Patterns</h2>
|
||||
<div class="code-block">
|
||||
<pre><code>/* 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; }</code></pre>
|
||||
</div>
|
||||
</section>
|
||||
`,
|
||||
|
||||
grid: `
|
||||
<h1>CSS Grid Reference</h1>
|
||||
<p class="ref-intro">CSS Grid is a two-dimensional layout system for complex row and column layouts. Apply <code>display: grid</code> to a container.</p>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Container Properties</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Property</th><th>Values</th><th>Description</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>display</code></td><td>grid, inline-grid</td><td>Enable grid container</td></tr>
|
||||
<tr><td><code>grid-template-columns</code></td><td>track sizes</td><td>Define column widths</td></tr>
|
||||
<tr><td><code>grid-template-rows</code></td><td>track sizes</td><td>Define row heights</td></tr>
|
||||
<tr><td><code>gap</code></td><td>length</td><td>Space between cells</td></tr>
|
||||
<tr><td><code>justify-items</code></td><td>start, end, center, stretch</td><td>Horizontal alignment in cells</td></tr>
|
||||
<tr><td><code>align-items</code></td><td>start, end, center, stretch</td><td>Vertical alignment in cells</td></tr>
|
||||
<tr><td><code>justify-content</code></td><td>start, end, center, space-between, space-around</td><td>Horizontal grid alignment</td></tr>
|
||||
<tr><td><code>align-content</code></td><td>start, end, center, space-between, space-around</td><td>Vertical grid alignment</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Track Sizing</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Value</th><th>Description</th><th>Example</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>px, rem, %</code></td><td>Fixed or relative sizes</td><td><code>200px 1rem 50%</code></td></tr>
|
||||
<tr><td><code>fr</code></td><td>Fraction of available space</td><td><code>1fr 2fr 1fr</code></td></tr>
|
||||
<tr><td><code>auto</code></td><td>Size to content</td><td><code>auto 1fr auto</code></td></tr>
|
||||
<tr><td><code>minmax(min, max)</code></td><td>Size range</td><td><code>minmax(100px, 1fr)</code></td></tr>
|
||||
<tr><td><code>repeat(n, size)</code></td><td>Repeat n times</td><td><code>repeat(3, 1fr)</code></td></tr>
|
||||
<tr><td><code>repeat(auto-fill, ...)</code></td><td>Fill available space</td><td><code>repeat(auto-fill, minmax(200px, 1fr))</code></td></tr>
|
||||
<tr><td><code>repeat(auto-fit, ...)</code></td><td>Fill and stretch</td><td><code>repeat(auto-fit, minmax(200px, 1fr))</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Item Properties</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Property</th><th>Values</th><th>Description</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>grid-column</code></td><td>start / end</td><td>Column span</td></tr>
|
||||
<tr><td><code>grid-row</code></td><td>start / end</td><td>Row span</td></tr>
|
||||
<tr><td><code>grid-area</code></td><td>row-start / col-start / row-end / col-end</td><td>Shorthand for both</td></tr>
|
||||
<tr><td><code>justify-self</code></td><td>start, end, center, stretch</td><td>Horizontal alignment</td></tr>
|
||||
<tr><td><code>align-self</code></td><td>start, end, center, stretch</td><td>Vertical alignment</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Common Patterns</h2>
|
||||
<div class="code-block">
|
||||
<pre><code>/* 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 */
|
||||
}</code></pre>
|
||||
</div>
|
||||
</section>
|
||||
`,
|
||||
|
||||
html: `
|
||||
<h1>HTML Elements Reference</h1>
|
||||
<p class="ref-intro">Semantic HTML elements that describe their meaning to browsers and assistive technologies.</p>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Document Structure</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Element</th><th>Purpose</th><th>Example</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code><html></code></td><td>Root element</td><td><code><html lang="en"></code></td></tr>
|
||||
<tr><td><code><head></code></td><td>Document metadata</td><td>Contains title, meta, links</td></tr>
|
||||
<tr><td><code><body></code></td><td>Document content</td><td>All visible content</td></tr>
|
||||
<tr><td><code><header></code></td><td>Introductory content</td><td>Logo, nav, title</td></tr>
|
||||
<tr><td><code><nav></code></td><td>Navigation links</td><td>Main site navigation</td></tr>
|
||||
<tr><td><code><main></code></td><td>Main content (one per page)</td><td>Primary page content</td></tr>
|
||||
<tr><td><code><footer></code></td><td>Footer content</td><td>Copyright, links</td></tr>
|
||||
<tr><td><code><aside></code></td><td>Sidebar/tangential content</td><td>Related links, ads</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Content Sectioning</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Element</th><th>Purpose</th><th>Example</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code><article></code></td><td>Self-contained content</td><td>Blog post, comment</td></tr>
|
||||
<tr><td><code><section></code></td><td>Thematic grouping</td><td>Chapter, tab panel</td></tr>
|
||||
<tr><td><code><h1>-<h6></code></td><td>Headings (hierarchy)</td><td>One h1 per page, nest others</td></tr>
|
||||
<tr><td><code><p></code></td><td>Paragraph</td><td>Block of text</td></tr>
|
||||
<tr><td><code><div></code></td><td>Generic container</td><td>When no semantic element fits</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Text Content</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Element</th><th>Purpose</th><th>Example</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code><a></code></td><td>Hyperlink</td><td><code><a href="url">Link</a></code></td></tr>
|
||||
<tr><td><code><strong></code></td><td>Important text (bold)</td><td><code><strong>Warning</strong></code></td></tr>
|
||||
<tr><td><code><em></code></td><td>Emphasized text (italic)</td><td><code><em>really</em></code></td></tr>
|
||||
<tr><td><code><code></code></td><td>Inline code</td><td><code><code>const x</code></code></td></tr>
|
||||
<tr><td><code><pre></code></td><td>Preformatted text</td><td>Code blocks</td></tr>
|
||||
<tr><td><code><span></code></td><td>Generic inline container</td><td>Styling inline text</td></tr>
|
||||
<tr><td><code><br></code></td><td>Line break</td><td>Address, poem lines</td></tr>
|
||||
<tr><td><code><hr></code></td><td>Thematic break</td><td>Scene change, topic shift</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Lists</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Element</th><th>Purpose</th><th>Example</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code><ul></code></td><td>Unordered list</td><td>Bulleted items</td></tr>
|
||||
<tr><td><code><ol></code></td><td>Ordered list</td><td>Numbered steps</td></tr>
|
||||
<tr><td><code><li></code></td><td>List item</td><td>Inside ul or ol</td></tr>
|
||||
<tr><td><code><dl></code></td><td>Description list</td><td>Term/definition pairs</td></tr>
|
||||
<tr><td><code><dt></code></td><td>Description term</td><td>The term being defined</td></tr>
|
||||
<tr><td><code><dd></code></td><td>Description details</td><td>Definition of the term</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Forms</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Element</th><th>Purpose</th><th>Key Attributes</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code><form></code></td><td>Form container</td><td>action, method</td></tr>
|
||||
<tr><td><code><input></code></td><td>Input field</td><td>type, name, required, placeholder</td></tr>
|
||||
<tr><td><code><textarea></code></td><td>Multi-line text</td><td>rows, cols, name</td></tr>
|
||||
<tr><td><code><select></code></td><td>Dropdown menu</td><td>name, multiple</td></tr>
|
||||
<tr><td><code><option></code></td><td>Select option</td><td>value, selected</td></tr>
|
||||
<tr><td><code><button></code></td><td>Clickable button</td><td>type (submit/button/reset)</td></tr>
|
||||
<tr><td><code><label></code></td><td>Input label</td><td>for (matches input id)</td></tr>
|
||||
<tr><td><code><fieldset></code></td><td>Group form controls</td><td>With legend for title</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Media</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Element</th><th>Purpose</th><th>Key Attributes</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code><img></code></td><td>Image</td><td>src, alt (required), width, height</td></tr>
|
||||
<tr><td><code><figure></code></td><td>Self-contained media</td><td>Contains img + figcaption</td></tr>
|
||||
<tr><td><code><figcaption></code></td><td>Figure caption</td><td>Description of figure</td></tr>
|
||||
<tr><td><code><video></code></td><td>Video player</td><td>src, controls, autoplay</td></tr>
|
||||
<tr><td><code><audio></code></td><td>Audio player</td><td>src, controls</td></tr>
|
||||
<tr><td><code><picture></code></td><td>Responsive images</td><td>Contains source + img</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="ref-section">
|
||||
<h2>Tables</h2>
|
||||
<table class="ref-table">
|
||||
<thead><tr><th>Element</th><th>Purpose</th><th>Notes</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code><table></code></td><td>Table container</td><td>For tabular data only</td></tr>
|
||||
<tr><td><code><thead></code></td><td>Table header group</td><td>Contains header rows</td></tr>
|
||||
<tr><td><code><tbody></code></td><td>Table body group</td><td>Contains data rows</td></tr>
|
||||
<tr><td><code><tfoot></code></td><td>Table footer group</td><td>Summary row</td></tr>
|
||||
<tr><td><code><tr></code></td><td>Table row</td><td>Contains cells</td></tr>
|
||||
<tr><td><code><th></code></td><td>Header cell</td><td>scope="col" or "row"</td></tr>
|
||||
<tr><td><code><td></code></td><td>Data cell</td><td>colspan, rowspan for spanning</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
`
|
||||
};
|
||||
|
||||
// ================= 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 = `<p>Reference for "${activeRef}" coming soon...</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
|
||||
@@ -135,6 +135,22 @@
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<!-- Reference/Cheatsheet Pages -->
|
||||
<div class="reference-page hidden" id="reference-page">
|
||||
<article class="reference-content">
|
||||
<nav class="reference-nav" id="reference-nav">
|
||||
<a href="#reference/css" class="ref-nav-link" data-ref="css">CSS Properties</a>
|
||||
<a href="#reference/selectors" class="ref-nav-link" data-ref="selectors">Selectors</a>
|
||||
<a href="#reference/flexbox" class="ref-nav-link" data-ref="flexbox">Flexbox</a>
|
||||
<a href="#reference/grid" class="ref-nav-link" data-ref="grid">Grid</a>
|
||||
<a href="#reference/html" class="ref-nav-link" data-ref="html">HTML Elements</a>
|
||||
</nav>
|
||||
<div class="reference-body" id="reference-body">
|
||||
<!-- Reference content injected by JS -->
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<main class="game-layout" id="main-content">
|
||||
<!-- Left Panel: Instructions + Editor -->
|
||||
<div class="left-panel">
|
||||
|
||||
157
src/main.css
157
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;
|
||||
|
||||
Reference in New Issue
Block a user