Synchronizes 72 lesson files across 5 languages (de, pl, es, ar, uk) to match the English source. This ensures code, solutions, and validations are identical while only title, description, task, and message fields are translated. Changes include: - Box model lessons (01-box-model.json) - Units and variables (05-units-variables.json) - Transitions and animations (06-transitions-animations.json) - Responsive design (08-responsive.json) - HTML elements (20-html-elements.json) - HTML forms basic and validation (21, 22) - HTML details/summary, progress/meter (23, 24) - HTML datalist, dialog, fieldset (25, 27, 28) - HTML tables and SVG (30, 32) - HTML marquee (31) - Welcome module (00-welcome.json) Fixes validation inconsistencies and removes extra content that exceeded English source. German translations were largely correct; Polish, Spanish, Arabic, and Ukrainian required full translations.
146 lines
6.7 KiB
JSON
146 lines
6.7 KiB
JSON
{
|
|
"$schema": "../../schemas/code-crispies-module-schema.json",
|
|
"id": "transitions-animations",
|
|
"title": "Animaciones CSS",
|
|
"description": "Añade interactividad a tu UI mediante transiciones suaves de propiedades y animaciones basadas en keyframes.",
|
|
"difficulty": "intermediate",
|
|
"lessons": [
|
|
{
|
|
"id": "transitions-1",
|
|
"title": "Transitions",
|
|
"description": "Aprende a aplicar <kbd>transition</kbd> a propiedades para cambios suaves en estados.<br><br><pre>transition: property duration;\n/* ej. transition: background-color 0.3s; */</pre>",
|
|
"task": "Añade <kbd>transition: background-color 0.3s</kbd> para que el color cambie suavemente al hacer hover.",
|
|
"previewHTML": "<button class=\"btn\">Hover Me</button>",
|
|
"previewBaseCSS": "body { font-family: sans-serif; padding: 1rem; } .btn { background: black; color: white; padding: 0.5rem 1rem; border: none; cursor: pointer; } .btn:hover { background: white; color: black; }",
|
|
"sandboxCSS": "",
|
|
"codePrefix": "/* Add transition */\n.btn {",
|
|
"initialCode": "",
|
|
"codeSuffix": "}",
|
|
"solution": " transition: background-color 0.3s;",
|
|
"previewContainer": "preview-area",
|
|
"validations": [
|
|
{
|
|
"type": "contains",
|
|
"value": "transition",
|
|
"message": "Usa la propiedad <kbd>transition</kbd>",
|
|
"options": { "caseSensitive": false }
|
|
},
|
|
{
|
|
"type": "regex",
|
|
"value": "transition:\\s*background-color\\s*0\\.3s",
|
|
"message": "Establece <kbd>transition: background-color 0.3s</kbd>",
|
|
"options": { "caseSensitive": false }
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "transitions-2",
|
|
"title": "Timing Funcs",
|
|
"description": "Explora funciones de easing como <kbd>ease</kbd>, <kbd>linear</kbd>, <kbd>ease-in</kbd>, <kbd>ease-out</kbd> para controlar el ritmo de la animación.",
|
|
"task": "Establece <kbd>transition-timing-function</kbd> a <kbd>ease-in-out</kbd>.",
|
|
"previewHTML": "<button class=\"btn\">Timing</button>",
|
|
"previewBaseCSS": "body { font-family: sans-serif; padding: 1rem; } .btn { background: navy; color: gold; padding: 0.5rem 1rem; border: none; cursor: pointer; transition: all 0.5s; } .btn:hover { background: gold; color: navy; transform: scale(1.1); }",
|
|
"sandboxCSS": "",
|
|
"codePrefix": "/* Set timing function */\n.btn {",
|
|
"initialCode": "",
|
|
"codeSuffix": "}",
|
|
"solution": " transition-timing-function: ease-in-out;",
|
|
"previewContainer": "preview-area",
|
|
"validations": [
|
|
{
|
|
"type": "contains",
|
|
"value": "transition-timing-function",
|
|
"message": "Usa <kbd>transition-timing-function</kbd>",
|
|
"options": { "caseSensitive": false }
|
|
},
|
|
{
|
|
"type": "property_value",
|
|
"value": { "property": "transition-timing-function", "expected": "ease-in-out" },
|
|
"message": "Establece timing a <kbd>ease-in-out</kbd>"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "transitions-3",
|
|
"title": "Keyframes",
|
|
"description": "Crea animaciones nombradas usando <kbd>@keyframes</kbd> y aplícalas con el atajo <kbd>animation</kbd>.<br><br><pre>@keyframes bounce {\n 50% { transform: translateY(-20px); }\n}\n.ball {\n animation: bounce 1s infinite;\n}</pre>",
|
|
"task": "Define un keyframe en <kbd>50%</kbd> con <kbd>transform: translateY(-20px)</kbd> y aplica <kbd>animation: bounce 1s infinite</kbd> a <kbd>.ball</kbd>.",
|
|
"previewHTML": "<div class=\"ball\"></div>",
|
|
"previewBaseCSS": "body { font-family: sans-serif; padding: 1rem; } .ball { width: 50px; height: 50px; background: crimson; border-radius: 50%; margin: 2rem auto; }",
|
|
"sandboxCSS": "",
|
|
"codePrefix": "/* Define keyframes and apply animation */\n@keyframes bounce {",
|
|
"initialCode": "",
|
|
"codeSuffix": "}\n.ball { }",
|
|
"solution": " 50% { transform: translateY(-20px); }\n}\n.ball {\n animation: bounce 1s infinite;",
|
|
"previewContainer": "preview-area",
|
|
"validations": [
|
|
{
|
|
"type": "contains",
|
|
"value": "@keyframes bounce",
|
|
"message": "Define <kbd>@keyframes bounce</kbd>",
|
|
"options": { "caseSensitive": false }
|
|
},
|
|
{
|
|
"type": "regex",
|
|
"value": "50%.*transform: translateY\\(-20px\\)",
|
|
"message": "En <kbd>50%</kbd>, usa <kbd>transform: translateY(-20px)</kbd>",
|
|
"options": { "caseSensitive": false }
|
|
},
|
|
{
|
|
"type": "contains",
|
|
"value": "animation",
|
|
"message": "Usa la propiedad <kbd>animation</kbd> en <kbd>.ball</kbd>",
|
|
"options": { "caseSensitive": false }
|
|
},
|
|
{
|
|
"type": "regex",
|
|
"value": "animation:.*bounce.*1s.*infinite",
|
|
"message": "Aplica <kbd>animation: bounce 1s infinite</kbd>",
|
|
"options": { "caseSensitive": false }
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"id": "transitions-4",
|
|
"title": "Animation Properties",
|
|
"description": "Ajusta las animaciones con <kbd>animation-delay</kbd>, <kbd>animation-iteration-count</kbd>, <kbd>animation-direction</kbd> y <kbd>animation-fill-mode</kbd>.",
|
|
"task": "Aplica la animación <kbd>pulse</kbd> a <kbd>.box</kbd> con <kbd>animation-name: pulse</kbd>, <kbd>animation-duration: 2s</kbd>, <kbd>animation-delay: 1s</kbd>, <kbd>animation-iteration-count: 2</kbd> y <kbd>animation-fill-mode: forwards</kbd>.",
|
|
"previewHTML": "<div class=\"box\">Pulse</div>",
|
|
"previewBaseCSS": "body { font-family: sans-serif; padding: 1rem; } .box { width: 100px; height: 100px; background: black; color: white; display: flex; align-items: center; justify-content: center; margin: 2rem auto; } @keyframes pulse { 0% { background: black; color: white; transform: scale(1); } 50% { background: white; color: black; transform: scale(1.2); } 100% { background: limegreen; color: black; transform: scale(1); } }",
|
|
"sandboxCSS": "",
|
|
"codePrefix": "/* Apply animation properties */\n.box {",
|
|
"initialCode": "",
|
|
"codeSuffix": "}",
|
|
"solution": " animation-name: pulse;\n animation-duration: 2s;\n animation-delay: 1s;\n animation-iteration-count: 2;\n animation-fill-mode: forwards;",
|
|
"previewContainer": "preview-area",
|
|
"validations": [
|
|
{
|
|
"type": "property_value",
|
|
"value": { "property": "animation-name", "expected": "pulse" },
|
|
"message": "Establece <kbd>animation-name: pulse</kbd>"
|
|
},
|
|
{
|
|
"type": "property_value",
|
|
"value": { "property": "animation-duration", "expected": "2s" },
|
|
"message": "Establece <kbd>animation-duration: 2s</kbd>"
|
|
},
|
|
{
|
|
"type": "property_value",
|
|
"value": { "property": "animation-delay", "expected": "1s" },
|
|
"message": "Establece <kbd>animation-delay: 1s</kbd>"
|
|
},
|
|
{
|
|
"type": "property_value",
|
|
"value": { "property": "animation-iteration-count", "expected": "2" },
|
|
"message": "Establece <kbd>animation-iteration-count: 2</kbd>"
|
|
},
|
|
{
|
|
"type": "property_value",
|
|
"value": { "property": "animation-fill-mode", "expected": "forwards" },
|
|
"message": "Establece <kbd>animation-fill-mode: forwards</kbd>"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|