learn react ui logoLearnReactUI
Lets Develop A Simple Calculator

Lets Develop A Simple Calculator

Last Updated Date: 26.10.2023 Version: 1.0.0 Author: Onur Dayibasi

Introduction

Developing a Calculator may appear to some of you to be a very basic project, but following the development of this example will allow you to adapt to React in a short time as you touch on many themes.

Source Code The source code for the app is available by downloading the content.

Demos You can access this knowledgemap from the You can access this knowledgemap from the link

1. Analysis

Using the calculator on my closest Macbook running MacOS, I will describe this training. The same reasoning can be used whether you take a physical calculator or one that you can find nearby.

Let's select the program that shows up when we type Calculator into the MacBook's search box.

Untitled

When we launch the Calculator program, we get presented by the application shown below.

Untitled

On the application's main screen

  • The screen that displays the number you typed
  • There are also buttons. These buttons have several purposes.
    • Counting from 0 to 9.
    • There are buttons for AC and C. AC clears entire memory, whereas C merely clears the screen. -, enables you to generate decimal numbers.
    • When you type % after a number, it divides it by 100.
    • Pressing the +/- buttons changes the matching number from negative to positive.
    • With the yellow buttons, you can add, subtract, multiply, divide, and compute.

1.1 Disassemble

First and foremost, disassemble the calculator as shown.

Untitled

We're breaking down the UI as a major process here. This is due to the fact that we are using the Component Driven UI Development technique. We need to separate the Atoms of the application and component we will design, as Brad Frost discusses in his book Atomic Design.

1.2 Identifying Parts

We actually have two parts. The display (Screen) is one, and the buttons that accept user inputs (Button) are the other.

Here we will connect 2 types of components

  • A Model that will hold the State
  • and we need a Controller to manage this Model.

Untitled

Our application will have four different component structures.

  • Screen: The component in charge of showing the numbers assigned to it.
  • Button: These are the components that will accept user interaction and send it to the Controller.
  • Model: The framework that stores the user interactions.
  • Controller: The component in charge of managing the application. In other words, the section that governs the business logic that will process the user's inputs and output the Model.

2. Mechanics (Code Without Styling)

2.1 Beginning of the Project

How can a basic calculator be created that functions within a browser? In these kinds of articles, my focus will be on UI mechanics rather than aesthetic appeal or design.

My first thinking while considering how to create a basic calculator was to use React Hooks and JS.

Untitled

My goal is to create a basic Calculator similar to the one shown above. To illustrate this concept in a straightforward manner, I will create a Calculator with as few visuals and functions as feasible.

First, I had to create an infrastructure. For this, let's create our infrastructure using Vite offered by React.

npm create vite@latest

Let's add the SimpleCalculator we will develop later into this App rendering.

Untitled

SimpleCalculator requires only the text "Simple Calculator" for the time being. This will be improved over time.

We may divide the code we will write into two pieces.

  • The component that contains the Calculator Mechanics and Model React code and shows it on the screen and responds to user commands.
  • The Math Part, as shown in the screenshot below, contains the Calculator Mechanics and model. The UI & Interaction Part generates the calculator's display and includes Function, Number, Command buttons, and Display.

The Math Part, as shown in the screenshot below, contains the Calculator Mechanics and model. The UI & Interaction Part generates the calculator's display and includes Function, Number, Command buttons, and Display.

Untitled

2.2 . Calculator Mechanics and the Model-Holding Part

In its most basic form, our calculator should do four operations. Addition, Subtraction, Division, and Multiplication must all be modeled. When we pass it an arr argument, it executes the required operation on it using the reducer.

2.2.1 Calculate Mechanism

Untitled

2.2.2 Input Manager

In our model that operates user inputs, reset, calc, push have an effect on result.

Untitled

Reset: It will assign the Result value to the empty string, so the corresponding Screen will print it as 0 when printing it to the screen.

**const** val = props.value === '' ? 0 : props.value;

Calculate: Suppose the user enters some operations on the screen, say 3+5 and then presses the = button, doCalculation is executed. Here we need to consider all cases. Let the user press the buttons in the following order.

Case1: [3,+,5,=], Case2:[=], Case3: [3=]

When the equals button is pressed, calc will look at the values pressed before it and if there is one of the previously written addition, subtraction and other 4 operations in this value, it will do the operation, otherwise it will return the same value.

//When User Clicks =
const calc = () => {
  const op = isOpExist();
  result = doCalculation(op);
  return result;
};

Push: handles the digit and 4 operation functions that we press. It adds the pressed values to the result. For example 34+332.

//When User Clicks Numbers/Functions
const push = (val) => {
  const op = isOpExist();
  if (op && opsMeta.includes(val)) {
    result = doCalculation(op);
  }
  result += val;
  return result;
};

Here, if the user presses 34+332 after these operations and then presses one of the 4 operation functions, it perceives it as if he pressed = before, and then does this operation first and then writes it to 366 + result.

Note: Here we are trying to find out which 4 operation Op is in Result, if it is not present, it returns false.

const isOpExist = () => {
  let flag = false;
  opsMeta.forEach((el) => {
    if (result.includes(el)) flag = el;
  });
  return flag;
};

2.2.3 Calculate Manager

We split the Result according to the op we find in Result and make the resulting arr related to the 4 processing functions 2.2.1 Calculate Mechanism.

const doCalculation = (op) => {
  if (op) {
    const arr = result.split(op);
    const arrInt = arr.map((el) => parseInt(el));
    switch (op) {
      case "+":
        return sum(arrInt) + "";
      case "-":
        return sub(arrInt) + "";
      case "*":
        return mul(arrInt) + "";
      case "/":
        return div(arrInt) + "";
      default:
        return "";
    }
  }
};

2.3 Calculator Display and User Interaction

The Calculator basically consists of 4 parts

Untitled

  • Screen
  • Function Buttons
  • Number Buttons
  • Command Buttons

Now we need Button and Screen components to make this happen in React.

const Button = (props) => {
  return <button onClick={props.onClickHandler}>{props.title}</button>;
};

const Screen = (props) => {
  const val = props.value === "" ? 0 : props.value;
  return <div>{val}</div>;
};

**2.3.1 How to Make Buttons**

I think it is more accurate to create their data models before creating buttons.

Operation Buttons

const opButtonsData = [
  { title: "+", val: "+" },
  { title: "-", val: "-" },
  { title: "*", val: "*" },
  { title: "/", val: "/" },
];

Number Model from 1 to 10

const numButtonsDataGen = (limit) => {
  const numArr = [];
  for (let i = 0; i < limit; i++) numArr.push({ title: `${i}`, val: i });
  return numArr;
};

const numButtonsData10 = numButtonsDataGen(10);

The above part created the Button Models. Reset and Calc will be created one by one. Now let's see how we create these buttons in the code. We convert them to Button JSX array by returning the button model array with map.

Untitled

Note: What is important in this section is that we bind onClickHandler which functions we will call when the buttons are pressed calc = so we tell our calculator to do the operation and return to us. We pass the returned result in setResult.

We define the result value on the screen as a state with Hook. It is important that we use this because React components will call the component rendering again in State, Props changes. You must ensure that this state change occurs for the screen to refresh.

const [result, setResult] = useState("");

**2.3.2 Rendering**

To render the entire Calculator to the screen, just render the screen component with all buttons in return.

Untitled

3. Styling

The macOS calculator has a lovely look.

Untitled

3.1 Layout

Untitled

3.1.1 Split Layout into Parts

Untitled

3.1.2 Divide Layout into Parts and Color it

Untitled

3.1.3 Let's Set Coloring and Font Size

Untitled

3.2**. Apply Styling**

3.2.1 Create Layout

Untitled

3.2.2 Create Screen and Button Layout

Untitled

3.2.3 Create Table and Row for Button Layout

Untitled

3.2.4 Create Button Layout Cells

Untitled

3.4.5 Put Buttons in Button Layout

Untitled

3.4.6 Let's Adjust the Size in Button Layout

Untitled

3.4.7 Let's Color the Buttons and Background

Untitled

3.4.8 Adjust Coloring, Font Size and Border-Radious

Untitled

4. Responsive

We have done the styling of the simple calculator. Now we will try to make it responsive for different platforms.

Demo: https://onurdayibasi.dev/device-layouts

Responsive: When we enter your web page or application from different devices, your application is shaped according to the screen conditions by differentiating your application according to the changing screen sizes.

Untitled

So what do you mean by different, different platforms? On this subject, the CSS-Tricks page "Media Queries for Standard Devices" has done Viewport analysis for 99 different devices and from this analysis you can see that there are devices of very different sizes, pixel ratios and that users can use these devices (mobile devices) in Landscape and Portrait (horizontal and vertical).

Untitled

Of course, if the number of these devices is more than 100, it will lead us to a situation where it is not possible to handle them one by one. Taking them one by one will both make our application very fragile and cause us to keep too many parametric values related to Styling.

Instead, it is useful to try to focus on general styling structures that will work in certain width and height ranges. As you can see from the min-width ranges below, you can define different styles, lengths and sizes of the UI according to the variables in these ranges.

@media (min-width:320px)  {
/* smartphones, iPhone, portrait 480x320 phones */ }

@media (min-width:481px)  { /* portrait e-readers (Nook/Kindle), smaller tablets @ 600 or @ 640 wide. */ }

@media (min-width:641px)  { /* portrait tablets, portrait iPad, landscape e-readers, landscape 800x480 or 854x480 phones */ }

@media (min-width:961px)  { /* tablet, landscape iPad, lo-res laptops ands desktops */ }

@media (min-width:1025px) { /* big landscape tablets, laptops, and desktops */ }

@media (min-width:1281px) { /* hi-res laptops and desktops */ }

Hesap Makinesine geri döndüğümüzde hem hesap makinesi genişlik ve uzunluk, ve font-size değişen media-query göre parametrik ve dinamik hale getirdim.

Untitled

Bu sayede hesap makinesi belli aralıklarda belli büyüklükte olacak şekilde tasarımımı gerçekleştiriyorum.

4.1 Is Full Dynamic?

If you say that you will not use media query to make it fully dynamic, then instead of giving fixed pixels to the unit part, defining it through the vw viewport unit will make the whole page dynamic according to the screen size.

unit:10px  -> unit: 1vw

4.2 Layout

I want the structure to be sorted in 2 types of Layout in the Calculator display example.

  • On wide screens, the demo screen and the description part should stand side by side.
  • On narrow screens, the demo screen and the description should be stacked one below the other.

Untitled

Since I used FlexLayout in the example, it was enough to change flex-direction. Or if we were using Grid system, we could change the number of columns.

Untitled

Note: An important issue here is that since you are working with preprocessors such as SCSS, LESS, it would be wrong to expect scss to do your media-query structures with $unit. Because these structures are compiled on the server side and created statically for you. In other words, SCSS Client Side cannot create a dynamic structure because it does not work on the browser, for this you need to use CSS Variables - unit etc..