feat: reorder learning path for design students and improve animations
Learning path changes: - Reorder modules: CSS visual (selectors, colors, typography) first, then layout (flexbox, grid), then HTML structure last - Add intro lessons on CSS property syntax before selectors - Add Figure module (images with captions) - Remove Progress/Meter module (too niche) - Reduce Tables from 3 to 1 lesson - Reduce Form Validation from 3 to 1 lesson - Rename "CSS Selectors" module to "CSS Basics" Animation improvements: - Change success text to "Your CODE looks CRISPY!" - Increase animation duration to 3s - Fix Firefox glow: use linear-gradient pulse instead of conic rotation - Fix expected result toggle: match padding to prevent layout jump 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
@@ -630,7 +630,7 @@ function runCode() {
|
||||
elements.previewWrapper?.classList.add("matched");
|
||||
setTimeout(() => {
|
||||
elements.previewWrapper?.classList.remove("matched");
|
||||
}, 3000);
|
||||
}, 3500);
|
||||
|
||||
updateNavigationButtons();
|
||||
updateProgressDisplay();
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
// English lesson imports
|
||||
import welcomeEN from "../../lessons/00-welcome.json";
|
||||
import basicSelectorsEN from "../../lessons/00-basic-selectors.json";
|
||||
import advancedSelectorsEN from "../../lessons/01-advanced-selectors.json";
|
||||
import boxModelEN from "../../lessons/01-box-model.json";
|
||||
import colorsEN from "../../lessons/03-colors.json";
|
||||
import typographyEN from "../../lessons/04-typography.json";
|
||||
@@ -17,7 +16,7 @@ import htmlElementsEN from "../../lessons/20-html-elements.json";
|
||||
import htmlFormsBasicEN from "../../lessons/21-html-forms-basic.json";
|
||||
import htmlFormsValidationEN from "../../lessons/22-html-forms-validation.json";
|
||||
import htmlDetailsSummaryEN from "../../lessons/23-html-details-summary.json";
|
||||
import htmlProgressMeterEN from "../../lessons/24-html-progress-meter.json";
|
||||
import htmlFigureEN from "../../lessons/29-html-figure.json";
|
||||
import htmlTablesEN from "../../lessons/30-html-tables.json";
|
||||
import htmlSvgEN from "../../lessons/32-html-svg.json";
|
||||
import flexboxEN from "../../lessons/flexbox.json";
|
||||
@@ -35,7 +34,6 @@ import htmlElementsDE from "../../lessons/de/20-html-elements.json";
|
||||
import htmlFormsBasicDE from "../../lessons/de/21-html-forms-basic.json";
|
||||
import htmlFormsValidationDE from "../../lessons/de/22-html-forms-validation.json";
|
||||
import htmlDetailsSummaryDE from "../../lessons/de/23-html-details-summary.json";
|
||||
import htmlProgressMeterDE from "../../lessons/de/24-html-progress-meter.json";
|
||||
import htmlTablesDE from "../../lessons/de/30-html-tables.json";
|
||||
import htmlSvgDE from "../../lessons/de/32-html-svg.json";
|
||||
import flexboxDE from "../../lessons/de/flexbox.json";
|
||||
@@ -51,7 +49,6 @@ import htmlElementsPL from "../../lessons/pl/20-html-elements.json";
|
||||
import htmlFormsBasicPL from "../../lessons/pl/21-html-forms-basic.json";
|
||||
import htmlFormsValidationPL from "../../lessons/pl/22-html-forms-validation.json";
|
||||
import htmlDetailsSummaryPL from "../../lessons/pl/23-html-details-summary.json";
|
||||
import htmlProgressMeterPL from "../../lessons/pl/24-html-progress-meter.json";
|
||||
import htmlTablesPL from "../../lessons/pl/30-html-tables.json";
|
||||
import htmlSvgPL from "../../lessons/pl/32-html-svg.json";
|
||||
import flexboxPL from "../../lessons/pl/flexbox.json";
|
||||
@@ -67,7 +64,6 @@ import htmlElementsES from "../../lessons/es/20-html-elements.json";
|
||||
import htmlFormsBasicES from "../../lessons/es/21-html-forms-basic.json";
|
||||
import htmlFormsValidationES from "../../lessons/es/22-html-forms-validation.json";
|
||||
import htmlDetailsSummaryES from "../../lessons/es/23-html-details-summary.json";
|
||||
import htmlProgressMeterES from "../../lessons/es/24-html-progress-meter.json";
|
||||
import htmlTablesES from "../../lessons/es/30-html-tables.json";
|
||||
import htmlSvgES from "../../lessons/es/32-html-svg.json";
|
||||
import flexboxES from "../../lessons/es/flexbox.json";
|
||||
@@ -83,7 +79,6 @@ import htmlElementsAR from "../../lessons/ar/20-html-elements.json";
|
||||
import htmlFormsBasicAR from "../../lessons/ar/21-html-forms-basic.json";
|
||||
import htmlFormsValidationAR from "../../lessons/ar/22-html-forms-validation.json";
|
||||
import htmlDetailsSummaryAR from "../../lessons/ar/23-html-details-summary.json";
|
||||
import htmlProgressMeterAR from "../../lessons/ar/24-html-progress-meter.json";
|
||||
import htmlTablesAR from "../../lessons/ar/30-html-tables.json";
|
||||
import htmlSvgAR from "../../lessons/ar/32-html-svg.json";
|
||||
import flexboxAR from "../../lessons/ar/flexbox.json";
|
||||
@@ -99,199 +94,180 @@ import htmlElementsUK from "../../lessons/uk/20-html-elements.json";
|
||||
import htmlFormsBasicUK from "../../lessons/uk/21-html-forms-basic.json";
|
||||
import htmlFormsValidationUK from "../../lessons/uk/22-html-forms-validation.json";
|
||||
import htmlDetailsSummaryUK from "../../lessons/uk/23-html-details-summary.json";
|
||||
import htmlProgressMeterUK from "../../lessons/uk/24-html-progress-meter.json";
|
||||
import htmlTablesUK from "../../lessons/uk/30-html-tables.json";
|
||||
import htmlSvgUK from "../../lessons/uk/32-html-svg.json";
|
||||
import flexboxUK from "../../lessons/uk/flexbox.json";
|
||||
|
||||
// English module store - ordered by learning path
|
||||
// English module store - ordered for design students
|
||||
const moduleStoreEN = [
|
||||
// Welcome
|
||||
welcomeEN,
|
||||
// HTML Fundamentals
|
||||
htmlElementsEN,
|
||||
htmlFormsBasicEN,
|
||||
htmlFormsValidationEN,
|
||||
// HTML Interactive
|
||||
htmlDetailsSummaryEN,
|
||||
htmlProgressMeterEN,
|
||||
// HTML Data
|
||||
htmlTablesEN,
|
||||
// CSS Fundamentals
|
||||
// CSS Visual (immediate impact)
|
||||
basicSelectorsEN,
|
||||
advancedSelectorsEN,
|
||||
colorsEN,
|
||||
typographyEN,
|
||||
boxModelEN,
|
||||
unitsVariablesEN,
|
||||
// CSS Graphics
|
||||
htmlSvgEN,
|
||||
// CSS Layouts
|
||||
// CSS Layout
|
||||
flexboxEN,
|
||||
gridEN,
|
||||
unitsVariablesEN,
|
||||
responsiveEN,
|
||||
// CSS Animation
|
||||
// CSS Polish
|
||||
transitionsAnimationsEN,
|
||||
// HTML Structure
|
||||
htmlElementsEN,
|
||||
htmlFigureEN,
|
||||
htmlSvgEN,
|
||||
// HTML Interactive
|
||||
htmlDetailsSummaryEN,
|
||||
htmlFormsBasicEN,
|
||||
htmlFormsValidationEN,
|
||||
htmlTablesEN,
|
||||
// Goodbye
|
||||
goodbyeEN
|
||||
];
|
||||
|
||||
// German module store - ordered by learning path
|
||||
// German module store - ordered for design students
|
||||
const moduleStoreDE = [
|
||||
// Welcome
|
||||
welcomeDE,
|
||||
// HTML Fundamentals
|
||||
htmlElementsDE,
|
||||
htmlFormsBasicDE,
|
||||
htmlFormsValidationDE,
|
||||
// HTML Interactive
|
||||
htmlDetailsSummaryDE,
|
||||
htmlProgressMeterDE,
|
||||
// HTML Data
|
||||
htmlTablesDE,
|
||||
// CSS Fundamentals
|
||||
// CSS Visual (immediate impact)
|
||||
basicSelectorsDE,
|
||||
advancedSelectorsEN, // Using EN fallback until translated
|
||||
colorsEN, // Using EN fallback until translated
|
||||
typographyEN, // Using EN fallback until translated
|
||||
boxModelDE,
|
||||
unitsVariablesDE,
|
||||
// CSS Graphics
|
||||
htmlSvgDE,
|
||||
// CSS Layouts
|
||||
// CSS Layout
|
||||
flexboxDE,
|
||||
gridEN, // Using EN fallback until translated
|
||||
unitsVariablesDE,
|
||||
responsiveDE,
|
||||
// CSS Animation
|
||||
// CSS Polish
|
||||
transitionsAnimationsDE,
|
||||
// HTML Structure
|
||||
htmlElementsDE,
|
||||
htmlFigureEN, // Using EN fallback until translated
|
||||
htmlSvgDE,
|
||||
// HTML Interactive
|
||||
htmlDetailsSummaryDE,
|
||||
htmlFormsBasicDE,
|
||||
htmlFormsValidationDE,
|
||||
htmlTablesDE,
|
||||
// Goodbye
|
||||
goodbyeEN
|
||||
];
|
||||
|
||||
// Polish module store - ordered by learning path
|
||||
// Polish module store - ordered for design students
|
||||
const moduleStorePL = [
|
||||
// Welcome
|
||||
welcomePL,
|
||||
// HTML Fundamentals
|
||||
htmlElementsPL,
|
||||
htmlFormsBasicPL,
|
||||
htmlFormsValidationPL,
|
||||
// HTML Interactive
|
||||
htmlDetailsSummaryPL,
|
||||
htmlProgressMeterPL,
|
||||
// HTML Data
|
||||
htmlTablesPL,
|
||||
// CSS Fundamentals
|
||||
// CSS Visual (immediate impact)
|
||||
basicSelectorsPL,
|
||||
advancedSelectorsEN, // Using EN fallback until translated
|
||||
colorsEN, // Using EN fallback until translated
|
||||
typographyEN, // Using EN fallback until translated
|
||||
boxModelPL,
|
||||
unitsVariablesPL,
|
||||
// CSS Graphics
|
||||
htmlSvgPL,
|
||||
// CSS Layouts
|
||||
// CSS Layout
|
||||
flexboxPL,
|
||||
gridEN, // Using EN fallback until translated
|
||||
unitsVariablesPL,
|
||||
responsivePL,
|
||||
// CSS Animation
|
||||
// CSS Polish
|
||||
transitionsAnimationsPL,
|
||||
// HTML Structure
|
||||
htmlElementsPL,
|
||||
htmlFigureEN, // Using EN fallback until translated
|
||||
htmlSvgPL,
|
||||
// HTML Interactive
|
||||
htmlDetailsSummaryPL,
|
||||
htmlFormsBasicPL,
|
||||
htmlFormsValidationPL,
|
||||
htmlTablesPL,
|
||||
// Goodbye
|
||||
goodbyeEN
|
||||
];
|
||||
|
||||
// Spanish module store - ordered by learning path
|
||||
// Spanish module store - ordered for design students
|
||||
const moduleStoreES = [
|
||||
// Welcome
|
||||
welcomeES,
|
||||
// HTML Fundamentals
|
||||
htmlElementsES,
|
||||
htmlFormsBasicES,
|
||||
htmlFormsValidationES,
|
||||
// HTML Interactive
|
||||
htmlDetailsSummaryES,
|
||||
htmlProgressMeterES,
|
||||
// HTML Data
|
||||
htmlTablesES,
|
||||
// CSS Fundamentals
|
||||
// CSS Visual (immediate impact)
|
||||
basicSelectorsES,
|
||||
advancedSelectorsEN, // Using EN fallback until translated
|
||||
colorsEN, // Using EN fallback until translated
|
||||
typographyEN, // Using EN fallback until translated
|
||||
boxModelES,
|
||||
unitsVariablesES,
|
||||
// CSS Graphics
|
||||
htmlSvgES,
|
||||
// CSS Layouts
|
||||
// CSS Layout
|
||||
flexboxES,
|
||||
gridEN, // Using EN fallback until translated
|
||||
unitsVariablesES,
|
||||
responsiveES,
|
||||
// CSS Animation
|
||||
// CSS Polish
|
||||
transitionsAnimationsES,
|
||||
// HTML Structure
|
||||
htmlElementsES,
|
||||
htmlFigureEN, // Using EN fallback until translated
|
||||
htmlSvgES,
|
||||
// HTML Interactive
|
||||
htmlDetailsSummaryES,
|
||||
htmlFormsBasicES,
|
||||
htmlFormsValidationES,
|
||||
htmlTablesES,
|
||||
// Goodbye
|
||||
goodbyeEN
|
||||
];
|
||||
|
||||
// Arabic module store - ordered by learning path
|
||||
// Arabic module store - ordered for design students
|
||||
const moduleStoreAR = [
|
||||
// Welcome
|
||||
welcomeAR,
|
||||
// HTML Fundamentals
|
||||
htmlElementsAR,
|
||||
htmlFormsBasicAR,
|
||||
htmlFormsValidationAR,
|
||||
// HTML Interactive
|
||||
htmlDetailsSummaryAR,
|
||||
htmlProgressMeterAR,
|
||||
// HTML Data
|
||||
htmlTablesAR,
|
||||
// CSS Fundamentals
|
||||
// CSS Visual (immediate impact)
|
||||
basicSelectorsAR,
|
||||
advancedSelectorsEN, // Using EN fallback until translated
|
||||
colorsEN, // Using EN fallback until translated
|
||||
typographyEN, // Using EN fallback until translated
|
||||
boxModelAR,
|
||||
unitsVariablesAR,
|
||||
// CSS Graphics
|
||||
htmlSvgAR,
|
||||
// CSS Layouts
|
||||
// CSS Layout
|
||||
flexboxAR,
|
||||
gridEN, // Using EN fallback until translated
|
||||
unitsVariablesAR,
|
||||
responsiveAR,
|
||||
// CSS Animation
|
||||
// CSS Polish
|
||||
transitionsAnimationsAR,
|
||||
// HTML Structure
|
||||
htmlElementsAR,
|
||||
htmlFigureEN, // Using EN fallback until translated
|
||||
htmlSvgAR,
|
||||
// HTML Interactive
|
||||
htmlDetailsSummaryAR,
|
||||
htmlFormsBasicAR,
|
||||
htmlFormsValidationAR,
|
||||
htmlTablesAR,
|
||||
// Goodbye
|
||||
goodbyeEN
|
||||
];
|
||||
|
||||
// Ukrainian module store - ordered by learning path
|
||||
// Ukrainian module store - ordered for design students
|
||||
const moduleStoreUK = [
|
||||
// Welcome
|
||||
welcomeUK,
|
||||
// HTML Fundamentals
|
||||
htmlElementsUK,
|
||||
htmlFormsBasicUK,
|
||||
htmlFormsValidationUK,
|
||||
// HTML Interactive
|
||||
htmlDetailsSummaryUK,
|
||||
htmlProgressMeterUK,
|
||||
// HTML Data
|
||||
htmlTablesUK,
|
||||
// CSS Fundamentals
|
||||
// CSS Visual (immediate impact)
|
||||
basicSelectorsUK,
|
||||
advancedSelectorsEN, // Using EN fallback until translated
|
||||
colorsEN, // Using EN fallback until translated
|
||||
typographyEN, // Using EN fallback until translated
|
||||
boxModelUK,
|
||||
unitsVariablesUK,
|
||||
// CSS Graphics
|
||||
htmlSvgUK,
|
||||
// CSS Layouts
|
||||
// CSS Layout
|
||||
flexboxUK,
|
||||
gridEN, // Using EN fallback until translated
|
||||
unitsVariablesUK,
|
||||
responsiveUK,
|
||||
// CSS Animation
|
||||
// CSS Polish
|
||||
transitionsAnimationsUK,
|
||||
// HTML Structure
|
||||
htmlElementsUK,
|
||||
htmlFigureEN, // Using EN fallback until translated
|
||||
htmlSvgUK,
|
||||
// HTML Interactive
|
||||
htmlDetailsSummaryUK,
|
||||
htmlFormsBasicUK,
|
||||
htmlFormsValidationUK,
|
||||
htmlTablesUK,
|
||||
// Goodbye
|
||||
goodbyeEN
|
||||
];
|
||||
|
||||
96
src/main.css
96
src/main.css
@@ -207,7 +207,7 @@ kbd {
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
color: var(--light-text);
|
||||
transition: all 0.2s;
|
||||
transition: color 0.2s, border-color 0.2s;
|
||||
}
|
||||
|
||||
.help-toggle:hover {
|
||||
@@ -587,7 +587,7 @@ kbd {
|
||||
.expected-frame {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: var(--spacing-sm);
|
||||
padding: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.expected-frame iframe {
|
||||
@@ -617,17 +617,19 @@ kbd {
|
||||
#7c4dff,
|
||||
#9b59b6
|
||||
) border-box;
|
||||
animation: spin-border 2.5s linear forwards;
|
||||
animation: spin-border 3s ease-out forwards;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/* Colorful glow effect layer */
|
||||
/* Colorful glow effect layer on the preview area */
|
||||
.preview-wrapper.matched::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: -12px;
|
||||
border-radius: calc(var(--border-radius-md) + 12px);
|
||||
background: conic-gradient(
|
||||
from var(--border-angle),
|
||||
/* Multi-color gradient glow - works in all browsers */
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
#9b59b6,
|
||||
#e040fb,
|
||||
#00bcd4,
|
||||
@@ -635,9 +637,50 @@ kbd {
|
||||
#9b59b6
|
||||
);
|
||||
z-index: -1;
|
||||
filter: blur(20px);
|
||||
filter: blur(24px);
|
||||
opacity: 0;
|
||||
animation: spin-glow 2.5s linear forwards;
|
||||
animation: glow-pulse 3s ease-out forwards;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@keyframes glow-pulse {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
15% {
|
||||
opacity: 0.8;
|
||||
transform: scale(1);
|
||||
}
|
||||
60% {
|
||||
opacity: 0.6;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: scale(1.02);
|
||||
}
|
||||
}
|
||||
|
||||
/* Animated CRISPY badge (matches logo style) */
|
||||
.preview-wrapper.matched::after {
|
||||
content: "Your CODE looks CRISPY!";
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 0;
|
||||
transform: translateX(-50%) translateY(-100%);
|
||||
font-family: system-ui, -apple-system, sans-serif;
|
||||
font-size: 2rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.05em;
|
||||
color: white;
|
||||
background: var(--primary-color);
|
||||
padding: 0.5rem 1.25rem;
|
||||
border-radius: 8px;
|
||||
z-index: 10;
|
||||
pointer-events: none;
|
||||
animation: crispy-fall 3s ease-in-out forwards;
|
||||
opacity: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@keyframes spin-border {
|
||||
@@ -656,6 +699,9 @@ kbd {
|
||||
@keyframes spin-glow {
|
||||
0% {
|
||||
--border-angle: 0deg;
|
||||
opacity: 0;
|
||||
}
|
||||
10% {
|
||||
opacity: 0.8;
|
||||
}
|
||||
80% {
|
||||
@@ -668,6 +714,30 @@ kbd {
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes crispy-fall {
|
||||
0% {
|
||||
top: 0;
|
||||
transform: translateX(-50%) translateY(-100%);
|
||||
opacity: 0;
|
||||
}
|
||||
15% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
top: 50%;
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
opacity: 1;
|
||||
}
|
||||
85% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 100%;
|
||||
transform: translateX(-50%) translateY(0%);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================= GAME CONTROLS ================= */
|
||||
.game-controls {
|
||||
display: flex;
|
||||
@@ -895,7 +965,7 @@ button.lesson-list-item {
|
||||
cursor: pointer;
|
||||
font-family: var(--font-main);
|
||||
font-size: 0.9rem;
|
||||
transition: all 0.2s;
|
||||
transition: background 0.2s, color 0.2s, border-color 0.2s;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
@@ -1056,7 +1126,7 @@ button.lesson-list-item {
|
||||
height: 20px;
|
||||
background: #ccc;
|
||||
border-radius: 20px;
|
||||
transition: 0.3s;
|
||||
transition: background 0.3s;
|
||||
margin-right: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -1070,7 +1140,7 @@ button.lesson-list-item {
|
||||
bottom: 2px;
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
transition: 0.3s;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
input:checked + .toggle-slider {
|
||||
@@ -1134,7 +1204,7 @@ input:checked + .toggle-slider::before {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
transition: all 0.2s;
|
||||
transition: background 0.2s, color 0.2s;
|
||||
}
|
||||
|
||||
.dialog-close:hover {
|
||||
@@ -1201,7 +1271,7 @@ input:checked + .toggle-slider::before {
|
||||
border: 1px solid var(--primary-bg-medium);
|
||||
text-decoration: none;
|
||||
color: var(--text-color);
|
||||
transition: all 0.2s ease;
|
||||
transition: background 0.2s, border-color 0.2s, transform 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
|
||||
.project-card:hover {
|
||||
|
||||
Reference in New Issue
Block a user