refactor: simplify HTML lessons to use semantic elements only
- Remove presentational classes (.form-group, .required, .hint, .checkbox-group) - Replace <span class="required">*</span> with plain * in label text - Replace <div class="hint"> with semantic <small> element - Simplify checkbox markup to use native label wrapping pattern - Update previewBaseCSS to style semantic elements directly - Add code quality standards to CLAUDE.md emphasizing WCAG compliance and native HTML
This commit is contained in:
19
CLAUDE.md
19
CLAUDE.md
@@ -48,6 +48,25 @@ For Tailwind mode, user classes are injected via `{{USER_CLASSES}}` placeholder
|
|||||||
|
|
||||||
Tests use Vitest with jsdom environment. Setup in `tests/setup.js` includes DOM testing library matchers. Test files are in `tests/unit/`.
|
Tests use Vitest with jsdom environment. Setup in `tests/setup.js` includes DOM testing library matchers. Test files are in `tests/unit/`.
|
||||||
|
|
||||||
|
## Code Quality Standards
|
||||||
|
|
||||||
|
This project adheres to the highest standards for web development:
|
||||||
|
|
||||||
|
- **Semantic HTML5**: Always use semantic elements (`<header>`, `<nav>`, `<main>`, `<article>`, `<section>`, `<footer>`, `<figure>`, etc.) over generic `<div>` containers
|
||||||
|
- **WCAG Compliance**: Ensure accessibility - proper heading hierarchy, ARIA labels where needed, keyboard navigation support
|
||||||
|
- **Native HTML over JavaScript**: Prefer native HTML elements and attributes (e.g., `<dialog>`, `<details>`, `required`, `pattern`) over JS-driven solutions
|
||||||
|
- **No unnecessary classes**: Avoid presentational classes like `.form-group` or `.container` in lesson examples - teach pure semantic HTML first
|
||||||
|
- **Progressive enhancement**: Core functionality should work without JavaScript where possible
|
||||||
|
- **Valid HTML**: All HTML must be valid according to W3C standards
|
||||||
|
|
||||||
|
### Lesson Content Guidelines
|
||||||
|
|
||||||
|
When creating or editing lessons:
|
||||||
|
- Student code examples should be minimal and semantic
|
||||||
|
- Avoid CSS framework patterns (Bootstrap, Tailwind utility classes) in HTML lessons
|
||||||
|
- Use native form validation attributes instead of JavaScript validation
|
||||||
|
- Teach the platform's native capabilities first
|
||||||
|
|
||||||
## Git Commits
|
## Git Commits
|
||||||
|
|
||||||
- Do NOT add co-authoring lines to commit messages
|
- Do NOT add co-authoring lines to commit messages
|
||||||
|
|||||||
@@ -49,12 +49,12 @@
|
|||||||
"id": "input-types",
|
"id": "input-types",
|
||||||
"title": "Input Types",
|
"title": "Input Types",
|
||||||
"description": "Different input types provide appropriate keyboards and validation:<br><br><kbd>type=\"text\"</kbd> - General text<br><kbd>type=\"email\"</kbd> - Email with @ validation<br><kbd>type=\"password\"</kbd> - Hidden characters<br><kbd>type=\"number\"</kbd> - Numeric keyboard<br><kbd>type=\"tel\"</kbd> - Phone keyboard",
|
"description": "Different input types provide appropriate keyboards and validation:<br><br><kbd>type=\"text\"</kbd> - General text<br><kbd>type=\"email\"</kbd> - Email with @ validation<br><kbd>type=\"password\"</kbd> - Hidden characters<br><kbd>type=\"number\"</kbd> - Numeric keyboard<br><kbd>type=\"tel\"</kbd> - Phone keyboard",
|
||||||
"task": "Create a login form with two fields:<br>1. An email field: <kbd><label for=\"email\">Email:</label></kbd> and <kbd><input type=\"email\" id=\"email\"></kbd><br>2. A password field: <kbd><label for=\"password\">Password:</label></kbd> and <kbd><input type=\"password\" id=\"password\"></kbd><br><br>Optionally wrap each in a <kbd><div class=\"form-group\"></kbd> for spacing.",
|
"task": "Create a login form with two fields:<br>1. An email field: <kbd><label for=\"email\">Email:</label></kbd> and <kbd><input type=\"email\" id=\"email\"></kbd><br>2. A password field: <kbd><label for=\"password\">Password:</label></kbd> and <kbd><input type=\"password\" id=\"password\"></kbd>",
|
||||||
"previewHTML": "",
|
"previewHTML": "",
|
||||||
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 300px; } .form-group { margin-bottom: 15px; } label { display: block; margin-bottom: 5px; } input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; }",
|
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 300px; } label { display: block; margin-top: 15px; margin-bottom: 5px; } label:first-child { margin-top: 0; } input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; }",
|
||||||
"sandboxCSS": "",
|
"sandboxCSS": "",
|
||||||
"initialCode": "<form>\n <!-- Add email and password inputs -->\n</form>",
|
"initialCode": "<form>\n <!-- Add email and password inputs -->\n</form>",
|
||||||
"solution": "<form>\n <div class=\"form-group\">\n <label for=\"email\">Email:</label>\n <input type=\"email\" id=\"email\" name=\"email\">\n </div>\n <div class=\"form-group\">\n <label for=\"password\">Password:</label>\n <input type=\"password\" id=\"password\" name=\"password\">\n </div>\n</form>",
|
"solution": "<form>\n <label for=\"email\">Email:</label>\n <input type=\"email\" id=\"email\" name=\"email\">\n \n <label for=\"password\">Password:</label>\n <input type=\"password\" id=\"password\" name=\"password\">\n</form>",
|
||||||
"previewContainer": "preview-area",
|
"previewContainer": "preview-area",
|
||||||
"validations": [
|
"validations": [
|
||||||
{
|
{
|
||||||
@@ -80,10 +80,10 @@
|
|||||||
"description": "Forms need a way to submit data. Use:<br><br><kbd><button type=\"submit\"></kbd> - Preferred, flexible content<br><kbd><input type=\"submit\"></kbd> - Simple text-only button<br><br>The button text should be action-oriented (e.g., 'Sign In', 'Register', 'Send').",
|
"description": "Forms need a way to submit data. Use:<br><br><kbd><button type=\"submit\"></kbd> - Preferred, flexible content<br><kbd><input type=\"submit\"></kbd> - Simple text-only button<br><br>The button text should be action-oriented (e.g., 'Sign In', 'Register', 'Send').",
|
||||||
"task": "Add a submit button to the form with the text 'Sign In'.",
|
"task": "Add a submit button to the form with the text 'Sign In'.",
|
||||||
"previewHTML": "",
|
"previewHTML": "",
|
||||||
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 300px; } .form-group { margin-bottom: 15px; } label { display: block; margin-bottom: 5px; } input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } button { width: 100%; padding: 10px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; } button:hover { background: #1565c0; }",
|
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 300px; } label { display: block; margin-top: 15px; margin-bottom: 5px; } label:first-child { margin-top: 0; } input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } button { width: 100%; margin-top: 20px; padding: 10px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; } button:hover { background: #1565c0; }",
|
||||||
"sandboxCSS": "",
|
"sandboxCSS": "",
|
||||||
"initialCode": "<form>\n <div class=\"form-group\">\n <label for=\"email\">Email:</label>\n <input type=\"email\" id=\"email\">\n </div>\n <div class=\"form-group\">\n <label for=\"password\">Password:</label>\n <input type=\"password\" id=\"password\">\n </div>\n <!-- Add submit button -->\n</form>",
|
"initialCode": "<form>\n <label for=\"email\">Email:</label>\n <input type=\"email\" id=\"email\">\n \n <label for=\"password\">Password:</label>\n <input type=\"password\" id=\"password\">\n \n <!-- Add submit button -->\n</form>",
|
||||||
"solution": "<form>\n <div class=\"form-group\">\n <label for=\"email\">Email:</label>\n <input type=\"email\" id=\"email\">\n </div>\n <div class=\"form-group\">\n <label for=\"password\">Password:</label>\n <input type=\"password\" id=\"password\">\n </div>\n <button type=\"submit\">Sign In</button>\n</form>",
|
"solution": "<form>\n <label for=\"email\">Email:</label>\n <input type=\"email\" id=\"email\">\n \n <label for=\"password\">Password:</label>\n <input type=\"password\" id=\"password\">\n \n <button type=\"submit\">Sign In</button>\n</form>",
|
||||||
"previewContainer": "preview-area",
|
"previewContainer": "preview-area",
|
||||||
"validations": [
|
"validations": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,12 +10,12 @@
|
|||||||
"id": "required-fields",
|
"id": "required-fields",
|
||||||
"title": "Required Fields",
|
"title": "Required Fields",
|
||||||
"description": "The <kbd>required</kbd> attribute prevents form submission if the field is empty.<br><br>Add it to any input that must be filled:<br><kbd><input type=\"text\" required></kbd><br><br>The browser shows a validation message automatically.",
|
"description": "The <kbd>required</kbd> attribute prevents form submission if the field is empty.<br><br>Add it to any input that must be filled:<br><kbd><input type=\"text\" required></kbd><br><br>The browser shows a validation message automatically.",
|
||||||
"task": "Make both the name and email fields required.",
|
"task": "Make both the name and email fields required by adding the <kbd>required</kbd> attribute.",
|
||||||
"previewHTML": "",
|
"previewHTML": "",
|
||||||
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 350px; } .form-group { margin-bottom: 15px; } label { display: block; margin-bottom: 5px; } label .required { color: #d32f2f; } input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } input:invalid { border-color: #d32f2f; } button { padding: 10px 20px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; }",
|
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 350px; } label { display: block; margin-top: 15px; margin-bottom: 5px; } label:first-of-type { margin-top: 0; } input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } input:invalid { border-color: #d32f2f; } button { margin-top: 20px; padding: 10px 20px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; }",
|
||||||
"sandboxCSS": "",
|
"sandboxCSS": "",
|
||||||
"initialCode": "<form>\n <div class=\"form-group\">\n <label for=\"name\">Name: <span class=\"required\">*</span></label>\n <input type=\"text\" id=\"name\" name=\"name\">\n </div>\n <div class=\"form-group\">\n <label for=\"email\">Email: <span class=\"required\">*</span></label>\n <input type=\"email\" id=\"email\" name=\"email\">\n </div>\n <button type=\"submit\">Submit</button>\n</form>",
|
"initialCode": "<form>\n <label for=\"name\">Name: *</label>\n <input type=\"text\" id=\"name\" name=\"name\">\n \n <label for=\"email\">Email: *</label>\n <input type=\"email\" id=\"email\" name=\"email\">\n \n <button type=\"submit\">Submit</button>\n</form>",
|
||||||
"solution": "<form>\n <div class=\"form-group\">\n <label for=\"name\">Name: <span class=\"required\">*</span></label>\n <input type=\"text\" id=\"name\" name=\"name\" required>\n </div>\n <div class=\"form-group\">\n <label for=\"email\">Email: <span class=\"required\">*</span></label>\n <input type=\"email\" id=\"email\" name=\"email\" required>\n </div>\n <button type=\"submit\">Submit</button>\n</form>",
|
"solution": "<form>\n <label for=\"name\">Name: *</label>\n <input type=\"text\" id=\"name\" name=\"name\" required>\n \n <label for=\"email\">Email: *</label>\n <input type=\"email\" id=\"email\" name=\"email\" required>\n \n <button type=\"submit\">Submit</button>\n</form>",
|
||||||
"previewContainer": "preview-area",
|
"previewContainer": "preview-area",
|
||||||
"validations": [
|
"validations": [
|
||||||
{
|
{
|
||||||
@@ -36,10 +36,10 @@
|
|||||||
"description": "Control what users can enter:<br><br><kbd>minlength</kbd> / <kbd>maxlength</kbd> - Text length limits<br><kbd>min</kbd> / <kbd>max</kbd> - Number range<br><kbd>pattern</kbd> - Regex pattern matching<br><kbd>placeholder</kbd> - Hint text (not a label!)",
|
"description": "Control what users can enter:<br><br><kbd>minlength</kbd> / <kbd>maxlength</kbd> - Text length limits<br><kbd>min</kbd> / <kbd>max</kbd> - Number range<br><kbd>pattern</kbd> - Regex pattern matching<br><kbd>placeholder</kbd> - Hint text (not a label!)",
|
||||||
"task": "Add validation to the password input:<br>1. Add <kbd>minlength=\"8\"</kbd> for minimum length<br>2. Add <kbd>maxlength=\"20\"</kbd> for maximum length<br>3. Add <kbd>placeholder=\"Enter password\"</kbd> as a hint",
|
"task": "Add validation to the password input:<br>1. Add <kbd>minlength=\"8\"</kbd> for minimum length<br>2. Add <kbd>maxlength=\"20\"</kbd> for maximum length<br>3. Add <kbd>placeholder=\"Enter password\"</kbd> as a hint",
|
||||||
"previewHTML": "",
|
"previewHTML": "",
|
||||||
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 350px; } .form-group { margin-bottom: 15px; } label { display: block; margin-bottom: 5px; } input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } input:invalid:not(:placeholder-shown) { border-color: #d32f2f; } .hint { font-size: 12px; color: #666; margin-top: 4px; } button { padding: 10px 20px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; }",
|
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 350px; } label { display: block; margin-bottom: 5px; } input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } input:invalid:not(:placeholder-shown) { border-color: #d32f2f; } small { display: block; font-size: 12px; color: #666; margin-top: 4px; } button { margin-top: 20px; padding: 10px 20px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; }",
|
||||||
"sandboxCSS": "",
|
"sandboxCSS": "",
|
||||||
"initialCode": "<form>\n <div class=\"form-group\">\n <label for=\"password\">Password:</label>\n <input type=\"password\" id=\"password\" name=\"password\" required>\n <div class=\"hint\">Must be 8-20 characters</div>\n </div>\n <button type=\"submit\">Create Account</button>\n</form>",
|
"initialCode": "<form>\n <label for=\"password\">Password:</label>\n <input type=\"password\" id=\"password\" name=\"password\" required>\n <small>Must be 8-20 characters</small>\n \n <button type=\"submit\">Create Account</button>\n</form>",
|
||||||
"solution": "<form>\n <div class=\"form-group\">\n <label for=\"password\">Password:</label>\n <input type=\"password\" id=\"password\" name=\"password\" required minlength=\"8\" maxlength=\"20\" placeholder=\"Enter password\">\n <div class=\"hint\">Must be 8-20 characters</div>\n </div>\n <button type=\"submit\">Create Account</button>\n</form>",
|
"solution": "<form>\n <label for=\"password\">Password:</label>\n <input type=\"password\" id=\"password\" name=\"password\" required minlength=\"8\" maxlength=\"20\" placeholder=\"Enter password\">\n <small>Must be 8-20 characters</small>\n \n <button type=\"submit\">Create Account</button>\n</form>",
|
||||||
"previewContainer": "preview-area",
|
"previewContainer": "preview-area",
|
||||||
"validations": [
|
"validations": [
|
||||||
{
|
{
|
||||||
@@ -65,10 +65,10 @@
|
|||||||
"description": "Build a complete registration form with all validation concepts:<br><br>- Required fields marked with *<br>- Email validation (use type=\"email\")<br>- Password with length constraints<br>- Terms checkbox (required)<br>- Submit button",
|
"description": "Build a complete registration form with all validation concepts:<br><br>- Required fields marked with *<br>- Email validation (use type=\"email\")<br>- Password with length constraints<br>- Terms checkbox (required)<br>- Submit button",
|
||||||
"task": "Complete the registration form. Add required attributes, proper input types, and validation constraints.",
|
"task": "Complete the registration form. Add required attributes, proper input types, and validation constraints.",
|
||||||
"previewHTML": "",
|
"previewHTML": "",
|
||||||
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 400px; background: #f5f5f5; padding: 25px; border-radius: 8px; } h2 { margin-top: 0; margin-bottom: 20px; } .form-group { margin-bottom: 18px; } label { display: block; margin-bottom: 5px; font-weight: 500; } .required { color: #d32f2f; } input[type='text'], input[type='email'], input[type='password'] { width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; font-size: 14px; } input:focus { outline: 2px solid #1976d2; border-color: transparent; } .checkbox-group { display: flex; align-items: flex-start; gap: 8px; } .checkbox-group input { width: auto; margin-top: 3px; } .checkbox-group label { margin: 0; font-weight: normal; } button { width: 100%; padding: 12px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; font-weight: 500; } button:hover { background: #1565c0; }",
|
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 400px; background: #f5f5f5; padding: 25px; border-radius: 8px; } h2 { margin-top: 0; margin-bottom: 20px; } label { display: block; margin-top: 15px; margin-bottom: 5px; font-weight: 500; } input[type='text'], input[type='email'], input[type='password'] { width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; font-size: 14px; } input:focus { outline: 2px solid #1976d2; border-color: transparent; } input[type='checkbox'] { width: auto; margin-right: 8px; vertical-align: middle; } label:has(input[type='checkbox']) { display: flex; align-items: center; font-weight: normal; } button { width: 100%; margin-top: 20px; padding: 12px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; font-weight: 500; } button:hover { background: #1565c0; }",
|
||||||
"sandboxCSS": "",
|
"sandboxCSS": "",
|
||||||
"initialCode": "<form>\n <h2>Create Account</h2>\n \n <div class=\"form-group\">\n <label for=\"fullname\">Full Name <span class=\"required\">*</span></label>\n <input type=\"text\" id=\"fullname\" name=\"fullname\">\n </div>\n \n <div class=\"form-group\">\n <label for=\"email\">Email <span class=\"required\">*</span></label>\n <input id=\"email\" name=\"email\">\n </div>\n \n <div class=\"form-group\">\n <label for=\"password\">Password <span class=\"required\">*</span></label>\n <input id=\"password\" name=\"password\">\n </div>\n \n <div class=\"form-group checkbox-group\">\n <input type=\"checkbox\" id=\"terms\" name=\"terms\">\n <label for=\"terms\">I agree to the Terms of Service <span class=\"required\">*</span></label>\n </div>\n \n <button type=\"submit\">Register</button>\n</form>",
|
"initialCode": "<form>\n <h2>Create Account</h2>\n \n <label for=\"fullname\">Full Name *</label>\n <input type=\"text\" id=\"fullname\" name=\"fullname\">\n \n <label for=\"email\">Email *</label>\n <input id=\"email\" name=\"email\">\n \n <label for=\"password\">Password *</label>\n <input id=\"password\" name=\"password\">\n \n <label>\n <input type=\"checkbox\" id=\"terms\" name=\"terms\">\n I agree to the Terms of Service *\n </label>\n \n <button type=\"submit\">Register</button>\n</form>",
|
||||||
"solution": "<form>\n <h2>Create Account</h2>\n \n <div class=\"form-group\">\n <label for=\"fullname\">Full Name <span class=\"required\">*</span></label>\n <input type=\"text\" id=\"fullname\" name=\"fullname\" required>\n </div>\n \n <div class=\"form-group\">\n <label for=\"email\">Email <span class=\"required\">*</span></label>\n <input type=\"email\" id=\"email\" name=\"email\" required>\n </div>\n \n <div class=\"form-group\">\n <label for=\"password\">Password <span class=\"required\">*</span></label>\n <input type=\"password\" id=\"password\" name=\"password\" required minlength=\"8\">\n </div>\n \n <div class=\"form-group checkbox-group\">\n <input type=\"checkbox\" id=\"terms\" name=\"terms\" required>\n <label for=\"terms\">I agree to the Terms of Service <span class=\"required\">*</span></label>\n </div>\n \n <button type=\"submit\">Register</button>\n</form>",
|
"solution": "<form>\n <h2>Create Account</h2>\n \n <label for=\"fullname\">Full Name *</label>\n <input type=\"text\" id=\"fullname\" name=\"fullname\" required>\n \n <label for=\"email\">Email *</label>\n <input type=\"email\" id=\"email\" name=\"email\" required>\n \n <label for=\"password\">Password *</label>\n <input type=\"password\" id=\"password\" name=\"password\" required minlength=\"8\">\n \n <label>\n <input type=\"checkbox\" id=\"terms\" name=\"terms\" required>\n I agree to the Terms of Service *\n </label>\n \n <button type=\"submit\">Register</button>\n</form>",
|
||||||
"previewContainer": "preview-area",
|
"previewContainer": "preview-area",
|
||||||
"validations": [
|
"validations": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -49,12 +49,12 @@
|
|||||||
"id": "input-types",
|
"id": "input-types",
|
||||||
"title": "Eingabetypen",
|
"title": "Eingabetypen",
|
||||||
"description": "Verschiedene Eingabetypen bieten passende Tastaturen und Validierung:<br><br><kbd>type=\"text\"</kbd> - Allgemeiner Text<br><kbd>type=\"email\"</kbd> - E-Mail mit @-Validierung<br><kbd>type=\"password\"</kbd> - Versteckte Zeichen<br><kbd>type=\"number\"</kbd> - Numerische Tastatur<br><kbd>type=\"tel\"</kbd> - Telefon-Tastatur",
|
"description": "Verschiedene Eingabetypen bieten passende Tastaturen und Validierung:<br><br><kbd>type=\"text\"</kbd> - Allgemeiner Text<br><kbd>type=\"email\"</kbd> - E-Mail mit @-Validierung<br><kbd>type=\"password\"</kbd> - Versteckte Zeichen<br><kbd>type=\"number\"</kbd> - Numerische Tastatur<br><kbd>type=\"tel\"</kbd> - Telefon-Tastatur",
|
||||||
"task": "Erstelle ein Anmeldeformular mit zwei Feldern:<br>1. Ein E-Mail-Feld: <kbd><label for=\"email\">E-Mail:</label></kbd> und <kbd><input type=\"email\" id=\"email\"></kbd><br>2. Ein Passwort-Feld: <kbd><label for=\"password\">Passwort:</label></kbd> und <kbd><input type=\"password\" id=\"password\"></kbd><br><br>Optional kannst du jedes in ein <kbd><div class=\"form-group\"></kbd> für Abstände einschließen.",
|
"task": "Erstelle ein Anmeldeformular mit zwei Feldern:<br>1. Ein E-Mail-Feld: <kbd><label for=\"email\">E-Mail:</label></kbd> und <kbd><input type=\"email\" id=\"email\"></kbd><br>2. Ein Passwort-Feld: <kbd><label for=\"password\">Passwort:</label></kbd> und <kbd><input type=\"password\" id=\"password\"></kbd>",
|
||||||
"previewHTML": "",
|
"previewHTML": "",
|
||||||
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 300px; } .form-group { margin-bottom: 15px; } label { display: block; margin-bottom: 5px; } input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; }",
|
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 300px; } label { display: block; margin-top: 15px; margin-bottom: 5px; } label:first-child { margin-top: 0; } input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; }",
|
||||||
"sandboxCSS": "",
|
"sandboxCSS": "",
|
||||||
"initialCode": "<form>\n <!-- Füge E-Mail- und Passwort-Eingaben hinzu -->\n</form>",
|
"initialCode": "<form>\n <!-- Füge E-Mail- und Passwort-Eingaben hinzu -->\n</form>",
|
||||||
"solution": "<form>\n <div class=\"form-group\">\n <label for=\"email\">E-Mail:</label>\n <input type=\"email\" id=\"email\" name=\"email\">\n </div>\n <div class=\"form-group\">\n <label for=\"password\">Passwort:</label>\n <input type=\"password\" id=\"password\" name=\"password\">\n </div>\n</form>",
|
"solution": "<form>\n <label for=\"email\">E-Mail:</label>\n <input type=\"email\" id=\"email\" name=\"email\">\n \n <label for=\"password\">Passwort:</label>\n <input type=\"password\" id=\"password\" name=\"password\">\n</form>",
|
||||||
"previewContainer": "preview-area",
|
"previewContainer": "preview-area",
|
||||||
"validations": [
|
"validations": [
|
||||||
{
|
{
|
||||||
@@ -80,10 +80,10 @@
|
|||||||
"description": "Formulare benötigen eine Möglichkeit zum Absenden. Verwende:<br><br><kbd><button type=\"submit\"></kbd> - Bevorzugt, flexibler Inhalt<br><kbd><input type=\"submit\"></kbd> - Einfacher Text-Button<br><br>Der Button-Text sollte handlungsorientiert sein (z.B. 'Anmelden', 'Registrieren', 'Senden').",
|
"description": "Formulare benötigen eine Möglichkeit zum Absenden. Verwende:<br><br><kbd><button type=\"submit\"></kbd> - Bevorzugt, flexibler Inhalt<br><kbd><input type=\"submit\"></kbd> - Einfacher Text-Button<br><br>Der Button-Text sollte handlungsorientiert sein (z.B. 'Anmelden', 'Registrieren', 'Senden').",
|
||||||
"task": "Füge dem Formular einen Absende-Button mit dem Text 'Anmelden' hinzu.",
|
"task": "Füge dem Formular einen Absende-Button mit dem Text 'Anmelden' hinzu.",
|
||||||
"previewHTML": "",
|
"previewHTML": "",
|
||||||
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 300px; } .form-group { margin-bottom: 15px; } label { display: block; margin-bottom: 5px; } input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } button { width: 100%; padding: 10px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; } button:hover { background: #1565c0; }",
|
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 300px; } label { display: block; margin-top: 15px; margin-bottom: 5px; } label:first-child { margin-top: 0; } input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } button { width: 100%; margin-top: 20px; padding: 10px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; } button:hover { background: #1565c0; }",
|
||||||
"sandboxCSS": "",
|
"sandboxCSS": "",
|
||||||
"initialCode": "<form>\n <div class=\"form-group\">\n <label for=\"email\">E-Mail:</label>\n <input type=\"email\" id=\"email\">\n </div>\n <div class=\"form-group\">\n <label for=\"password\">Passwort:</label>\n <input type=\"password\" id=\"password\">\n </div>\n <!-- Füge Absende-Button hinzu -->\n</form>",
|
"initialCode": "<form>\n <label for=\"email\">E-Mail:</label>\n <input type=\"email\" id=\"email\">\n \n <label for=\"password\">Passwort:</label>\n <input type=\"password\" id=\"password\">\n \n <!-- Füge Absende-Button hinzu -->\n</form>",
|
||||||
"solution": "<form>\n <div class=\"form-group\">\n <label for=\"email\">E-Mail:</label>\n <input type=\"email\" id=\"email\">\n </div>\n <div class=\"form-group\">\n <label for=\"password\">Passwort:</label>\n <input type=\"password\" id=\"password\">\n </div>\n <button type=\"submit\">Anmelden</button>\n</form>",
|
"solution": "<form>\n <label for=\"email\">E-Mail:</label>\n <input type=\"email\" id=\"email\">\n \n <label for=\"password\">Passwort:</label>\n <input type=\"password\" id=\"password\">\n \n <button type=\"submit\">Anmelden</button>\n</form>",
|
||||||
"previewContainer": "preview-area",
|
"previewContainer": "preview-area",
|
||||||
"validations": [
|
"validations": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,12 +10,12 @@
|
|||||||
"id": "required-fields",
|
"id": "required-fields",
|
||||||
"title": "Pflichtfelder",
|
"title": "Pflichtfelder",
|
||||||
"description": "Das <kbd>required</kbd>-Attribut verhindert das Absenden des Formulars, wenn das Feld leer ist.<br><br>Füge es zu jeder Eingabe hinzu, die ausgefüllt werden muss:<br><kbd><input type=\"text\" required></kbd><br><br>Der Browser zeigt automatisch eine Validierungsmeldung an.",
|
"description": "Das <kbd>required</kbd>-Attribut verhindert das Absenden des Formulars, wenn das Feld leer ist.<br><br>Füge es zu jeder Eingabe hinzu, die ausgefüllt werden muss:<br><kbd><input type=\"text\" required></kbd><br><br>Der Browser zeigt automatisch eine Validierungsmeldung an.",
|
||||||
"task": "Mache sowohl das Name- als auch das E-Mail-Feld zu Pflichtfeldern.",
|
"task": "Mache sowohl das Name- als auch das E-Mail-Feld zu Pflichtfeldern, indem du das <kbd>required</kbd>-Attribut hinzufügst.",
|
||||||
"previewHTML": "",
|
"previewHTML": "",
|
||||||
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 350px; } .form-group { margin-bottom: 15px; } label { display: block; margin-bottom: 5px; } label .required { color: #d32f2f; } input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } input:invalid { border-color: #d32f2f; } button { padding: 10px 20px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; }",
|
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 350px; } label { display: block; margin-top: 15px; margin-bottom: 5px; } label:first-of-type { margin-top: 0; } input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } input:invalid { border-color: #d32f2f; } button { margin-top: 20px; padding: 10px 20px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; }",
|
||||||
"sandboxCSS": "",
|
"sandboxCSS": "",
|
||||||
"initialCode": "<form>\n <div class=\"form-group\">\n <label for=\"name\">Name: <span class=\"required\">*</span></label>\n <input type=\"text\" id=\"name\" name=\"name\">\n </div>\n <div class=\"form-group\">\n <label for=\"email\">E-Mail: <span class=\"required\">*</span></label>\n <input type=\"email\" id=\"email\" name=\"email\">\n </div>\n <button type=\"submit\">Absenden</button>\n</form>",
|
"initialCode": "<form>\n <label for=\"name\">Name: *</label>\n <input type=\"text\" id=\"name\" name=\"name\">\n \n <label for=\"email\">E-Mail: *</label>\n <input type=\"email\" id=\"email\" name=\"email\">\n \n <button type=\"submit\">Absenden</button>\n</form>",
|
||||||
"solution": "<form>\n <div class=\"form-group\">\n <label for=\"name\">Name: <span class=\"required\">*</span></label>\n <input type=\"text\" id=\"name\" name=\"name\" required>\n </div>\n <div class=\"form-group\">\n <label for=\"email\">E-Mail: <span class=\"required\">*</span></label>\n <input type=\"email\" id=\"email\" name=\"email\" required>\n </div>\n <button type=\"submit\">Absenden</button>\n</form>",
|
"solution": "<form>\n <label for=\"name\">Name: *</label>\n <input type=\"text\" id=\"name\" name=\"name\" required>\n \n <label for=\"email\">E-Mail: *</label>\n <input type=\"email\" id=\"email\" name=\"email\" required>\n \n <button type=\"submit\">Absenden</button>\n</form>",
|
||||||
"previewContainer": "preview-area",
|
"previewContainer": "preview-area",
|
||||||
"validations": [
|
"validations": [
|
||||||
{
|
{
|
||||||
@@ -36,10 +36,10 @@
|
|||||||
"description": "Kontrolliere, was Benutzer eingeben können:<br><br><kbd>minlength</kbd> / <kbd>maxlength</kbd> - Textlängenbegrenzung<br><kbd>min</kbd> / <kbd>max</kbd> - Zahlenbereich<br><kbd>pattern</kbd> - Regex-Musterabgleich<br><kbd>placeholder</kbd> - Hinweistext (kein Label!)",
|
"description": "Kontrolliere, was Benutzer eingeben können:<br><br><kbd>minlength</kbd> / <kbd>maxlength</kbd> - Textlängenbegrenzung<br><kbd>min</kbd> / <kbd>max</kbd> - Zahlenbereich<br><kbd>pattern</kbd> - Regex-Musterabgleich<br><kbd>placeholder</kbd> - Hinweistext (kein Label!)",
|
||||||
"task": "Füge Validierung zur Passwort-Eingabe hinzu:<br>1. Füge <kbd>minlength=\"8\"</kbd> für die Mindestlänge hinzu<br>2. Füge <kbd>maxlength=\"20\"</kbd> für die Maximallänge hinzu<br>3. Füge <kbd>placeholder=\"Passwort eingeben\"</kbd> als Hinweis hinzu",
|
"task": "Füge Validierung zur Passwort-Eingabe hinzu:<br>1. Füge <kbd>minlength=\"8\"</kbd> für die Mindestlänge hinzu<br>2. Füge <kbd>maxlength=\"20\"</kbd> für die Maximallänge hinzu<br>3. Füge <kbd>placeholder=\"Passwort eingeben\"</kbd> als Hinweis hinzu",
|
||||||
"previewHTML": "",
|
"previewHTML": "",
|
||||||
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 350px; } .form-group { margin-bottom: 15px; } label { display: block; margin-bottom: 5px; } input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } input:invalid:not(:placeholder-shown) { border-color: #d32f2f; } .hint { font-size: 12px; color: #666; margin-top: 4px; } button { padding: 10px 20px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; }",
|
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 350px; } label { display: block; margin-bottom: 5px; } input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } input:invalid:not(:placeholder-shown) { border-color: #d32f2f; } small { display: block; font-size: 12px; color: #666; margin-top: 4px; } button { margin-top: 20px; padding: 10px 20px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; }",
|
||||||
"sandboxCSS": "",
|
"sandboxCSS": "",
|
||||||
"initialCode": "<form>\n <div class=\"form-group\">\n <label for=\"password\">Passwort:</label>\n <input type=\"password\" id=\"password\" name=\"password\" required>\n <div class=\"hint\">Muss 8-20 Zeichen lang sein</div>\n </div>\n <button type=\"submit\">Konto erstellen</button>\n</form>",
|
"initialCode": "<form>\n <label for=\"password\">Passwort:</label>\n <input type=\"password\" id=\"password\" name=\"password\" required>\n <small>Muss 8-20 Zeichen lang sein</small>\n \n <button type=\"submit\">Konto erstellen</button>\n</form>",
|
||||||
"solution": "<form>\n <div class=\"form-group\">\n <label for=\"password\">Passwort:</label>\n <input type=\"password\" id=\"password\" name=\"password\" required minlength=\"8\" maxlength=\"20\" placeholder=\"Passwort eingeben\">\n <div class=\"hint\">Muss 8-20 Zeichen lang sein</div>\n </div>\n <button type=\"submit\">Konto erstellen</button>\n</form>",
|
"solution": "<form>\n <label for=\"password\">Passwort:</label>\n <input type=\"password\" id=\"password\" name=\"password\" required minlength=\"8\" maxlength=\"20\" placeholder=\"Passwort eingeben\">\n <small>Muss 8-20 Zeichen lang sein</small>\n \n <button type=\"submit\">Konto erstellen</button>\n</form>",
|
||||||
"previewContainer": "preview-area",
|
"previewContainer": "preview-area",
|
||||||
"validations": [
|
"validations": [
|
||||||
{
|
{
|
||||||
@@ -65,10 +65,10 @@
|
|||||||
"description": "Erstelle ein vollständiges Registrierungsformular mit allen Validierungskonzepten:<br><br>- Pflichtfelder mit * markiert<br>- E-Mail-Validierung (type=\"email\" verwenden)<br>- Passwort mit Längenbeschränkungen<br>- AGB-Checkbox (Pflichtfeld)<br>- Absende-Button",
|
"description": "Erstelle ein vollständiges Registrierungsformular mit allen Validierungskonzepten:<br><br>- Pflichtfelder mit * markiert<br>- E-Mail-Validierung (type=\"email\" verwenden)<br>- Passwort mit Längenbeschränkungen<br>- AGB-Checkbox (Pflichtfeld)<br>- Absende-Button",
|
||||||
"task": "Vervollständige das Registrierungsformular. Füge required-Attribute, passende Eingabetypen und Validierungsbeschränkungen hinzu.",
|
"task": "Vervollständige das Registrierungsformular. Füge required-Attribute, passende Eingabetypen und Validierungsbeschränkungen hinzu.",
|
||||||
"previewHTML": "",
|
"previewHTML": "",
|
||||||
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 400px; background: #f5f5f5; padding: 25px; border-radius: 8px; } h2 { margin-top: 0; margin-bottom: 20px; } .form-group { margin-bottom: 18px; } label { display: block; margin-bottom: 5px; font-weight: 500; } .required { color: #d32f2f; } input[type='text'], input[type='email'], input[type='password'] { width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; font-size: 14px; } input:focus { outline: 2px solid #1976d2; border-color: transparent; } .checkbox-group { display: flex; align-items: flex-start; gap: 8px; } .checkbox-group input { width: auto; margin-top: 3px; } .checkbox-group label { margin: 0; font-weight: normal; } button { width: 100%; padding: 12px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; font-weight: 500; } button:hover { background: #1565c0; }",
|
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } form { max-width: 400px; background: #f5f5f5; padding: 25px; border-radius: 8px; } h2 { margin-top: 0; margin-bottom: 20px; } label { display: block; margin-top: 15px; margin-bottom: 5px; font-weight: 500; } input[type='text'], input[type='email'], input[type='password'] { width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; font-size: 14px; } input:focus { outline: 2px solid #1976d2; border-color: transparent; } input[type='checkbox'] { width: auto; margin-right: 8px; vertical-align: middle; } label:has(input[type='checkbox']) { display: flex; align-items: center; font-weight: normal; } button { width: 100%; margin-top: 20px; padding: 12px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; font-weight: 500; } button:hover { background: #1565c0; }",
|
||||||
"sandboxCSS": "",
|
"sandboxCSS": "",
|
||||||
"initialCode": "<form>\n <h2>Konto erstellen</h2>\n \n <div class=\"form-group\">\n <label for=\"fullname\">Vollständiger Name <span class=\"required\">*</span></label>\n <input type=\"text\" id=\"fullname\" name=\"fullname\">\n </div>\n \n <div class=\"form-group\">\n <label for=\"email\">E-Mail <span class=\"required\">*</span></label>\n <input id=\"email\" name=\"email\">\n </div>\n \n <div class=\"form-group\">\n <label for=\"password\">Passwort <span class=\"required\">*</span></label>\n <input id=\"password\" name=\"password\">\n </div>\n \n <div class=\"form-group checkbox-group\">\n <input type=\"checkbox\" id=\"terms\" name=\"terms\">\n <label for=\"terms\">Ich stimme den Nutzungsbedingungen zu <span class=\"required\">*</span></label>\n </div>\n \n <button type=\"submit\">Registrieren</button>\n</form>",
|
"initialCode": "<form>\n <h2>Konto erstellen</h2>\n \n <label for=\"fullname\">Vollständiger Name *</label>\n <input type=\"text\" id=\"fullname\" name=\"fullname\">\n \n <label for=\"email\">E-Mail *</label>\n <input id=\"email\" name=\"email\">\n \n <label for=\"password\">Passwort *</label>\n <input id=\"password\" name=\"password\">\n \n <label>\n <input type=\"checkbox\" id=\"terms\" name=\"terms\">\n Ich stimme den Nutzungsbedingungen zu *\n </label>\n \n <button type=\"submit\">Registrieren</button>\n</form>",
|
||||||
"solution": "<form>\n <h2>Konto erstellen</h2>\n \n <div class=\"form-group\">\n <label for=\"fullname\">Vollständiger Name <span class=\"required\">*</span></label>\n <input type=\"text\" id=\"fullname\" name=\"fullname\" required>\n </div>\n \n <div class=\"form-group\">\n <label for=\"email\">E-Mail <span class=\"required\">*</span></label>\n <input type=\"email\" id=\"email\" name=\"email\" required>\n </div>\n \n <div class=\"form-group\">\n <label for=\"password\">Passwort <span class=\"required\">*</span></label>\n <input type=\"password\" id=\"password\" name=\"password\" required minlength=\"8\">\n </div>\n \n <div class=\"form-group checkbox-group\">\n <input type=\"checkbox\" id=\"terms\" name=\"terms\" required>\n <label for=\"terms\">Ich stimme den Nutzungsbedingungen zu <span class=\"required\">*</span></label>\n </div>\n \n <button type=\"submit\">Registrieren</button>\n</form>",
|
"solution": "<form>\n <h2>Konto erstellen</h2>\n \n <label for=\"fullname\">Vollständiger Name *</label>\n <input type=\"text\" id=\"fullname\" name=\"fullname\" required>\n \n <label for=\"email\">E-Mail *</label>\n <input type=\"email\" id=\"email\" name=\"email\" required>\n \n <label for=\"password\">Passwort *</label>\n <input type=\"password\" id=\"password\" name=\"password\" required minlength=\"8\">\n \n <label>\n <input type=\"checkbox\" id=\"terms\" name=\"terms\" required>\n Ich stimme den Nutzungsbedingungen zu *\n </label>\n \n <button type=\"submit\">Registrieren</button>\n</form>",
|
||||||
"previewContainer": "preview-area",
|
"previewContainer": "preview-area",
|
||||||
"validations": [
|
"validations": [
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user