Skip to content

edpau/fm_tip-calculator-app

Repository files navigation

Frontend Mentor - Tip calculator app solution

This is a solution to the Tip calculator app challenge on Frontend Mentor. Frontend Mentor challenges help you improve your coding skills by building realistic projects.

Table of contents

Overview

The challenge

Users should be able to:

  • View the optimal layout for the app depending on their device's screen size
  • See hover states for all interactive elements on the page
  • Calculate the correct tip and total cost of the bill per person

Screenshot

Screenshot

Links

My process

Built with

  • Semantic HTML5 markup
  • CSS custom properties
  • Flexbox
  • CSS Grid
  • Mobile-first workflow
  • React - JS library
  • Next.js - React framework
  • Styled Components - For styles

Note: These are just examples. Delete this note and replace the list above with your own choices

What I learned

form

  • <form action="#" novalidate> This ensures that the form does not submit anywhere and does not perform any validation.

  • The

    element is a convenient way to create groups of widgets that share the same purpose, for styling and semantic purposes. You can label a by including a element just below the opening tag.

  • The HTML element is a container element into which a site or app can inject the results of a calculation or the outcome of a user action.

Get form data using FormData()

const form = document.querySelector(".tip-calculator") as HTMLFormElement;

const formData = new FormData(form);
const data = Object.fromEntries(formData);

// {billAmount: '', tip-percentage: '5', numberOfPeople: ''}

Radio Button, hide radio button and only show button label

  • I tried to hide the radio button, while I am using grid for my layout, display: none on the .select-tip__radio[type="radio"] seems to work, but lost the accessibility, so below is better
.select-tip__radio[type="radio"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

Radio Button label, checked color

  • When changing checked color of the label, need to select checked on the radio button
input[type="radio"]:checked + label {
  background-color: var(--color-button-tip-selected);
  color: var(--color-button-tip-text-selected);
}

How to make custom radio input custom %

  • I put a input below the radio button label in the sane div, and put it to disabled and use CSS to set pointer-events: none. So user can select the custom radio label just as the other.
<div class="select-tip__custom-container">
  <input
    class="select-tip__radio select-tip__radio--custom"
    type="radio"
    id="tip-percentage-custom"
    name="tip-percentage"
    value="0"
  />
  <label
    class="select-tip__radio-label select-tip__radio-label--custom"
    for="tip-percentage-custom"
  >
  </label>
  <input
    type="number"
    class="select-tip__radio-custom-input"
    name="tip-percentage-custom-input"
    placeholder="Custom"
    min="0"
    autocomplete="off"
    disabled
  />
</div>
  • When the user selected the custom radio label I use JS to set the input disabled = false, set pointer-events: auto and focus on the input.
if (target.id === "tip-percentage-custom") {
  customInput.disabled = false;
  customInput.style.pointerEvents = "auto";
  customInput.focus();
} else {
  customInput.disabled = true;
  customInput.style.pointerEvents = "none";
  customInput.value = "";
}

TS

Record<K, T> utility type
  • In TypeScript, the Record<K, T> utility type is used to define an object type with a set of keys K and a set of values T. It essentially represents an object where every key has a specific value type.

Round number to 2 decimal place

  • How to round to at most 2 decimal places, if necessary

  • toFixed() will also not round correctly in some cases, also it return a string.

    parseFloat("1.555").toFixed(2); // Returns 1.55 instead of 1.56.
    parseFloat("1.5550").toFixed(2); // Returns 1.55 instead of 1.56.
    // However, it will return correct result if you round 1.5551.
    parseFloat("1.5551").toFixed(2); // Returns 1.56 as expected.
  • JavaScript round a number to 2 decimal places

  • using the Math.round() function, problem it will not leave 2 decimal place.

var a = 5.678948;
let b = 10.257683;
let c = 6.6456583;
let result1 = Math.round(a * 100) / 100;
let result2 = Math.round(b * 10) / 10;
let result3 = Math.round(x * 1000) / 1000;
console.log(result1); // 5.68
console.log(result2); // 10.3
console.log(typeof result2); // 6.646

Reminder

  • use aria-live="polite" for displaying error

Continued development

  • improve the accessibility on the screen reader reading the Tip Amount per person and the result.

Useful resources

From

Styling Radio Buttons

-how to create a custom Input radio button which have attributes inside it - show me basic, how to style an input

Style input

JS

HTML DOM Events

Design system

Author

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published