diff --git a/src/app.de.js b/src/app.de.js
index 05221e0..54e260a 100644
--- a/src/app.de.js
+++ b/src/app.de.js
@@ -49,11 +49,13 @@ const elements = {
resetBtn: document.getElementById("reset-btn"),
disableFeedbackToggle: document.getElementById("disable-feedback-toggle"),
- // Modal
- modalContainer: document.getElementById("modal-container"),
- modalTitle: document.getElementById("modal-title"),
- modalContent: document.getElementById("modal-content"),
- modalClose: document.getElementById("modal-close")
+ // Dialogs
+ helpDialog: document.getElementById("help-dialog"),
+ helpDialogClose: document.getElementById("help-dialog-close"),
+ resetDialog: document.getElementById("reset-dialog"),
+ resetDialogClose: document.getElementById("reset-dialog-close"),
+ cancelReset: document.getElementById("cancel-reset"),
+ confirmReset: document.getElementById("confirm-reset")
};
// Initialize the lesson engine - now the single source of truth
@@ -448,78 +450,36 @@ function runCode() {
}
}
-// ================= MODALS =================
+// ================= DIALOGS =================
function showHelp() {
- elements.modalTitle.textContent = "Hilfe";
+ elements.helpDialog.showModal();
+}
- elements.modalContent.innerHTML = `
-
So verwendest du Code Crispies
- Code Crispies ist eine interaktive Plattform zum Erlernen von HTML, CSS und Tailwind durch praktische Übungen.
-
- Erste Schritte
- Öffne das Menü (☰), um ein Lektionsmodul auszuwählen. Jedes Modul enthält eine Reihe von Lektionen.
-
- Lektionen abschließen
-
- - Lies die Anleitung auf der linken Seite
- - Schreibe deinen Code im Editor
- - Klicke auf "Ausführen" oder drücke Strg+Enter zum Testen
- - Folge den Hinweisen, um Probleme zu beheben
- - Klicke auf "Weiter", wenn du fertig bist
-
-
- Tipps
-
- - Klicke auf "Lösung zeigen", um das Zielergebnis zu sehen
- - Dein Fortschritt wird automatisch gespeichert
- - Strg+Enter führt deinen Code aus
-
-
- Emmet-Kürzel (HTML-Modus)
- Tippe Abkürzungen ein und drücke Tab zum Erweitern:
-
- - div.container → div mit Klasse
- - ul>li*5 → ul mit 5 li-Kindern
- - nav>ul>li*3>a → verschachtelte Struktur
- - p{Hallo} → p mit Textinhalt
-
- `;
-
- elements.modalContainer.classList.remove("hidden");
+function closeHelpDialog() {
+ elements.helpDialog.close();
}
function showResetConfirmation() {
- elements.modalTitle.textContent = "Fortschritt zurücksetzen";
-
- elements.modalContent.innerHTML = `
- Bist du sicher, dass du deinen gesamten Fortschritt zurücksetzen möchtest? Dies kann nicht rückgängig gemacht werden.
-
-
-
-
- `;
-
- document.getElementById("cancel-reset").addEventListener("click", closeModal);
- document.getElementById("confirm-reset").addEventListener("click", () => {
- lessonEngine.clearProgress();
- closeModal();
- closeSidebar();
-
- // Reload first module
- const modules = lessonEngine.modules;
- if (modules.length > 0) {
- selectModule(modules[0].id);
- }
-
- updateProgressDisplay();
- });
-
- elements.modalContainer.classList.remove("hidden");
+ elements.resetDialog.showModal();
}
-function closeModal() {
- elements.modalContainer.classList.add("hidden");
+function closeResetDialog() {
+ elements.resetDialog.close();
+}
+
+function handleResetConfirm() {
+ lessonEngine.clearProgress();
+ closeResetDialog();
+ closeSidebar();
+
+ // Reload first module
+ const modules = lessonEngine.modules;
+ if (modules.length > 0) {
+ selectModule(modules[0].id);
+ }
+
+ updateProgressDisplay();
}
// ================= INITIALIZATION =================
@@ -575,10 +535,13 @@ function init() {
});
elements.resetCodeBtn.addEventListener("click", resetCode);
- // Modals
+ // Dialogs
elements.helpBtn.addEventListener("click", showHelp);
- elements.modalClose.addEventListener("click", closeModal);
+ elements.helpDialogClose.addEventListener("click", closeHelpDialog);
elements.resetBtn.addEventListener("click", showResetConfirmation);
+ elements.resetDialogClose.addEventListener("click", closeResetDialog);
+ elements.cancelReset.addEventListener("click", closeResetDialog);
+ elements.confirmReset.addEventListener("click", handleResetConfirm);
// Settings
elements.disableFeedbackToggle.addEventListener("change", (e) => {
@@ -599,10 +562,9 @@ function init() {
e.preventDefault();
}
- // Escape to close sidebar
+ // Escape to close sidebar (dialogs handle Escape natively)
if (e.key === "Escape") {
closeSidebar();
- closeModal();
}
});
}
diff --git a/src/app.js b/src/app.js
index a42b80a..d82b528 100644
--- a/src/app.js
+++ b/src/app.js
@@ -49,11 +49,13 @@ const elements = {
resetBtn: document.getElementById("reset-btn"),
disableFeedbackToggle: document.getElementById("disable-feedback-toggle"),
- // Modal
- modalContainer: document.getElementById("modal-container"),
- modalTitle: document.getElementById("modal-title"),
- modalContent: document.getElementById("modal-content"),
- modalClose: document.getElementById("modal-close")
+ // Dialogs
+ helpDialog: document.getElementById("help-dialog"),
+ helpDialogClose: document.getElementById("help-dialog-close"),
+ resetDialog: document.getElementById("reset-dialog"),
+ resetDialogClose: document.getElementById("reset-dialog-close"),
+ cancelReset: document.getElementById("cancel-reset"),
+ confirmReset: document.getElementById("confirm-reset")
};
// Initialize the lesson engine - now the single source of truth
@@ -448,78 +450,36 @@ function runCode() {
}
}
-// ================= MODALS =================
+// ================= DIALOGS =================
function showHelp() {
- elements.modalTitle.textContent = "Help";
+ elements.helpDialog.showModal();
+}
- elements.modalContent.innerHTML = `
- How to Use Code Crispies
- Code Crispies is an interactive platform for learning HTML, CSS, and Tailwind through practical exercises.
-
- Getting Started
- Open the menu (☰) to select a lesson module. Each module contains a series of lessons.
-
- Completing Lessons
-
- - Read the instructions on the left
- - Write your code in the editor
- - Click "Run" or press Ctrl+Enter to test
- - Follow the hints to fix any issues
- - Click "Next" when you're done
-
-
- Tips
-
- - Click "Show Expected" to see the target result
- - Your progress is saved automatically
- - Ctrl+Enter runs your code
-
-
- Emmet Shortcuts (HTML mode)
- Type abbreviations and press Tab to expand:
-
- - div.container → div with class
- - ul>li*5 → ul with 5 li children
- - nav>ul>li*3>a → nested structure
- - p{Hello} → p with text content
-
- `;
-
- elements.modalContainer.classList.remove("hidden");
+function closeHelpDialog() {
+ elements.helpDialog.close();
}
function showResetConfirmation() {
- elements.modalTitle.textContent = "Reset Progress";
-
- elements.modalContent.innerHTML = `
- Are you sure you want to reset all your progress? This cannot be undone.
-
-
-
-
- `;
-
- document.getElementById("cancel-reset").addEventListener("click", closeModal);
- document.getElementById("confirm-reset").addEventListener("click", () => {
- lessonEngine.clearProgress();
- closeModal();
- closeSidebar();
-
- // Reload first module
- const modules = lessonEngine.modules;
- if (modules.length > 0) {
- selectModule(modules[0].id);
- }
-
- updateProgressDisplay();
- });
-
- elements.modalContainer.classList.remove("hidden");
+ elements.resetDialog.showModal();
}
-function closeModal() {
- elements.modalContainer.classList.add("hidden");
+function closeResetDialog() {
+ elements.resetDialog.close();
+}
+
+function handleResetConfirm() {
+ lessonEngine.clearProgress();
+ closeResetDialog();
+ closeSidebar();
+
+ // Reload first module
+ const modules = lessonEngine.modules;
+ if (modules.length > 0) {
+ selectModule(modules[0].id);
+ }
+
+ updateProgressDisplay();
}
// ================= INITIALIZATION =================
@@ -575,10 +535,13 @@ function init() {
});
elements.resetCodeBtn.addEventListener("click", resetCode);
- // Modals
+ // Dialogs
elements.helpBtn.addEventListener("click", showHelp);
- elements.modalClose.addEventListener("click", closeModal);
+ elements.helpDialogClose.addEventListener("click", closeHelpDialog);
elements.resetBtn.addEventListener("click", showResetConfirmation);
+ elements.resetDialogClose.addEventListener("click", closeResetDialog);
+ elements.cancelReset.addEventListener("click", closeResetDialog);
+ elements.confirmReset.addEventListener("click", handleResetConfirm);
// Settings
elements.disableFeedbackToggle.addEventListener("change", (e) => {
@@ -599,10 +562,9 @@ function init() {
e.preventDefault();
}
- // Escape to close sidebar
+ // Escape to close sidebar (dialogs handle Escape natively)
if (e.key === "Escape") {
closeSidebar();
- closeModal();
}
});
}
diff --git a/src/index.de.html b/src/index.de.html
index aa13f25..c66b435 100644
--- a/src/index.de.html
+++ b/src/index.de.html
@@ -136,18 +136,60 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/src/index.html b/src/index.html
index 7b5aa07..c680f3f 100644
--- a/src/index.html
+++ b/src/index.html
@@ -136,18 +136,60 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/src/main.css b/src/main.css
index b78f038..5ab204b 100644
--- a/src/main.css
+++ b/src/main.css
@@ -839,32 +839,24 @@ input:checked + .toggle-slider::before {
}
-/* ================= MODAL ================= */
-.modal-container {
- position: fixed;
- inset: 0;
- background: var(--modal-bg);
- display: flex;
- justify-content: center;
- align-items: center;
- z-index: 1000;
-}
-
-.modal-container.hidden {
- display: none;
-}
-
-.modal {
- background: var(--panel-bg);
+/* ================= DIALOG (Native HTML) ================= */
+.dialog {
+ border: none;
border-radius: var(--border-radius-lg);
box-shadow: var(--shadow-modal);
+ padding: 0;
width: 90%;
max-width: 500px;
max-height: 80vh;
overflow-y: auto;
+ background: var(--panel-bg);
}
-.modal-header {
+.dialog::backdrop {
+ background: var(--modal-bg);
+}
+
+.dialog-header {
display: flex;
justify-content: space-between;
align-items: center;
@@ -872,22 +864,75 @@ input:checked + .toggle-slider::before {
border-bottom: 1px solid var(--border-color);
}
-.modal-close {
+.dialog-header h3 {
+ margin: 0;
+}
+
+.dialog-close {
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
color: var(--light-text);
+ line-height: 1;
+ padding: 0;
+ width: 28px;
+ height: 28px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 50%;
+ transition: all 0.2s;
}
-.modal-content {
+.dialog-close:hover {
+ background: var(--primary-bg-light);
+ color: var(--primary-color);
+}
+
+.dialog-content {
padding: var(--spacing-lg);
}
-.modal-content p {
+.dialog-content h4 {
+ margin-top: var(--spacing-md);
+ margin-bottom: var(--spacing-xs);
+ color: var(--dark-text);
+}
+
+.dialog-content h4:first-child {
+ margin-top: 0;
+}
+
+.dialog-content p {
margin-bottom: var(--spacing-md);
}
+.dialog-content ul,
+.dialog-content ol {
+ margin: 0 0 var(--spacing-md) 0;
+ padding-left: var(--spacing-lg);
+}
+
+.dialog-content li {
+ margin-bottom: var(--spacing-xs);
+}
+
+.dialog-content kbd {
+ background: var(--code-bg);
+ padding: 2px 6px;
+ border-radius: var(--border-radius-sm);
+ font-size: 0.85em;
+ border: 1px solid var(--border-color);
+}
+
+.dialog-actions {
+ display: flex;
+ justify-content: flex-end;
+ gap: var(--spacing-sm);
+ margin-top: var(--spacing-lg);
+}
+
/* ================= FOOTER ================= */
.app-footer {
padding: var(--spacing-md);