├── css └── style.css ├── images ├── button-dark.avif ├── button-deep-blue-metallic.avif ├── button-light.avif ├── button-pearl-white.avif ├── button-quicksilver.avif ├── button-solid-black.avif ├── button-stealth-grey.avif ├── button-ultra-red.avif ├── logo.svg ├── model-y-deep-blue-metallic-performance.jpg ├── model-y-deep-blue-metallic.jpg ├── model-y-interior-dark.jpg ├── model-y-interior-light.jpg ├── model-y-pearl-white-performance.jpg ├── model-y-pearl-white.jpg ├── model-y-quicksilver-performance.jpg ├── model-y-quicksilver.jpg ├── model-y-solid-black-performance.jpg ├── model-y-solid-black.jpg ├── model-y-stealth-grey-performance.jpg ├── model-y-stealth-grey.jpg ├── model-y-ultra-red-performance.jpg ├── model-y-ultra-red.jpg └── screen.jpg ├── index.html ├── js └── main.js └── readme.md /css/style.css: -------------------------------------------------------------------------------- 1 | .btn-selected { 2 | border: 2px solid #ccc; 3 | border-radius: 50%; 4 | padding: 8px; 5 | transition: transform 0.3s; 6 | } 7 | 8 | .btn-selected:hover { 9 | transform: scale(1) !important; 10 | } 11 | 12 | #top-bar { 13 | transition: transform 0.5s ease-in-out; 14 | } 15 | 16 | .visible-bar { 17 | transform: translateY(0); 18 | } 19 | 20 | .hidden-bar { 21 | transform: translateY(-100%); 22 | } 23 | -------------------------------------------------------------------------------- /images/button-dark.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/button-dark.avif -------------------------------------------------------------------------------- /images/button-deep-blue-metallic.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/button-deep-blue-metallic.avif -------------------------------------------------------------------------------- /images/button-light.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/button-light.avif -------------------------------------------------------------------------------- /images/button-pearl-white.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/button-pearl-white.avif -------------------------------------------------------------------------------- /images/button-quicksilver.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/button-quicksilver.avif -------------------------------------------------------------------------------- /images/button-solid-black.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/button-solid-black.avif -------------------------------------------------------------------------------- /images/button-stealth-grey.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/button-stealth-grey.avif -------------------------------------------------------------------------------- /images/button-ultra-red.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/button-ultra-red.avif -------------------------------------------------------------------------------- /images/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/model-y-deep-blue-metallic-performance.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/model-y-deep-blue-metallic-performance.jpg -------------------------------------------------------------------------------- /images/model-y-deep-blue-metallic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/model-y-deep-blue-metallic.jpg -------------------------------------------------------------------------------- /images/model-y-interior-dark.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/model-y-interior-dark.jpg -------------------------------------------------------------------------------- /images/model-y-interior-light.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/model-y-interior-light.jpg -------------------------------------------------------------------------------- /images/model-y-pearl-white-performance.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/model-y-pearl-white-performance.jpg -------------------------------------------------------------------------------- /images/model-y-pearl-white.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/model-y-pearl-white.jpg -------------------------------------------------------------------------------- /images/model-y-quicksilver-performance.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/model-y-quicksilver-performance.jpg -------------------------------------------------------------------------------- /images/model-y-quicksilver.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/model-y-quicksilver.jpg -------------------------------------------------------------------------------- /images/model-y-solid-black-performance.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/model-y-solid-black-performance.jpg -------------------------------------------------------------------------------- /images/model-y-solid-black.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/model-y-solid-black.jpg -------------------------------------------------------------------------------- /images/model-y-stealth-grey-performance.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/model-y-stealth-grey-performance.jpg -------------------------------------------------------------------------------- /images/model-y-stealth-grey.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/model-y-stealth-grey.jpg -------------------------------------------------------------------------------- /images/model-y-ultra-red-performance.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/model-y-ultra-red-performance.jpg -------------------------------------------------------------------------------- /images/model-y-ultra-red.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/model-y-ultra-red.jpg -------------------------------------------------------------------------------- /images/screen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/tesla-configurator-vanilla-js/29b05b57f6e5a2961bdffa3a245fedabed256a33/images/screen.jpg -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 13 | 14 | 15 | Design Your Tesla Model Y 16 | 17 | 18 | 19 |
20 |

21 | 0% APR available for qualified buyers 22 |

23 |
24 | 25 | 26 |
27 | Tesla 28 | 31 |
32 | 33 |
34 | 35 |
36 |
37 | 38 |
41 | Model Y 47 |
48 | 49 | 50 |
53 | Model Y Interior 59 |
60 |
61 |
62 | 63 | 64 | 241 |
242 | 243 | 244 | 245 | 246 | -------------------------------------------------------------------------------- /js/main.js: -------------------------------------------------------------------------------- 1 | const topBar = document.querySelector('#top-bar'); 2 | const exteriorColorSection = document.querySelector('#exterior-buttons'); 3 | const interiorColorSection = document.querySelector('#interior-buttons'); 4 | const exteriorImage = document.querySelector('#exterior-image'); 5 | const interiorImage = document.querySelector('#interior-image'); 6 | const wheelButtonsSection = document.querySelector('#wheel-buttons'); 7 | const performanceBtn = document.querySelector('#performance-btn'); 8 | const totalPriceElement = document.querySelector('#total-price'); 9 | const fullSelfDrivingCheckbox = document.querySelector( 10 | '#full-self-driving-checkbox' 11 | ); 12 | const accessoryCheckboxes = document.querySelectorAll( 13 | '.accessory-form-checkbox' 14 | ); 15 | const downPaymentElement = document.querySelector('#down-payment'); 16 | const monthlyPaymentElement = document.querySelector('#monthly-payment'); 17 | 18 | const basePrice = 52490; 19 | let currentPrice = basePrice; 20 | 21 | let selectedColor = 'Stealth Grey'; 22 | const selectedOptions = { 23 | 'Performance Wheels': false, 24 | 'Performance Package': false, 25 | 'Full Self-Drving': false, 26 | }; 27 | 28 | const pricing = { 29 | 'Performance Wheels': 2500, 30 | 'Performance Package': 5000, 31 | 'Full Self-Driving': 8500, 32 | Accessories: { 33 | 'Center Console Trays': 35, 34 | Sunshade: 105, 35 | 'All-Weather Interior Liners': 225, 36 | }, 37 | }; 38 | 39 | // Update total price in the UI 40 | const updateTotalPrice = () => { 41 | // Reset the current price to base price 42 | currentPrice = basePrice; 43 | 44 | // Performance Wheel Option 45 | if (selectedOptions['Performance Wheels']) { 46 | currentPrice += pricing['Performance Wheels']; 47 | } 48 | 49 | // Performance Package Option 50 | if (selectedOptions['Performance Package']) { 51 | currentPrice += pricing['Performance Package']; 52 | } 53 | 54 | // Full Self Driving Option 55 | if (selectedOptions['Full Self-Driving']) { 56 | currentPrice += pricing['Full Self-Driving']; 57 | } 58 | 59 | // Accessory Checkboxes 60 | accessoryCheckboxes.forEach((checkbox) => { 61 | // Extract the accessory label 62 | const accessoryLabel = checkbox 63 | .closest('label') 64 | .querySelector('span') 65 | .textContent.trim(); 66 | 67 | const accessoryPrice = pricing['Accessories'][accessoryLabel]; 68 | 69 | // Add to current price if accessory is selected 70 | if (checkbox.checked) { 71 | currentPrice += accessoryPrice; 72 | } 73 | }); 74 | 75 | // Update the total price in UI 76 | totalPriceElement.textContent = `$${currentPrice.toLocaleString()}`; 77 | 78 | updatePaymentBreakdown(); 79 | }; 80 | 81 | // Update payment breakdown based on current price 82 | const updatePaymentBreakdown = () => { 83 | // Calculate down payment 84 | const downPayment = currentPrice * 0.1; 85 | downPaymentElement.textContent = `$${downPayment.toLocaleString()}`; 86 | 87 | // Calculate loan details (assuming 60-month loan and 3% interest rate) 88 | const loanTermMonths = 60; 89 | const interestRate = 0.03; 90 | 91 | const loanAmount = currentPrice - downPayment; 92 | 93 | // Monthly payment formula: P * (r(1+r)^n) / ((1+r)^n - 1) 94 | const monthlyInterestRate = interestRate / 12; 95 | 96 | const monthlyPayment = 97 | (loanAmount * 98 | (monthlyInterestRate * 99 | Math.pow(1 + monthlyInterestRate, loanTermMonths))) / 100 | (Math.pow(1 + monthlyInterestRate, loanTermMonths) - 1); 101 | 102 | monthlyPaymentElement.textContent = `$${monthlyPayment 103 | .toFixed(2) 104 | .toLocaleString()}`; 105 | }; 106 | 107 | // Handle Top Bar On Scroll 108 | const handleScroll = () => { 109 | const atTop = window.scrollY === 0; 110 | topBar.classList.toggle('visible-bar', atTop); 111 | topBar.classList.toggle('hidden-bar', !atTop); 112 | }; 113 | 114 | // Image Mapping 115 | const exteriorImages = { 116 | 'Stealth Grey': './images/model-y-stealth-grey.jpg', 117 | 'Pearl White': './images/model-y-pearl-white.jpg', 118 | 'Deep Blue': './images/model-y-deep-blue-metallic.jpg', 119 | 'Solid Black': './images/model-y-solid-black.jpg', 120 | 'Ultra Red': './images/model-y-ultra-red.jpg', 121 | Quicksilver: './images/model-y-quicksilver.jpg', 122 | }; 123 | 124 | const interiorImages = { 125 | Dark: './images/model-y-interior-dark.jpg', 126 | Light: './images/model-y-interior-light.jpg', 127 | }; 128 | 129 | // Handle Color Selection 130 | const handleColorButtonClick = (event) => { 131 | let button; 132 | 133 | if (event.target.tagName === 'IMG') { 134 | button = event.target.closest('button'); 135 | } else if (event.target.tagName === 'BUTTON') { 136 | button = event.target; 137 | } 138 | 139 | if (button) { 140 | const buttons = event.currentTarget.querySelectorAll('button'); 141 | buttons.forEach((btn) => btn.classList.remove('btn-selected')); 142 | button.classList.add('btn-selected'); 143 | 144 | // Change exterior image 145 | if (event.currentTarget === exteriorColorSection) { 146 | selectedColor = button.querySelector('img').alt; 147 | updateExteriorImage(); 148 | } 149 | 150 | // Change interior image 151 | if (event.currentTarget === interiorColorSection) { 152 | const color = button.querySelector('img').alt; 153 | interiorImage.src = interiorImages[color]; 154 | } 155 | } 156 | }; 157 | 158 | // Update exterior image based on color and wheels 159 | const updateExteriorImage = () => { 160 | const performanceSuffix = selectedOptions['Performance Wheels'] 161 | ? '-performance' 162 | : ''; 163 | const colorKey = 164 | selectedColor in exteriorImages ? selectedColor : 'Stealth Grey'; 165 | exteriorImage.src = exteriorImages[colorKey].replace( 166 | '.jpg', 167 | `${performanceSuffix}.jpg` 168 | ); 169 | }; 170 | 171 | // Wheel Selection 172 | const handleWheelButtonClick = (event) => { 173 | if (event.target.tagName === 'BUTTON') { 174 | const buttons = document.querySelectorAll('#wheel-buttons button'); 175 | buttons.forEach((btn) => btn.classList.remove('bg-gray-700', 'text-white')); 176 | 177 | // Add selected styles to clicked button 178 | event.target.classList.add('bg-gray-700', 'text-white'); 179 | 180 | selectedOptions['Performance Wheels'] = 181 | event.target.textContent.includes('Performance'); 182 | 183 | updateExteriorImage(); 184 | 185 | updateTotalPrice(); 186 | } 187 | }; 188 | 189 | // Performance Package Selection 190 | const handlePerformanceButtonClick = () => { 191 | const isSelected = performanceBtn.classList.toggle('bg-gray-700'); 192 | performanceBtn.classList.toggle('text-white'); 193 | 194 | // Update selected options 195 | selectedOptions['Performance Package'] = isSelected; 196 | 197 | updateTotalPrice(); 198 | }; 199 | 200 | // Full Self Driving Selection 201 | const fullSelfDrivingChange = () => { 202 | selectedOptions['Full Self-Driving'] = fullSelfDrivingCheckbox.checked; 203 | updateTotalPrice(); 204 | }; 205 | 206 | // Handle Accessory Checkbox Listeners 207 | accessoryCheckboxes.forEach((checkbox) => { 208 | checkbox.addEventListener('change', () => updateTotalPrice()); 209 | }); 210 | 211 | // Initial Update Total Price 212 | updateTotalPrice(); 213 | 214 | // Event Listeners 215 | window.addEventListener('scroll', () => requestAnimationFrame(handleScroll)); 216 | exteriorColorSection.addEventListener('click', handleColorButtonClick); 217 | interiorColorSection.addEventListener('click', handleColorButtonClick); 218 | wheelButtonsSection.addEventListener('click', handleWheelButtonClick); 219 | performanceBtn.addEventListener('click', handlePerformanceButtonClick); 220 | fullSelfDrivingCheckbox.addEventListener('change', fullSelfDrivingChange); 221 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Tesla Car Configurator UI (Vanilla JS) 2 | 3 | UI to customize a Tesla Model Y. Change the exterior, interior and wheels. Add different options and get pricing. 4 | 5 | 6 | --------------------------------------------------------------------------------