// ========================================================================== // BASE FORMS // ========================================================================== // Theme-agnostic form structures and behaviors // Visual styling handled by themes // ========================================================================== // FORM CONTAINER .form { display: flex; flex-direction: column; gap: var(--form-gap, 24px); max-width: var(--form-max-width, 100%); margin: var(--form-margin, 0); &.form-inline { flex-direction: row; align-items: center; flex-wrap: wrap; gap: var(--form-inline-gap, 16px); } &.form-compact { gap: var(--form-compact-gap, 16px); } &.form-spacious { gap: var(--form-spacious-gap, 32px); } } // FIELDSET .fieldset { border: var(--fieldset-border, 1px solid transparent); border-radius: var(--fieldset-border-radius, 8px); padding: var(--fieldset-padding, 24px); margin: var(--fieldset-margin, 0 0 24px 0); .fieldset-legend { font-size: var(--fieldset-legend-size, 1.125rem); font-weight: var(--fieldset-legend-weight, 600); margin-bottom: var(--fieldset-legend-spacing, 16px); padding: var(--fieldset-legend-padding, 0 8px); } } // FORM FIELD .form-field { display: flex; flex-direction: column; gap: var(--form-field-gap, 8px); position: relative; &.form-field-inline { flex-direction: row; align-items: center; gap: var(--form-field-inline-gap, 12px); .form-label { flex-shrink: 0; margin-bottom: 0; min-width: var(--form-label-min-width, 120px); } .form-input-wrapper { flex: 1; } } &.form-field-checkbox, &.form-field-radio { flex-direction: row; align-items: flex-start; gap: var(--form-checkbox-gap, 8px); .form-input { flex-shrink: 0; margin: 0; } .form-label { flex: 1; margin-bottom: 0; cursor: pointer; line-height: var(--form-checkbox-label-line-height, 1.5); } } &.form-field-error { .form-input { border-color: var(--form-error-color, #dc3545); } .form-label { color: var(--form-error-color, #dc3545); } } &.form-field-success { .form-input { border-color: var(--form-success-color, #28a745); } } &.form-field-disabled { opacity: var(--form-disabled-opacity, 0.6); pointer-events: none; } } // FORM LABEL .form-label { font-size: var(--form-label-size, 0.875rem); font-weight: var(--form-label-weight, 500); line-height: var(--form-label-line-height, 1.4); margin-bottom: var(--form-label-spacing, 8px); cursor: pointer; &.form-label-required::after { content: var(--form-required-indicator, ' *'); color: var(--form-required-color, #dc3545); } &.form-label-optional::after { content: var(--form-optional-indicator, ' (optional)'); opacity: var(--form-optional-opacity, 0.6); font-weight: normal; } } // FORM INPUTS .form-input { width: 100%; padding: var(--form-input-padding, 12px 16px); border: var(--form-input-border, 1px solid #d1d5db); border-radius: var(--form-input-border-radius, 6px); font-family: inherit; font-size: var(--form-input-font-size, 1rem); line-height: var(--form-input-line-height, 1.5); transition: all var(--form-input-transition-duration, 0.2s) var(--form-input-transition-easing, ease); background: var(--form-input-background, transparent); &:focus { outline: var(--form-input-focus-outline, 2px solid transparent); outline-offset: var(--form-input-focus-outline-offset, 2px); border-color: var(--form-input-focus-border-color, #3b82f6); } &:disabled, &[readonly] { opacity: var(--form-input-disabled-opacity, 0.6); cursor: not-allowed; background: var(--form-input-disabled-background, #f9fafb); } &::placeholder { color: var(--form-input-placeholder-color, #9ca3af); opacity: 1; } } // INPUT SIZES .form-input-sm { --form-input-padding: 8px 12px; --form-input-font-size: 0.875rem; } .form-input-lg { --form-input-padding: 16px 20px; --form-input-font-size: 1.125rem; } // TEXTAREA .form-textarea { min-height: var(--form-textarea-min-height, 120px); resize: var(--form-textarea-resize, vertical); line-height: var(--form-textarea-line-height, 1.6); } // SELECT .form-select { cursor: pointer; appearance: none; background-image: var(--form-select-arrow, url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3E%3C/svg%3E")); background-position: right 12px center; background-repeat: no-repeat; background-size: 16px 12px; padding-right: var(--form-select-padding-right, 40px); &[multiple] { background-image: none; padding-right: var(--form-input-padding-right, 16px); } } // CHECKBOX & RADIO .form-checkbox, .form-radio { width: var(--form-checkbox-size, 18px); height: var(--form-checkbox-size, 18px); margin: var(--form-checkbox-margin, 2px 0 0 0); cursor: pointer; appearance: none; border: var(--form-checkbox-border, 2px solid #d1d5db); transition: all var(--form-checkbox-transition-duration, 0.2s) var(--form-checkbox-transition-easing, ease); &:focus { outline: var(--form-checkbox-focus-outline, 2px solid transparent); outline-offset: var(--form-checkbox-focus-outline-offset, 2px); } &:checked { background: var(--form-checkbox-checked-background, #3b82f6); border-color: var(--form-checkbox-checked-border-color, #3b82f6); } &:disabled { opacity: var(--form-checkbox-disabled-opacity, 0.5); cursor: not-allowed; } } .form-checkbox { border-radius: var(--form-checkbox-border-radius, 3px); &:checked { background-image: var(--form-checkbox-check-icon, url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m13.854 3.646-7.5 7.5a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6 10.293l7.146-7.147a.5.5 0 0 1 .708.708z'/%3E%3C/svg%3E")); background-position: center; background-repeat: no-repeat; background-size: 12px 12px; } &:indeterminate { background: var(--form-checkbox-indeterminate-background, #3b82f6); border-color: var(--form-checkbox-indeterminate-border-color, #3b82f6); background-image: var(--form-checkbox-indeterminate-icon, url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E")); background-position: center; background-repeat: no-repeat; background-size: 12px 12px; } } .form-radio { border-radius: 50%; &:checked { background-image: var(--form-radio-dot-icon, radial-gradient(circle at center, white 4px, transparent 4px)); } } // INPUT GROUPS .form-input-group { display: flex; position: relative; > .form-input { position: relative; flex: 1 1 auto; min-width: 0; &:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; border-left: none; } &:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; } &:focus { z-index: 2; } } .form-input-addon, .form-input-btn { display: flex; align-items: center; padding: var(--form-input-addon-padding, 12px 16px); font-size: var(--form-input-addon-font-size, 1rem); border: var(--form-input-border, 1px solid #d1d5db); white-space: nowrap; &:first-child { border-top-left-radius: var(--form-input-border-radius, 6px); border-bottom-left-radius: var(--form-input-border-radius, 6px); border-right: none; } &:last-child { border-top-right-radius: var(--form-input-border-radius, 6px); border-bottom-right-radius: var(--form-input-border-radius, 6px); border-left: none; } } .form-input-btn { cursor: pointer; transition: all var(--form-input-btn-transition-duration, 0.2s); &:hover { z-index: 2; } } } // FLOATING LABELS .form-floating { position: relative; .form-input { height: var(--form-floating-height, 56px); padding: var(--form-floating-padding, 20px 16px 8px 16px); &:focus, &:not(:placeholder-shown) { padding: var(--form-floating-padding-active, 20px 16px 8px 16px); } &::placeholder { opacity: 0; transition: opacity var(--form-floating-transition-duration, 0.2s); } &:focus::placeholder { opacity: 1; } } .form-label { position: absolute; top: 50%; left: 16px; margin-bottom: 0; pointer-events: none; transform: translateY(-50%); transition: all var(--form-floating-transition-duration, 0.2s) var(--form-floating-transition-easing, ease); transform-origin: left center; cursor: text; } .form-input:focus ~ .form-label, .form-input:not(:placeholder-shown) ~ .form-label { top: 12px; transform: translateY(0) scale(0.85); opacity: var(--form-floating-label-opacity, 0.7); } } // FORM FEEDBACK .form-feedback { font-size: var(--form-feedback-size, 0.875rem); line-height: var(--form-feedback-line-height, 1.4); margin-top: var(--form-feedback-spacing, 6px); &.form-feedback-error { color: var(--form-error-color, #dc3545); } &.form-feedback-success { color: var(--form-success-color, #28a745); } &.form-feedback-warning { color: var(--form-warning-color, #ffc107); } &.form-feedback-info { color: var(--form-info-color, #17a2b8); } } .form-help-text { font-size: var(--form-help-size, 0.875rem); line-height: var(--form-help-line-height, 1.4); margin-top: var(--form-help-spacing, 6px); opacity: var(--form-help-opacity, 0.7); } // FORM ACTIONS .form-actions { display: flex; gap: var(--form-actions-gap, 12px); align-items: center; padding-top: var(--form-actions-padding, 16px); margin-top: var(--form-actions-margin, 24px); border-top: var(--form-actions-border, 1px solid transparent); &.form-actions-center { justify-content: center; } &.form-actions-end { justify-content: flex-end; } &.form-actions-between { justify-content: space-between; } &.form-actions-stack { flex-direction: column; .btn { width: 100%; } } } @media (max-width: 576px) { .form-actions { flex-direction: column; .btn { width: 100%; } } .form-field-inline { flex-direction: column; align-items: stretch; .form-label { min-width: auto; } } } // FORM VALIDATION .was-validated { .form-input { &:valid { border-color: var(--form-success-color, #28a745); &:focus { border-color: var(--form-success-color, #28a745); box-shadow: var(--form-success-focus-shadow, 0 0 0 0.2rem rgba(40, 167, 69, 0.25)); } } &:invalid { border-color: var(--form-error-color, #dc3545); &:focus { border-color: var(--form-error-color, #dc3545); box-shadow: var(--form-error-focus-shadow, 0 0 0 0.2rem rgba(220, 53, 69, 0.25)); } } } } // ACCESSIBILITY @media (prefers-reduced-motion: reduce) { .form-input, .form-checkbox, .form-radio, .form-floating .form-label { transition: none; } } @media (prefers-contrast: high) { .form-input, .form-select, .form-textarea { border-width: 2px; } .form-checkbox, .form-radio { border-width: 3px; } }