description Login - Simple Form

Demonstrates basic form fields and validation Async

Your username or email address
Your account password
Keep me logged in on this device
Rendered in 0.000s
Debug panel (development only) — 0.000s render
<style data-schemaforms-layout-support>
.pydantic-form,
.md-form {
    width: 100%;
    max-width: none;
}

.pydantic-form > div,
.pydantic-form > fieldset,
.pydantic-form > [class*="row"],
.md-form > div,
.md-form > fieldset,
.md-form > [class*="row"] {
    width: 100% !important;
    max-width: none !important;
}

.pydantic-form [class*="col-"],
.md-form [class*="col-"] {
    min-width: 0;
    flex: 1 1 auto !important;
}

.pydantic-form [class*="section"],
.pydantic-form [data-schemaforms-section],
.pydantic-form fieldset,
.md-form [class*="section"],
.md-form [data-schemaforms-section],
.md-form fieldset {
    width: 100% !important;
    max-width: none !important;
    box-sizing: border-box;
}
</style>

<!-- Material Design 3 Self-Contained Form -->
<style>
/* Material Design 3 Self-Contained Styles - Using !important to override any conflicting styles */
.md-form-container {
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
    max-width: 100% !important;
    margin: 0 !important;
    padding: 20px !important;
    line-height: 1.5 !important;
    color: #1c1b1f !important;
    background: #fef7ff !important;
    border: none !important;
    box-sizing: border-box !important;
    position: relative !important;
}

.md-form {
    width: 100% !important;
    background: #ffffff !important;
    border-radius: 28px !important;
    padding: 32px !important;
    box-shadow: 0 1px 2px rgba(0,0,0,0.3), 0 2px 6px 2px rgba(0,0,0,0.15) !important;
    border: none !important;
    margin: 0 !important;
    box-sizing: border-box !important;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
}

/* Reset any Bootstrap interference */
.md-form * {
    box-sizing: border-box !important;
}

/* Material Design Form Fields */
.md-field {
    margin-bottom: 32px !important;
    position: relative !important;
    width: 100% !important;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
}

/* Model list container styling to blend with Material Design */
.md-model-list-container {
    background: transparent !important;
    border: none !important;
    padding: 0 !important;
    margin: 0 !important;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
}

/* Override Bootstrap styles for model list items within Material Design */
.md-model-list-container .card {
    border: 1px solid #79747e !important;
    border-radius: 12px !important;
    box-shadow: none !important;
    margin-bottom: 16px !important;
    background: #ffffff !important;
}

.md-model-list-container .card-header {
    background: #f7f2fa !important;
    border-bottom: 1px solid #e7e0ec !important;
    border-radius: 12px 12px 0 0 !important;
    color: #1c1b1f !important;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
    font-weight: 500 !important;
}

.md-model-list-container .btn {
    border-radius: 20px !important;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
    font-weight: 500 !important;
    text-transform: none !important;
}

.md-model-list-container .btn-primary {
    background: #6750a4 !important;
    border-color: #6750a4 !important;
}

.md-model-list-container .btn-danger {
    background: #ba1a1a !important;
    border-color: #ba1a1a !important;
}

.md-model-list-wrapper {
    background: transparent !important;
    margin-bottom: 32px !important;
}

.md-model-list-container {
    border: 1px solid #e7e0ec !important;
    border-radius: 24px !important;
    padding: 16px 20px !important;
    background: #fff !important;
    box-shadow: 0 1px 3px rgba(0,0,0,0.08) !important;
}

.md-model-list-items {
    display: flex !important;
    flex-direction: column !important;
    gap: 16px !important;
}

.md-model-card {
    border: 1px solid #e7e0ec !important;
    border-radius: 20px !important;
    background: #ffffff !important;
    padding: 16px 20px !important;
    box-shadow: 0 1px 3px rgba(0,0,0,0.08) !important;
}

.md-model-card__header {
    display: flex !important;
    justify-content: space-between !important;
    align-items: center !important;
    margin-bottom: 12px !important;
}

.md-model-card__body {
    padding: 0 !important;
}

.md-model-list-actions {
    margin-top: 12px !important;
    display: flex !important;
    justify-content: flex-end !important;
}

.md-button-tonal {
    background: #e8def8 !important;
    color: #1c1b1f !important;
}

.md-button-tonal:hover {
    background: #cdc2db !important;
}

.md-button__icon {
    margin-right: 8px !important;
    width: 20px !important;
    height: 20px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    flex: 0 0 20px !important;
    fill: currentColor !important;
}

.md-button__label {
    font-weight: 500 !important;
}

/* Layout card styling */
.md-layout-card {
    background: #ffffff !important;
    border-radius: 24px !important;
    padding: 24px 28px !important;
    margin-bottom: 32px !important;
    box-shadow: 0 1px 3px rgba(0,0,0,0.2), 0 4px 8px rgba(0,0,0,0.1) !important;
    border: 1px solid #e7e0ec !important;
}

.md-layout-card__header {
    margin-bottom: 12px !important;
}

.md-layout-card__title {
    font-size: 18px !important;
    font-weight: 600 !important;
    color: #1c1b1f !important;
}

.md-layout-card__help {
    color: #49454f !important;
    font-size: 14px !important;
    margin-bottom: 12px !important;
}

.md-layout-card__content {
    display: flex !important;
    flex-direction: column !important;
    gap: 16px !important;
}

.md-field-label {
    display: block !important;
    color: #49454f !important;
    font-size: 14px !important;
    font-weight: 500 !important;
    margin-bottom: 8px !important;
    position: relative !important;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
    line-height: 1.4 !important;
}

.md-field-label.required::after {
    content: ' *' !important;
    color: #ba1a1a !important;
}

/* Material Design Outlined Text Fields */
.md-text-field {
    position: relative;
    width: 100%;
}

/* Field container */
.md-field {
    margin: 16px 0;
}

/* Field with icon layout */
.md-field-with-icon {
    display: flex !important;
    align-items: flex-start !important;
    gap: 12px !important;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
}

/* Input wrapper for proper label positioning */
.md-input-wrapper {
    position: relative !important;
    flex: 1 !important;
    width: 100% !important;
}

.md-input {
    width: 100% !important;
    padding: 16px !important;
    border: 1px solid #79747e !important;
    border-radius: 4px !important;
    background: transparent !important;
    color: #1c1b1f !important;
    font-size: 16px !important;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
    outline: none !important;
    transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1) !important;
    box-sizing: border-box !important;
    line-height: 1.5 !important;
    margin: 0 !important;
}

.md-input:focus {
    border-color: #6750a4 !important;
    border-width: 2px !important;
    padding: 15px !important; /* Adjust for thicker border */
    box-shadow: none !important;
}

/* Icon styling - positioned outside to the left of input */
.md-icon {
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    width: 24px !important;
    height: 24px !important;
    margin-top: 16px !important; /* Align with input padding */
    color: #49454f !important;
    flex-shrink: 0 !important;
    transition: color 0.15s cubic-bezier(0.4, 0, 0.2, 1) !important;
    fill: currentColor !important;
}

.md-field-with-icon:focus-within .md-icon {
    color: #6750a4 !important;
}

.md-input:focus + .md-floating-label,
.md-input:not(:placeholder-shown) + .md-floating-label,
.md-textarea:focus + .md-floating-label,
.md-textarea:not(:placeholder-shown) + .md-floating-label,
.md-select:focus + .md-floating-label {
    transform: translateY(-28px) scale(0.75) !important;
    color: #6750a4 !important;
    background: #ffffff !important;
    padding: 0 4px !important;
}

.md-floating-label {
    position: absolute !important;
    left: 16px !important;
    top: 16px !important;
    color: #49454f !important;
    font-size: 16px !important;
    transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1) !important;
    pointer-events: none !important;
    background: transparent !important;
    z-index: 1 !important;
    transform-origin: left top !important;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
    font-weight: 400 !important;
    line-height: 1.4 !important;
}

.md-input:focus + .md-floating-label,
.md-input:not(:placeholder-shown) + .md-floating-label {
    transform: translateY(-28px) scale(0.75) !important;
    color: #6750a4;
    background: #ffffff;
    padding: 0 4px;
}

.md-input.error {
    border-color: #ba1a1a;
}

.md-input.error:focus {
    border-color: #ba1a1a;
}

.md-input.error + .md-floating-label {
    color: #ba1a1a;
}

/* Material Design Select */
.md-select {
    width: 100%;
    padding: 16px;
    border: 1px solid #79747e;
    border-radius: 4px;
    background: transparent;
    color: #1c1b1f;
    font-size: 16px;
    font-family: inherit;
    outline: none;
    cursor: pointer;
    transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
    box-sizing: border-box;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%2349454f' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
    background-position: right 12px center;
    background-repeat: no-repeat;
    background-size: 16px;
    padding-right: 40px;
}

.md-select:focus {
    border-color: #6750a4;
    border-width: 2px;
    padding: 15px 39px 15px 15px; /* Adjust for thicker border */
}

.md-select:focus + .md-floating-label {
    transform: translateY(-28px) scale(0.75);
    color: #6750a4;
    background: #ffffff;
    padding: 0 4px;
}

/* Material Design Textarea */
.md-textarea {
    width: 100%;
    min-height: 120px;
    padding: 16px;
    border: 1px solid #79747e;
    border-radius: 4px;
    background: transparent;
    color: #1c1b1f;
    font-size: 16px;
    font-family: inherit;
    outline: none;
    resize: vertical;
    transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
    box-sizing: border-box;
}

.md-textarea:focus {
    border-color: #6750a4;
    border-width: 2px;
    padding: 15px; /* Adjust for thicker border */
}

.md-textarea:focus + .md-floating-label,
.md-textarea:not(:placeholder-shown) + .md-floating-label {
    transform: translateY(-28px) scale(0.75);
    color: #6750a4;
    background: #ffffff;
    padding: 0 4px;
}

/* Material Design Checkboxes */
.md-checkbox-container {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    margin: 16px 0;
    cursor: pointer;
}

.md-checkbox {
    width: 18px;
    height: 18px;
    border: 2px solid #79747e;
    border-radius: 2px;
    background: transparent;
    cursor: pointer;
    position: relative;
    transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    margin-top: 2px; /* Align with text baseline */
    flex-shrink: 0;
}

.md-checkbox:checked {
    background: #6750a4;
    border-color: #6750a4;
}

.md-checkbox:checked::after {
    content: '';
    position: absolute;
    top: 1px;
    left: 4px;
    width: 6px;
    height: 10px;
    border: solid white;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

.md-checkbox-label {
    color: #1c1b1f;
    font-size: 16px;
    cursor: pointer;
    line-height: 1.5;
}

/* Material Design Buttons */
.md-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 10px 24px;
    border: none;
    border-radius: 20px;
    font-size: 14px;
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
    text-decoration: none;
    box-sizing: border-box;
    min-width: 64px;
    height: 40px;
    position: relative;
    overflow: hidden;
}

.md-button-filled {
    background: #6750a4;
    color: #ffffff;
    box-shadow: 0 1px 2px rgba(0,0,0,0.3), 0 1px 3px 1px rgba(0,0,0,0.15);
}

.md-button-filled:hover {
    background: #5a43a0;
    box-shadow: 0 1px 2px rgba(0,0,0,0.3), 0 2px 6px 2px rgba(0,0,0,0.15);
    transform: translateY(-1px);
}

.md-button-filled:active {
    transform: translateY(0);
    box-shadow: 0 1px 2px rgba(0,0,0,0.3), 0 1px 3px 1px rgba(0,0,0,0.15);
}

/* Help Text */
.md-help-text {
    font-size: 12px;
    color: #49454f;
    margin-top: 4px;
    line-height: 1.33;
    padding-left: 16px;
}

/* Compatibility: model-list/material mixed markup may emit `.help-text` */
.md-form .help-text {
    display: block;
    font-size: 12px;
    color: #49454f;
    margin-top: 4px;
    line-height: 1.33;
}

/* Error Text */
.md-error-text {
    font-size: 12px;
    color: #ba1a1a;
    margin-top: 4px;
    line-height: 1.33;
    font-weight: 400;
    padding-left: 16px;
}

.md-error-summary {
    border: 1px solid #f2b8b5;
    background: #ffdad6;
    color: #410e0b;
    border-radius: 12px;
    padding: 12px 14px;
}

.md-error-summary__title {
    font-weight: 600;
    margin-bottom: 6px;
}

.md-error-summary__list {
    margin: 0;
    padding-left: 1.25rem;
}

.md-error-summary__list li {
    margin-bottom: 2px;
}

/* Number and Date Inputs */
.md-input[type="number"],
.md-input[type="date"],
.md-input[type="email"],
.md-input[type="password"],
.md-input[type="tel"],
.md-input[type="url"] {
    /* Inherit all md-input styles */
}

.md-input[type="color"] {
    height: 56px;
    padding: 8px;
    cursor: pointer;
}

.md-input[type="range"] {
    padding: 16px 8px;
}

/* Compatibility: select controls rendered with Materialize-style class name */
.md-form select.browser-default {
    width: 100%;
    min-height: 40px;
    padding: 8px 10px;
    border: 1px solid #cac4d0;
    border-radius: 6px;
    background: #ffffff;
    box-sizing: border-box;
}

.md-form .md-input-wrapper {
    width: 100%;
}

/* Placeholder styling */
.md-input::placeholder {
    color: transparent;
}

.md-input:focus::placeholder {
    color: #49454f;
}

/* State layers for interactive elements */
.md-button-filled::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: currentColor;
    opacity: 0;
    transition: opacity 0.15s cubic-bezier(0.4, 0, 0.2, 1);
    border-radius: inherit;
}

.md-button-filled:hover::before {
    opacity: 0.08;
}

.md-button-filled:focus::before {
    opacity: 0.12;
}

.md-button-filled:active::before {
    opacity: 0.16;
}

/* Responsive Design */
@media (max-width: 768px) {
    .md-form {
        padding: 24px 16px;
        border-radius: 28px;
    }

    .md-field {
        margin-bottom: 24px;
    }
}

/* Typography Scale */
.md-headline-small {
    font-size: 24px;
    font-weight: 400;
    line-height: 32px;
    color: #1c1b1f;
}

.md-body-large {
    font-size: 16px;
    font-weight: 400;
    line-height: 24px;
    color: #1c1b1f;
}

.md-body-medium {
    font-size: 14px;
    font-weight: 400;
    line-height: 20px;
    color: #49454f;
}

.md-label-large {
    font-size: 14px;
    font-weight: 500;
    line-height: 20px;
    color: #1c1b1f;
}

/* Surface colors and elevation */
.md-surface {
    background: #fef7ff;
    color: #1c1b1f;
}

.md-surface-container {
    background: #f3f0ff;
    color: #1c1b1f;
}

.md-surface-container-high {
    background: #e7e0ec;
    color: #1c1b1f;
}
</style>

<div class="md-form-container">

<form id=""
      class="pydantic-form md-form col s12"
      style=""
      method="POST"
      action="/login?style=material"
      >
    
    
<div class="md-field">
    
<div class="md-field-with-icon">
    <svg class="material-icons md-icon" viewBox="0 0 24 24" focusable="false" aria-hidden="true"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" /></svg>
    
<div class="md-input-wrapper">
    
<input type="text"
       name="username"
       id="username"
       class="md-input"
       value="demo_user"
    placeholder=" " required="required" aria-required="true">

    <label class="md-floating-label" for="username">Username *</label>
</div>

</div>

    
<div class="md-help-text">Your username or email address</div>

    
</div>


<div class="md-field">
    
<div class="md-field-with-icon">
    <svg class="material-icons md-icon" viewBox="0 0 24 24" focusable="false" aria-hidden="true"><path d="M12 17a2 2 0 0 0 2-2v-2a2 2 0 0 0-4 0v2a2 2 0 0 0 2 2zm6-7h-1V8a5 5 0 0 0-10 0v2H6c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2v-8c0-1.1-.9-2-2-2zm-3 0H9V8a3 3 0 0 1 6 0v2z" /></svg>
    
<div class="md-input-wrapper">
    
<input type="password"
       name="password"
       id="password"
       class="md-input"
       value="demo_pass"
    placeholder=" " required="required" aria-required="true">

    <label class="md-floating-label" for="password">Password *</label>
</div>

</div>

    
<div class="md-help-text">Your account password</div>

    
</div>


<div class="md-field">
    <div class="md-checkbox-container">
        <input type="checkbox"
               name="remember_me"
               id="remember_me"
               class="md-checkbox"
               value="true"
             checked="checked" >
        <label for="remember_me" class="md-checkbox-label">Remember me</label>
    </div>
    
<div class="md-help-text">Keep me logged in on this device</div>

    
</div>

    
<div class="md-field">
    <button type="submit" class="md-button md-button-filled">Submit</button>
</div>
<div style="margin-top: 0.5rem; font-size: 0.75rem; color: #6c757d; text-align: right;">Rendered in 0.000s</div>
</form>

</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
    // Material Design 3 form enhancements

    // Floating label functionality for outlined text fields
    function initializeFloatingLabels() {
        const textFields = document.querySelectorAll('.md-input, .md-textarea, .md-select');

        textFields.forEach(input => {
            const label = input.nextElementSibling;
            if (label && label.classList.contains('md-floating-label')) {

                // Check initial state
                function updateLabelState() {
                    const hasValue = input.value && input.value.trim() !== '';
                    const isFocused = document.activeElement === input;

                    if (hasValue || isFocused) {
                        label.style.transform = 'translateY(-28px) scale(0.75)';
                        label.style.color = isFocused ? '#6750a4' : '#49454f';
                        label.style.background = '#ffffff';
                        label.style.padding = '0 4px';
                    } else {
                        label.style.transform = 'translateY(0) scale(1)';
                        label.style.color = '#49454f';
                        label.style.background = 'transparent';
                        label.style.padding = '0';
                    }
                }

                // Set up event listeners
                input.addEventListener('focus', updateLabelState);
                input.addEventListener('blur', updateLabelState);
                input.addEventListener('input', updateLabelState);

                // Initial state check
                updateLabelState();
            }
        });
    }

    // Enhanced focus and blur effects
    const inputs = document.querySelectorAll('.md-input, .md-select, .md-textarea');
    inputs.forEach(input => {
        input.addEventListener('focus', function() {
            this.style.transform = 'scale(1.01)';
            this.style.transition = 'all 0.15s cubic-bezier(0.4, 0, 0.2, 1)';
        });

        input.addEventListener('blur', function() {
            this.style.transform = 'scale(1)';
        });
    });

    // Checkbox interactions with Material Design ripple effect
    const checkboxes = document.querySelectorAll('.md-checkbox');
    checkboxes.forEach(checkbox => {
        checkbox.addEventListener('change', function() {
            const container = this.closest('.md-checkbox-container');
            if (this.checked) {
                // Create ripple effect
                const ripple = document.createElement('div');
                ripple.style.position = 'absolute';
                ripple.style.borderRadius = '50%';
                ripple.style.background = 'rgba(103, 80, 164, 0.3)';
                ripple.style.width = '40px';
                ripple.style.height = '40px';
                ripple.style.left = '-11px';
                ripple.style.top = '-11px';
                ripple.style.pointerEvents = 'none';
                ripple.style.transform = 'scale(0)';
                ripple.style.transition = 'transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)';

                this.style.position = 'relative';
                this.appendChild(ripple);

                // Animate ripple
                setTimeout(() => {
                    ripple.style.transform = 'scale(1)';
                    setTimeout(() => {
                        ripple.style.opacity = '0';
                        setTimeout(() => {
                            if (ripple.parentNode) {
                                ripple.parentNode.removeChild(ripple);
                            }
                        }, 300);
                    }, 200);
                }, 10);
            }
        });
    });

    // Enhanced form validation with Material Design styling
    const form = document.querySelector('.md-form');
    if (form) {
        form.addEventListener('submit', function(e) {
            const requiredInputs = this.querySelectorAll('input[required], select[required], textarea[required]');
            let hasErrors = false;

            requiredInputs.forEach(input => {
                const value = input.type === 'checkbox' ? input.checked : input.value.trim();
                const fieldContainer = input.closest('.md-field');

                if (!value) {
                    input.classList.add('error');

                    // Add error styling to label
                    const label = input.nextElementSibling;
                    if (label && label.classList.contains('md-floating-label')) {
                        label.style.color = '#ba1a1a';
                    }

                    // Create or update error message
                    let errorDiv = fieldContainer.querySelector('.md-error-text');
                    if (!errorDiv) {
                        errorDiv = document.createElement('div');
                        errorDiv.className = 'md-error-text';
                        fieldContainer.appendChild(errorDiv);
                    }
                    errorDiv.textContent = 'This field is required';

                    hasErrors = true;
                } else {
                    input.classList.remove('error');

                    // Remove error styling from label
                    const label = input.nextElementSibling;
                    if (label && label.classList.contains('md-floating-label')) {
                        label.style.color = input === document.activeElement ? '#6750a4' : '#49454f';
                    }

                    // Remove error message if it was dynamically added
                    const errorDiv = fieldContainer.querySelector('.md-error-text');
                    if (errorDiv && errorDiv.textContent === 'This field is required') {
                        errorDiv.remove();
                    }
                }
            });

            if (hasErrors) {
                e.preventDefault();
                // Scroll to first error with smooth animation
                const firstError = this.querySelector('.error');
                if (firstError) {
                    firstError.scrollIntoView({
                        behavior: 'smooth',
                        block: 'center',
                        inline: 'nearest'
                    });
                    // Focus the field for better UX
                    setTimeout(() => {
                        firstError.focus();
                    }, 500);
                }
            }
        });

        // Real-time validation for better UX
        const allInputs = form.querySelectorAll('input, select, textarea');
        allInputs.forEach(input => {
            input.addEventListener('blur', function() {
                if (this.hasAttribute('required')) {
                    const value = this.type === 'checkbox' ? this.checked : this.value.trim();
                    const fieldContainer = this.closest('.md-field');

                    if (!value) {
                        this.classList.add('error');
                        const label = this.nextElementSibling;
                        if (label && label.classList.contains('md-floating-label')) {
                            label.style.color = '#ba1a1a';
                        }
                    } else {
                        this.classList.remove('error');
                        const label = this.nextElementSibling;
                        if (label && label.classList.contains('md-floating-label')) {
                            label.style.color = '#49454f';
                        }
                    }
                }
            });
        });
    }

    # Initialize floating labels
    initializeFloatingLabels();

    # Reinitialize for dynamically added content
    window.reinitializeMaterialForms = function() {
        initializeFloatingLabels();
    };
});
</script>


<script>
(function() {
    document.addEventListener('DOMContentLoaded', function() {
        // Prevent Enter key from submitting forms unless on submit button
        const forms = document.querySelectorAll('form.md-form, form.pydantic-form');
        forms.forEach(function(form) {
            form.addEventListener('keydown', function(e) {
                // Check if Enter key is pressed
                if (e.key === 'Enter' || e.keyCode === 13) {
                    const target = e.target;

                    // Allow Enter in textareas (for multi-line input)
                    if (target.tagName === 'TEXTAREA') {
                        return;
                    }

                    // Allow Enter on submit buttons
                    if (target.tagName === 'BUTTON' && target.type === 'submit') {
                        return;
                    }

                    // Allow Enter on input type="submit"
                    if (target.tagName === 'INPUT' && target.type === 'submit') {
                        return;
                    }

                    // Prevent form submission for all other cases
                    e.preventDefault();
                    return false;
                }
            });
        });
    });
})();
</script>
class MinimalLoginForm(FormModel):
    """Minimal form example - Simple login form."""

    username: str = FormField(
        title="Username",
        input_type="text",
        placeholder="Enter your username",
        help_text="Your username or email address",
        icon="person",
        min_length=3,
        max_length=50,
    )

    password: str = FormField(
        title="Password",
        input_type="password",
        placeholder="Enter your password",
        help_text="Your account password",
        icon="lock",
        min_length=6,
    )

    remember_me: bool = FormField(
        False,
        title="Remember me",
        input_type="checkbox",
        help_text="Keep me logged in on this device",
        icon="check2-square",
    )

    @field_validator("username")
    @classmethod
    def validate_username(cls, v):
        if not v.strip():
            raise ValueError("Username cannot be empty")
        return v.strip()
{
  "description": "Minimal form example - Simple login form.",
  "properties": {
    "username": {
      "autofocus": false,
      "description": "Your username or email address",
      "disabled": false,
      "help_text": "Your username or email address",
      "icon": "person",
      "input_type": "text",
      "maxLength": 50,
      "minLength": 3,
      "placeholder": "Enter your username",
      "readonly": false,
      "title": "Username",
      "type": "string"
    },
    "password": {
      "autofocus": false,
      "description": "Your account password",
      "disabled": false,
      "help_text": "Your account password",
      "icon": "lock",
      "input_type": "password",
      "minLength": 6,
      "placeholder": "Enter your password",
      "readonly": false,
      "title": "Password",
      "type": "string"
    },
    "remember_me": {
      "autofocus": false,
      "default": false,
      "description": "Keep me logged in on this device",
      "disabled": false,
      "help_text": "Keep me logged in on this device",
      "icon": "check2-square",
      "input_type": "checkbox",
      "readonly": false,
      "title": "Remember me",
      "type": "boolean"
    }
  },
  "required": [
    "username",
    "password"
  ],
  "title": "MinimalLoginForm",
  "type": "object"
}
{
  "username": {
    "required": true,
    "type": "string",
    "minLength": 3,
    "maxLength": 50
  },
  "password": {
    "required": true,
    "type": "string",
    "minLength": 6
  },
  "remember_me": {
    "required": false,
    "type": "boolean"
  }
}
{
  "errors": {},
  "data": {
    "username": "demo_user",
    "password": "demo_pass",
    "remember_me": true
  }
}
API Endpoints Available
Schema: GET /api/forms/login/schema
Render: GET /api/forms/login/render
Submit: POST /api/forms/login/submit