Learn to code by watching others
22 |23 | See how experienced developers solve problems in real-time. Watching 24 | scripted tutorials is great, but understanding how developers think is 25 | invaluable. 26 |
27 |├── .gitignore ├── README.md ├── app.js ├── design ├── active-states.jpg ├── desktop-design.jpg ├── desktop-preview.jpg └── mobile-design.jpg ├── images ├── bg-intro-desktop.png ├── bg-intro-mobile.png ├── favicon-32x32.png └── icon-error.svg ├── index.html ├── style-guide.md └── style.css /.gitignore: -------------------------------------------------------------------------------- 1 | # Avoid accidental Sketch file upload 2 | ############################################### 3 | ## Please do not remove line 5 - thanks! 🙂 ## 4 | ############################################### 5 | *.sketch 6 | 7 | # Avoid accidental XD or Figma upload if you convert the design file 8 | ####################################################### 9 | ## Please do not remove lines 11 and 12 - thanks! 🙂 ## 10 | ####################################################### 11 | *.xd 12 | *.fig 13 | 14 | # Avoid your project being littered with annoying .DS_Store files! 15 | .DS_Store 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Frontend Mentor - Intro component with sign up form solution 2 | 3 | This is a solution to the [Intro component with sign up form challenge on Frontend Mentor](https://www.frontendmentor.io/challenges/intro-component-with-signup-form-5cf91bd49edda32581d28fd1). Frontend Mentor challenges help you improve your coding skills by building realistic projects. 4 | 5 | ## Table of contents 6 | 7 | - [Overview](#overview) 8 | - [The challenge](#the-challenge) 9 | - [Screenshot](#screenshot) 10 | - [Links](#links) 11 | - [My process](#my-process) 12 | - [Built with](#built-with) 13 | - [Author](#author) 14 | 15 | ## Overview 16 | 17 | ### The challenge 18 | 19 | Users should be able to: 20 | 21 | - View the optimal layout for the site depending on their device's screen size 22 | - See hover states for all interactive elements on the page 23 | - Receive an error message when the `form` is submitted if: 24 | - Any `input` field is empty. The message for this error should say _"[Field Name] cannot be empty"_ 25 | - The email address is not formatted correctly (i.e. a correct email address should have this structure: `name@host.tld`). The message for this error should say _"Looks like this is not an email"_ 26 | 27 | ### Screenshot 28 | 29 |  30 | 31 | ### Links 32 | 33 | - Solution URL: [https://github.com/JohnMwendwa/intro-component-with-signup-form](https://github.com/JohnMwendwa/intro-component-with-signup-form) 34 | - Live Site URL: [https://johnmwendwa.github.io/intro-component-with-signup-form](https://johnmwendwa.github.io/intro-component-with-signup-form/) 35 | 36 | ## My process 37 | 38 | ### Built with 39 | 40 | - Semantic HTML5 markup 41 | - CSS custom properties 42 | - CSS flexbox 43 | - CSS Grid 44 | - Mobile-first workflow 45 | - JavaScript 46 | 47 | ## Author 48 | 49 | - Website - [John Mwendwa](https://johnmwendwa.vercel.app/) 50 | - Frontend Mentor - [@JohnMwendwa](https://www.frontendmentor.io/profile/JohnMwendwa) 51 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | const form = document.querySelector("form"); 2 | const firstName = document.querySelector("#first_name"); 3 | const lastName = document.querySelector("#last_name"); 4 | const email = document.querySelector("#email"); 5 | const password = document.querySelector("#password"); 6 | const submitButton = document.querySelector("form button"); 7 | 8 | form.addEventListener("submit", (e) => { 9 | e.preventDefault(); 10 | 11 | checkInputs(); 12 | }); 13 | 14 | function checkInputs() { 15 | console.log(firstName); 16 | const firstNameValue = firstName.value.trim(); 17 | const lastNameValue = lastName.value.trim(); 18 | const emailValue = email.value.trim(); 19 | const passwordValue = password.value.trim(); 20 | const isValidEmail = (email) => { 21 | return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); 22 | }; 23 | 24 | const firtNameError = document.querySelector(".first_name"); 25 | const lastNameError = document.querySelector(".last_name"); 26 | const emailError = document.querySelector(".email"); 27 | const passwordError = document.querySelector(".password"); 28 | 29 | // Validate first name 30 | if (firstNameValue === "") { 31 | firstName.style.outline = "1px solid red"; 32 | firtNameError.style.display = "block"; 33 | document.querySelector(".error.first_name").textContent = 34 | "First Name cannot be empty"; 35 | return; 36 | } else { 37 | firstName.style.outline = "1px solid var(--grayishBlue)"; 38 | firtNameError.style.display = "none"; 39 | document.querySelector(".error.first_name").textContent = ""; 40 | } 41 | 42 | // Validate last name 43 | if (lastNameValue === "") { 44 | lastName.style.outline = "1px solid red"; 45 | lastNameError.style.display = "block"; 46 | document.querySelector(".error.last_name").textContent = 47 | "Last Name cannot be empty"; 48 | return; 49 | } else { 50 | lastName.style.outline = "1px solid var(--grayishBlue)"; 51 | lastNameError.style.display = "none"; 52 | document.querySelector(".error.last_name").textContent = ""; 53 | } 54 | 55 | // Validate email 56 | if (emailValue === "") { 57 | email.style.outline = "1px solid red"; 58 | emailError.style.display = "block"; 59 | document.querySelector(".error.email").textContent = 60 | "Email cannot be empty"; 61 | return; 62 | } else if (!isValidEmail(emailValue)) { 63 | email.style.outline = "1px solid red"; 64 | emailError.style.display = "block"; 65 | document.querySelector(".error.email").textContent = 66 | "Looks like this is not an email"; 67 | return; 68 | } else { 69 | email.style.outline = "1px solid var(--grayishBlue)"; 70 | emailError.style.display = "none"; 71 | document.querySelector(".error.email").textContent = ""; 72 | } 73 | 74 | // Validate password 75 | if (passwordValue === "") { 76 | password.style.outline = "1px solid red"; 77 | passwordError.style.display = "block"; 78 | document.querySelector(".error.password").textContent = 79 | "Password cannot be empty"; 80 | return; 81 | } else { 82 | password.style.outline = "1px solid var(--grayishBlue)"; 83 | passwordError.style.display = "none"; 84 | document.querySelector(".error.password").textContent = ""; 85 | } 86 | 87 | // change button text to "Submitted successfully" 88 | submitButton.textContent = "Submitted successfully"; 89 | 90 | // Reset form after 3 seconds 91 | setTimeout(() => { 92 | form.reset(); 93 | submitButton.textContent = "Claim your free trial"; 94 | }, 5000); 95 | } 96 | -------------------------------------------------------------------------------- /design/active-states.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnMwendwa/intro-component-with-signup-form/8922d5ad3859307a48d0c9616df20ea4fcd8f97a/design/active-states.jpg -------------------------------------------------------------------------------- /design/desktop-design.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnMwendwa/intro-component-with-signup-form/8922d5ad3859307a48d0c9616df20ea4fcd8f97a/design/desktop-design.jpg -------------------------------------------------------------------------------- /design/desktop-preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnMwendwa/intro-component-with-signup-form/8922d5ad3859307a48d0c9616df20ea4fcd8f97a/design/desktop-preview.jpg -------------------------------------------------------------------------------- /design/mobile-design.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnMwendwa/intro-component-with-signup-form/8922d5ad3859307a48d0c9616df20ea4fcd8f97a/design/mobile-design.jpg -------------------------------------------------------------------------------- /images/bg-intro-desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnMwendwa/intro-component-with-signup-form/8922d5ad3859307a48d0c9616df20ea4fcd8f97a/images/bg-intro-desktop.png -------------------------------------------------------------------------------- /images/bg-intro-mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnMwendwa/intro-component-with-signup-form/8922d5ad3859307a48d0c9616df20ea4fcd8f97a/images/bg-intro-mobile.png -------------------------------------------------------------------------------- /images/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnMwendwa/intro-component-with-signup-form/8922d5ad3859307a48d0c9616df20ea4fcd8f97a/images/favicon-32x32.png -------------------------------------------------------------------------------- /images/icon-error.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 14 | 15 | 16 |23 | See how experienced developers solve problems in real-time. Watching 24 | scripted tutorials is great, but understanding how developers think is 25 | invaluable. 26 |
27 |