Files
code-crispies/src/index.html
Michael Czechowski fbe0f20ef7 feat: add reset code confirmation dialog with skip option
- Add dialog to confirm resetting code to initial state
- Allow users to skip confirmation with "don't show again" checkbox
- Save preference to user settings
- Improve i18n and CodeEditor components
2026-01-07 14:16:45 +01:00

262 lines
12 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="./favicon.ico" type="image/x-icon" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="description"
content="Code Crispies - Free, open-source platform for learning HTML and CSS through hands-on exercises. Master semantic markup, selectors, flexbox, animations and more."
/>
<title>Code Crispies - Learn HTML & CSS Interactively</title>
<link rel="stylesheet" href="main.css" />
</head>
<body>
<a href="#main-content" class="skip-link" data-i18n="skipLink">Skip to main content</a>
<div class="app-container">
<header class="header">
<button id="menu-btn" class="menu-toggle" data-i18n-aria-label="menuOpen" aria-label="Open menu">
<span class="hamburger-icon"></span>
</button>
<a href="#" id="logo-link" class="logo">
<img src="./bowl.png" width="40" alt="CODE CRISPIES Logo" />
<h1><span class="code-text">CODE</span><span>CRISPIES</span></h1>
</a>
<div class="header-actions">
<button id="help-btn" class="help-toggle" data-i18n-aria-label="help" aria-label="Help">?</button>
</div>
</header>
<main class="game-layout" id="main-content">
<!-- Left Panel: Instructions + Editor -->
<div class="left-panel">
<section class="instructions">
<h2 id="lesson-title"></h2>
<div class="task-instruction" id="task-instruction"></div>
<div class="lesson-description" id="lesson-description"></div>
</section>
<section class="editor-section">
<div class="code-editor">
<div class="editor-header">
<label for="code-input" class="editor-label" data-i18n="editorLabel">CSS Editor</label>
<div class="editor-actions">
<div class="editor-tools">
<button id="undo-btn" class="btn btn-icon" data-i18n-title="undoTitle" title="Undo (Ctrl+Z)"></button>
<button id="redo-btn" class="btn btn-icon" data-i18n-title="redoTitle" title="Redo (Ctrl+Shift+Z)"></button>
<button
id="reset-code-btn"
class="btn btn-icon"
data-i18n-title="resetCodeTitle"
title="Reset to initial code"
>
</button>
</div>
<button id="run-btn" class="btn btn-run"><img src="./gear.svg" alt="" /><span data-i18n="run">Run</span></button>
</div>
</div>
<div class="editor-content">
<textarea id="code-input" class="code-input" spellcheck="false" autocomplete="off" style="display: none"></textarea>
</div>
</div>
<div class="hint-area" id="hint-area"></div>
</section>
</div>
<!-- Right Panel: Preview + Navigation -->
<div class="right-panel">
<div class="game-controls">
<button id="prev-btn" class="btn" data-i18n="previous">Previous</button>
<span class="module-pill" id="module-pill">
<span class="module-name"></span>
<span class="level-indicator" id="level-indicator"></span>
</span>
<button id="next-btn" class="btn btn-primary" data-i18n="next">Next</button>
</div>
<div class="preview-section">
<div class="preview-wrapper">
<div class="preview-frame" id="preview-area"></div>
<div class="expected-overlay" id="expected-overlay">
<div class="expected-frame" id="preview-expected"></div>
</div>
</div>
<div class="preview-header">
<span class="preview-label" data-i18n="yourOutput">Your Output</span>
<button id="show-expected-btn" class="btn btn-small" data-i18n="showExpected">Show Expected</button>
</div>
</div>
</div>
</main>
<!-- Sidebar Backdrop -->
<div class="sidebar-backdrop" id="sidebar-backdrop"></div>
<!-- Slide-out Sidebar -->
<aside class="sidebar-drawer" id="sidebar-drawer" data-i18n-aria-label="menu" aria-label="Menu">
<div class="sidebar-header">
<h3 data-i18n="menu">Menu</h3>
<button id="close-sidebar" class="close-btn" data-i18n-aria-label="closeMenu" aria-label="Close menu">&times;</button>
</div>
<div class="sidebar-section">
<h4 data-i18n="progress">Progress</h4>
<div class="progress-display" id="progress-display">
<div class="progress-bar">
<div class="progress-fill" id="progress-fill"></div>
</div>
<span class="progress-text" id="progress-text">0% Complete</span>
</div>
</div>
<nav class="sidebar-section" aria-label="Lesson navigation">
<h4 id="lessons-heading" data-i18n="lessons">Lessons</h4>
<div class="module-list" id="module-list" role="tree" aria-labelledby="lessons-heading"></div>
</nav>
<div class="sidebar-section">
<h4 data-i18n="settings">Settings</h4>
<label class="setting-row">
<span class="setting-label" data-i18n="language">Language</span>
<select id="lang-select" class="lang-select">
<option value="en">English</option>
<option value="de">Deutsch</option>
<option value="pl">Polski</option>
<option value="es">Español</option>
<option value="ar">العربية</option>
<option value="uk">Українська</option>
</select>
</label>
<label class="toggle-switch">
<input type="checkbox" id="disable-feedback-toggle" checked />
<span class="toggle-slider"></span>
<span class="toggle-label" data-i18n="showHints">Show Hints</span>
</label>
<button id="reset-btn" class="btn btn-text" data-i18n="resetAllProgress">Reset All Progress</button>
</div>
<footer class="app-footer">
<span data-i18n="openSource">Open Source:</span>
<a href="https://git.librete.ch/libretech/code-crispies" target="_blank">Gitea</a>
<span data-i18n="by">by</span> <a href="https://librete.ch" title="LibreTECH">LibreTECH</a>
</footer>
</aside>
<!-- Help Dialog -->
<dialog id="help-dialog" class="dialog">
<div class="dialog-header">
<h3 data-i18n="helpTitle">Help</h3>
<button id="help-dialog-close" class="dialog-close" aria-label="Close">&times;</button>
</div>
<div class="dialog-content">
<h4 data-i18n="aboutTitle">About Code Crispies</h4>
<p data-i18n="aboutText">
Code Crispies is a free, open-source platform for learning web development through hands-on exercises. No account required -
just start coding!
</p>
<h4 data-i18n="learningModesTitle">Learning Modes</h4>
<ul>
<li data-i18n-html="modeCss"><strong>CSS</strong> - Write CSS rules to style elements</li>
<li data-i18n-html="modeTailwind"><strong>Tailwind</strong> - Apply utility classes directly in HTML</li>
<li data-i18n-html="modeHtml"><strong>HTML</strong> - Practice semantic markup and native elements</li>
</ul>
<h4 data-i18n="gettingStartedTitle">Getting Started</h4>
<p data-i18n="gettingStartedText">
Open the menu (☰) to browse lesson modules. Each module covers a specific topic with progressive exercises.
</p>
<h4 data-i18n="completingLessonsTitle">Completing Lessons</h4>
<ol>
<li data-i18n="completingStep1">Read the task instructions on the left</li>
<li data-i18n="completingStep2">Write your code in the editor</li>
<li data-i18n="completingStep3">Watch the live preview update as you type</li>
<li data-i18n="completingStep4">Follow hints to fix any issues</li>
<li data-i18n-html="completingStep5">Click <strong>Next</strong> when complete</li>
</ol>
<h4 data-i18n="editorToolsTitle">Editor Tools</h4>
<ul>
<li data-i18n-html="editorToolUndo"><strong>↶ Undo</strong> / <strong>↷ Redo</strong> - Navigate edit history</li>
<li data-i18n-html="editorToolReset"><strong>⟲ Reset</strong> - Restore initial code for current lesson</li>
<li data-i18n-html="editorToolExpected"><strong>Show Expected</strong> - Toggle the target result overlay</li>
</ul>
<h4 data-i18n="keyboardShortcutsTitle">Keyboard Shortcuts</h4>
<ul>
<li data-i18n-html="shortcutUndo"><kbd>Ctrl+Z</kbd> - Undo</li>
<li data-i18n-html="shortcutRedo"><kbd>Ctrl+Shift+Z</kbd> - Redo</li>
</ul>
<h4 data-i18n="emmetTitle">Emmet Shortcuts (HTML mode)</h4>
<p data-i18n-html="emmetText">Type abbreviations and press <kbd>Tab</kbd> to expand:</p>
<ul>
<li data-i18n-html="emmetClass"><kbd>div.box</kbd> → div with class</li>
<li data-i18n-html="emmetChildren"><kbd>ul>li*3</kbd> → ul with 3 li children</li>
<li data-i18n-html="emmetNested"><kbd>form>input+button</kbd> → nested structure</li>
<li data-i18n-html="emmetContent"><kbd>p{Hello}</kbd> → p with text content</li>
</ul>
<h4 data-i18n="moreProjectsTitle">More Projects</h4>
<div class="project-cards">
<a href="https://nextlevelshit.github.io/html-over-js/" target="_blank" class="project-card">
<strong>HTML over JS</strong>
<span data-i18n="htmlOverJsDesc"> - Learn to leverage native HTML elements instead of custom JavaScript solutions</span>
</a>
<a href="https://nextlevelshit.github.io/web-engineering-mandala/" target="_blank" class="project-card">
<strong>Web Engineering Mandala</strong>
<span data-i18n="mandalaDesc"> - Interactive visualization of JavaScript technologies organized by complexity</span>
</a>
</div>
<h4 data-i18n="contactTitle">Contact & Links</h4>
<p data-i18n-html="contactText">Code Crispies is developed by <a href="https://librete.ch" target="_blank">LibreTECH</a></p>
<ul>
<li><a href="https://git.librete.ch/libretech/code-crispies" target="_blank">Gitea</a> Self-hosted source repository</li>
<li><a href="https://github.com/nextlevelshit/code-crispies" target="_blank">GitHub</a> Public mirror</li>
<li><a href="https://www.linkedin.com/in/michael-werner-czechowski" target="_blank">LinkedIn</a> Michael Czechowski</li>
</ul>
</div>
</dialog>
<!-- Reset Code Confirmation Dialog -->
<dialog id="reset-code-dialog" class="dialog">
<div class="dialog-header">
<h3 data-i18n="resetCodeDialogTitle">Reset Code</h3>
<button id="reset-code-dialog-close" class="dialog-close" aria-label="Close">&times;</button>
</div>
<div class="dialog-content">
<p data-i18n="resetCodeDialogText">Reset your code to the initial state for this lesson?</p>
<label class="toggle-switch" style="margin: 1rem 0">
<input type="checkbox" id="reset-code-dont-show" />
<span class="toggle-slider"></span>
<span class="toggle-label" data-i18n="dontShowAgain">Don't show this again</span>
</label>
<div class="dialog-actions">
<button id="cancel-reset-code" class="btn" data-i18n="cancel">Cancel</button>
<button id="confirm-reset-code" class="btn btn-ghost" data-i18n="reset">Reset</button>
</div>
</div>
</dialog>
<!-- Reset Confirmation Dialog -->
<dialog id="reset-dialog" class="dialog">
<div class="dialog-header">
<h3 data-i18n="resetDialogTitle">Reset Progress</h3>
<button id="reset-dialog-close" class="dialog-close" aria-label="Close">&times;</button>
</div>
<div class="dialog-content">
<p data-i18n="resetDialogText">Are you sure you want to reset all your progress? This cannot be undone.</p>
<div class="dialog-actions">
<button id="cancel-reset" class="btn" data-i18n="cancel">Cancel</button>
<button id="confirm-reset" class="btn btn-ghost" data-i18n="resetAll">Reset All</button>
</div>
</div>
</dialog>
</div>
<script type="module" src="app.js"></script>
</body>
</html>