Latest solutions
Password Generator App with Added Accessibility (Typescript/Vite)
#accessibility#vite#typescriptSubmitted about 2 years ago
Latest comments
- @astr0n0merSubmitted about 2 years ago@joshdailPosted about 2 years ago
Really nice job on this project. I also used absolute for getting the pop-up to work. It looks like your solution scales properly when the screen size changes, so I don't see any problem with it being absolutely positioned since it works and displays correctly.
As far as whether to use h1 or img tag, I think that using an img tag, like you did, is better since an h1 tag is meant to be used for actual text. And you have the alt text for the image, so that takes care of the accessibility for the image. On a full website or app you would probably have an h1 somewhere else on the screen, but since this project is just a component I wouldn't worry about the h1 warning.
Also really nice job making the buttons focusable and keyboard accessible!
Marked as helpful0 - @kxnzxSubmitted over 2 years ago@joshdailPosted over 2 years ago
I would suggest having the code for the error message in a separate function outside of your calculateAndDisplayValues function. That way calculateAndDisplayValues is focused just on the math, and you have another function focused just on the error message.
So you could pull your error handling code outside of calculateAndDisplayValues and put it inside an event listener, something like this:
document.getElementById("people").addEventListener("click",() => { let people = document.getElementById("people").value; // Convert the number of people to a number: /* If you want to treat the value as a number, you can use the parseInt() or parseFloat() functions to convert it to a number. */ people = parseInt(people, 10); // Check if the number of people is a valid number: if (isNaN(people) || people <= 0) { // Display an error message if the value is not valid: document.getElementById("error").innerHTML = "Can't be zero"; document.getElementById("people").classList.add("invalid"); return; } else { document.getElementById("error").innerHTML = ""; document.getElementById("people").classList.remove("invalid"); } })
Then in calculateAndDisplayValues, you would still need to make sure that there is a valid input for number of people so you don't get NaN or divide by zero errors. You could have a line of code that checks to make sure there is a valid value before the function does the math, like this:
if (people <= 0 || isNaN(people) { return; } let tipAmountPerPerson = (billAmount * tipPercentage) / 100 / people;
Since the error message is taken care of by a separate function, you don't have to worry about it here in calculateAndDisplayValues. Here you're just concerned with making sure the math part of it works.
I hope this is helpful.
Marked as helpful0 - @kxnzxSubmitted over 2 years ago@joshdailPosted over 2 years ago
Nice job!
Looking at your solution, your form is not far off from working the way you want, just needs a few small tweaks to the code.
For the error message: What you could do is have the HTML start off as an empty tag, with no text, like this:
<small id="error" class="error"></small>
and then have the event listener in your JS script add the error message to the element's innerText only if the error condition is met. Same with the red outline, you can have a CSS class, for example like this:
.input.invalid { border: none; outline: 2px solid hsl(9, 31%, 58%); }
And in your event listener, when you add in the error text, you can use <element>.classList.add (or remove) to add/remove the red background, like this:
peopleInput.addEventListener("input", e => { const inputValue = peopleInput.value const peopleCount = Number(inputValue) if (peopleCount === 0 && peopleInput.value !== "") { peopleInput.classList.add(classInvalid) peopleErrorAlert.innerText = "Can't be zero" return } /* If no error make sure error message is not displayed */ peopleInput.classList.remove(classInvalid) peopleErrorAlert.innerText = "" })
For getting rid of "0", just set the value of the inputs to "" instead of "0" when the reset button is clicked. If you want it to show 0 as a placeholder, you could set the placeholder to 0 instead of the value, then the 0 will disappear as soon as a value is entered.
Marked as helpful0 - @SlavenaDuhnevaSubmitted over 2 years ago@joshdailPosted over 2 years ago
Nice job!
From what I can tell, your project is fine as far as appearing correctly on desktop and mobile. One good thing is that you are using rem for font sizes and not pixels. That can be important also for accessibility. Also, I see you are using CSS custom properties which are very helpful for responsive design.
As far as responsive design for desktop/tablet/mobile, I generally will use media queries for different screen sizes. So I might have @media (width < some_width) for mobile, then another for tablet size, and so on. I will use Chrome or Firefox Devtools to see where the app starts to break or look incorrect at a certain width, and use that as a basis for where to switch from desktop to tablet or mobile.
Using Flexbox and Grid for your page layouts is also great for responsiveness, since for Flexbox you can change rows to columns as the screen shrinks, and with Grid you can change the rows and columns as needed to fit different sizes.
Kevin Powell has a great Youtube channel and also a free course on responsive design on his website https://www.kevinpowell.co, you may find that helpful
Marked as helpful0 - @s9trangeSubmitted over 2 years ago@joshdailPosted over 2 years ago
Here are a few things I've found helpful:
Try to avoid setting definite widths when you can. I will usually set a width of 100% and then a max-width, like this:
.section-menu { width: 100%; max-width: 22em; }
That way, the element won't go wider than what you want, but it can also shrink with the page.
Also, if you're using Flexbox for your main page sections, then when the width goes down, you can switch the flex-direction from row to column and make any other changes in the flex layout. So for example here, when the width drops, the sections shift from being in a row to stacking on top of one another, being centered, and being the same width:
@media (width < 900px) and (orientation: portrait) { .container { flex-direction: column; align-items: center; padding-inline: 2em; } .section-menu, .section-meter { max-width: 22em; } }
I had to write a lot of media queries for this project. What I found helpful was using the Chrome and Firefox dev tools, and trying out different screen sizes to see where the components started to break. Then I would write a media query to fix the problem. So I have one @media (width < 900px) with some rules, then another @media (width < 420px) with more rules, and so on. Just a lot of trial and error and experimenting until it looks the way you want it to.
0 - @amerrikaSubmitted over 2 years ago@joshdailPosted over 2 years ago
Nice job!
It is possible to restrict the input fields. I also had a really hard time finding info online on how to do that. I used a combination of regular expressions and JS string methods and it seems to work.
Here are the regex I used :
const regexNumeralsDecimalsOnly = /[^0-9.]/g const regexNumeralsOnly = /[^0-9]/g
I couldn't figure out how to control the number of decimal places with regex, so after filtering with the regex I used string methods to filter down to only one decimal point and two decimal places. Then it immediately rewrites the value in the input field with the filtered value.
// First, filter the input value with regex, and escape out any invalid characters const filteredInput = billInput.value.replace(regexNumeralsDecimalsOnly, "") /* Force the input value to one decimal point and two decimal places at most The ternary expression looks for a decimal. If it finds one, it slices the string The first substring is the part before and including the decimal. The second part is after the decimal. Any additional decimals in the second substring are escaped out, and the length is limited to 2 characters */ const inputValue = filteredInput.indexOf(".") >= 0 ? filteredInput.substr(0, filteredInput.indexOf(".") + 1) + filteredInput.substr(filteredInput.indexOf(".") + 1, 2).replace(".", "") : filteredInput // Immediately the value in the input field with the filtered value, // preventing any invalid values from being entered billInput.value = inputValue
Regexr.com is a good place to test out and learn about regex. Regex seems to be one of the best ways to filter input to what you want it to be.
0