enzostvs HF Staff commited on
Commit
4e0616b
·
verified ·
1 Parent(s): 64efb4e

update the UI of the contact form

Browse files
Files changed (2) hide show
  1. script.js +29 -17
  2. style.css +99 -3
script.js CHANGED
@@ -71,9 +71,20 @@ backToTop?.addEventListener('click', () => window.scrollTo({ top: 0, behavior: '
71
  // Contact form with validation
72
  const form = document.getElementById('contact-form');
73
  const status = document.getElementById('form-status');
 
 
74
  const submitBtn = document.getElementById('submit-btn');
75
  const submitText = document.getElementById('submit-text');
 
76
 
 
 
 
 
 
 
 
 
77
  function validateForm() {
78
  let isValid = true;
79
 
@@ -153,20 +164,21 @@ document.querySelectorAll('input, textarea').forEach(input => {
153
  // Handle form submission
154
  form?.addEventListener('submit', async (e) => {
155
  e.preventDefault();
156
-
157
  if (!validateForm()) {
158
- status.textContent = 'Please fix the errors above';
 
159
  status.classList.add('text-red-400');
160
- status.classList.remove('text-zinc-400');
 
161
  return;
162
  }
163
 
164
  // Reset status
165
- status.textContent = '';
166
- status.classList.remove('text-red-400');
 
167
  status.classList.add('text-zinc-400');
168
-
169
- // Disable form and show loading state
170
  submitBtn.disabled = true;
171
  submitText.textContent = 'Sending...';
172
  submitBtn.classList.add('opacity-75');
@@ -180,27 +192,27 @@ form?.addEventListener('submit', async (e) => {
180
 
181
  // For demo purposes, just log the data
182
  console.log('Form submitted:', data);
183
-
184
  // Success
185
- status.textContent = 'Message sent successfully! I\'ll get back to you soon.';
186
- status.classList.remove('text-zinc-400');
 
187
  status.classList.add('text-emerald-400');
188
-
189
- // Reset form
190
  form.reset();
191
 
192
  // Reset button state
193
  submitBtn.disabled = false;
194
  submitText.textContent = 'Send message';
195
  submitBtn.classList.remove('opacity-75');
196
-
197
  } catch (error) {
198
  console.error('Form submission error:', error);
199
- status.textContent = 'Something went wrong. Please try again or email me directly.';
200
- status.classList.remove('text-zinc-400');
 
201
  status.classList.add('text-red-400');
202
-
203
- // Reset button state
204
  submitBtn.disabled = false;
205
  submitText.textContent = 'Send message';
206
  submitBtn.classList.remove('opacity-75');
 
71
  // Contact form with validation
72
  const form = document.getElementById('contact-form');
73
  const status = document.getElementById('form-status');
74
+ const statusIcon = document.getElementById('status-icon');
75
+ const statusText = document.getElementById('status-text');
76
  const submitBtn = document.getElementById('submit-btn');
77
  const submitText = document.getElementById('submit-text');
78
+ const resetBtn = document.getElementById('reset-btn');
79
 
80
+ // Reset button functionality
81
+ resetBtn?.addEventListener('click', () => {
82
+ form.reset();
83
+ document.querySelectorAll('.error-message').forEach(el => el.classList.add('hidden'));
84
+ document.querySelectorAll('input, textarea').forEach(el => el.classList.remove('border-red-400'));
85
+ statusText.textContent = '';
86
+ statusIcon.innerHTML = '';
87
+ });
88
  function validateForm() {
89
  let isValid = true;
90
 
 
164
  // Handle form submission
165
  form?.addEventListener('submit', async (e) => {
166
  e.preventDefault();
 
167
  if (!validateForm()) {
168
+ statusText.textContent = 'Please fix the errors above';
169
+ statusIcon.innerHTML = '<i data-feather="alert-circle" class="w-4 h-4"></i>';
170
  status.classList.add('text-red-400');
171
+ status.classList.remove('text-zinc-400', 'text-emerald-400');
172
+ feather.replace();
173
  return;
174
  }
175
 
176
  // Reset status
177
+ statusText.textContent = '';
178
+ statusIcon.innerHTML = '';
179
+ status.classList.remove('text-red-400', 'text-emerald-400');
180
  status.classList.add('text-zinc-400');
181
+ // Disable form and show loading state
 
182
  submitBtn.disabled = true;
183
  submitText.textContent = 'Sending...';
184
  submitBtn.classList.add('opacity-75');
 
192
 
193
  // For demo purposes, just log the data
194
  console.log('Form submitted:', data);
 
195
  // Success
196
+ statusText.textContent = 'Message sent successfully! I\'ll get back to you soon.';
197
+ statusIcon.innerHTML = '<i data-feather="check-circle" class="w-4 h-4"></i>';
198
+ status.classList.remove('text-zinc-400', 'text-red-400');
199
  status.classList.add('text-emerald-400');
200
+ feather.replace();
201
+ // Reset form
202
  form.reset();
203
 
204
  // Reset button state
205
  submitBtn.disabled = false;
206
  submitText.textContent = 'Send message';
207
  submitBtn.classList.remove('opacity-75');
 
208
  } catch (error) {
209
  console.error('Form submission error:', error);
210
+ statusText.textContent = 'Something went wrong. Please try again or email me directly.';
211
+ statusIcon.innerHTML = '<i data-feather="x-circle" class="w-4 h-4"></i>';
212
+ status.classList.remove('text-zinc-400', 'text-emerald-400');
213
  status.classList.add('text-red-400');
214
+ feather.replace();
215
+ // Reset button state
216
  submitBtn.disabled = false;
217
  submitText.textContent = 'Send message';
218
  submitBtn.classList.remove('opacity-75');
style.css CHANGED
@@ -143,15 +143,111 @@ a { text-decoration: none; }
143
  .mobile-link {
144
  @apply px-3 py-2 rounded-md text-zinc-300 hover:text-white hover:bg-white/10 transition;
145
  }
146
-
147
  /* Buttons */
148
  .btn-primary {
149
- @apply inline-flex items-center gap-2 rounded-lg border border-white/10 bg-[color:rgb(var(--color-primary-500)_/_0.2)] text-[color:rgb(var(--color-primary-500))] hover:bg-[color:rgb(var(--color-primary-500)_/_0.3)] px-5 py-3 font-medium transition-all duration-200 shadow-glow hover:shadow-lg hover:scale-[1.02];
150
  }
151
  .btn-ghost {
152
- @apply inline-flex items-center gap-2 rounded-md border border-white/10 bg-white/5 hover:bg-white/10 text-zinc-200 hover:text-white px-4 py-2 font-medium transition;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  }
154
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  /* Inputs */
156
  .label {
157
  @apply block text-sm font-medium text-zinc-300 mb-2;
 
143
  .mobile-link {
144
  @apply px-3 py-2 rounded-md text-zinc-300 hover:text-white hover:bg-white/10 transition;
145
  }
 
146
  /* Buttons */
147
  .btn-primary {
148
+ @apply inline-flex items-center gap-2 rounded-lg border border-white/10 bg-[color:rgb(var(--color-primary-500)_/_0.2)] text-[color:rgb(var(--color-primary-500))] hover:bg-[color:rgb(var(--color-primary-500)_/_0.3)] px-5 py-3 font-medium transition-all duration-200 shadow-glow hover:shadow-lg hover:scale-[1.02] relative overflow-hidden;
149
  }
150
  .btn-ghost {
151
+ @apply inline-flex items-center gap-2 rounded-md border border-white/10 bg-white/5 hover:bg-white/10 text-zinc-200 hover:text-white px-4 py-2 font-medium transition-all duration-200;
152
+ }
153
+
154
+ /* Enhanced form styles */
155
+ .form-field-input {
156
+ @apply w-full rounded-lg border border-white/10 bg-white/5 text-zinc-200 placeholder:text-zinc-500 px-4 py-3 outline-none focus:border-[color:rgb(var(--color-primary-500)_/_0.6)] focus:ring-2 focus:ring-[color:rgb(var(--color-primary-500)_/_0.2)] transition-all duration-200;
157
+ }
158
+
159
+ .form-field-input.pl-11 {
160
+ padding-left: 2.75rem;
161
+ }
162
+
163
+ /* Form field hover and focus effects */
164
+ .form-field-input:hover {
165
+ border-color: rgba(var(--color-primary-500), 0.3);
166
+ background: rgba(255, 255, 255, 0.08);
167
+ }
168
+
169
+ .form-field-input:focus {
170
+ transform: translateY(-1px);
171
+ box-shadow: 0 4px 12px rgba(var(--color-primary-500), 0.15);
172
+ }
173
+
174
+ /* Enhanced error states */
175
+ .form-field-input.error {
176
+ border-color: rgb(239, 68, 68);
177
+ background: rgba(239, 68, 68, 0.05);
178
+ animation: shake 0.3s ease-in-out;
179
+ }
180
+
181
+ @keyframes shake {
182
+ 0%, 100% { transform: translateX(0); }
183
+ 25% { transform: translateX(-5px); }
184
+ 75% { transform: translateX(5px); }
185
+ }
186
+
187
+ /* Status indicator animations */
188
+ #form-status {
189
+ @apply transition-all duration-300;
190
+ }
191
+
192
+ #form-status .feather {
193
+ @apply transition-all duration-300;
194
+ }
195
+
196
+ /* Success state animation */
197
+ @keyframes success-pulse {
198
+ 0% { transform: scale(1); }
199
+ 50% { transform: scale(1.1); }
200
+ 100% { transform: scale(1); }
201
  }
202
 
203
+ #form-status.text-emerald-400 .feather {
204
+ animation: success-pulse 0.5s ease-in-out;
205
+ }
206
+
207
+ /* Loading state for submit button */
208
+ .btn-primary:disabled {
209
+ @apply opacity-75 cursor-not-allowed;
210
+ position: relative;
211
+ }
212
+
213
+ .btn-primary:disabled::after {
214
+ content: '';
215
+ position: absolute;
216
+ top: 50%;
217
+ left: 50%;
218
+ width: 16px;
219
+ height: 16px;
220
+ margin: -8px 0 0 -8px;
221
+ border: 2px solid transparent;
222
+ border-top-color: currentColor;
223
+ border-radius: 50%;
224
+ animation: spin 0.8s linear infinite;
225
+ }
226
+
227
+ @keyframes spin {
228
+ to { transform: rotate(360deg); }
229
+ }
230
+
231
+ /* Light theme form adjustments */
232
+ html.light .form-field-input {
233
+ background: rgba(255, 255, 255, 0.9);
234
+ border-color: rgba(15, 23, 42, 0.15);
235
+ color: rgb(15, 23, 42);
236
+ }
237
+
238
+ html.light .form-field-input:hover {
239
+ border-color: rgba(var(--color-primary-500), 0.3);
240
+ background: rgba(255, 255, 255, 0.95);
241
+ }
242
+
243
+ html.light .form-field-input::placeholder {
244
+ color: rgb(100, 116, 139);
245
+ }
246
+
247
+ html.light .form-field-input.error {
248
+ background: rgba(239, 68, 68, 0.05);
249
+ border-color: rgb(239, 68, 68);
250
+ }
251
  /* Inputs */
252
  .label {
253
  @apply block text-sm font-medium text-zinc-300 mb-2;