Website Structure
This commit is contained in:
parent
62812f2090
commit
71f0676a62
22365 changed files with 4265753 additions and 791 deletions
87
Frontend-Learner/components/common/FormInput.vue
Normal file
87
Frontend-Learner/components/common/FormInput.vue
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
<script setup lang="ts">
|
||||
/**
|
||||
* @file FormInput.vue
|
||||
* @description Reusable input component with label, error handling, and support for disabled/required states.
|
||||
*/
|
||||
|
||||
defineProps<{
|
||||
modelValue: string
|
||||
label: string
|
||||
type?: string
|
||||
placeholder?: string
|
||||
error?: string
|
||||
required?: boolean
|
||||
disabled?: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
/** Update v-model value */
|
||||
'update:modelValue': [value: string]
|
||||
}>()
|
||||
|
||||
const updateValue = (event: Event) => {
|
||||
emit('update:modelValue', (event.target as HTMLInputElement).value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="form-group" :class="{ 'has-error': error }">
|
||||
<label class="input-label">
|
||||
{{ label }}
|
||||
<span v-if="required" class="required-mark">*</span>
|
||||
</label>
|
||||
<input
|
||||
:type="type || 'text'"
|
||||
:value="modelValue"
|
||||
class="input-field"
|
||||
:class="{ 'input-error': error }"
|
||||
:placeholder="placeholder"
|
||||
:disabled="disabled"
|
||||
@input="updateValue"
|
||||
>
|
||||
<span v-if="error" class="error-message">
|
||||
<span class="error-icon">⚠</span>
|
||||
{{ error }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.form-group {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.required-mark {
|
||||
color: var(--error);
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.input-error {
|
||||
border-color: var(--error) !important;
|
||||
background-color: rgba(239, 68, 68, 0.05);
|
||||
}
|
||||
|
||||
.input-error:focus {
|
||||
outline-color: var(--error) !important;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
color: var(--error);
|
||||
font-size: 12px;
|
||||
margin-top: 6px;
|
||||
animation: shake 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.error-icon {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@keyframes shake {
|
||||
0%, 100% { transform: translateX(0); }
|
||||
25% { transform: translateX(-4px); }
|
||||
75% { transform: translateX(4px); }
|
||||
}
|
||||
</style>
|
||||
Loading…
Add table
Add a link
Reference in a new issue