Responsive Time-Tracking Dashboard With KendoReact
Published: 2022-04-19 10:32:53

[KendoReact]([https://www.telerik.com/kendo-react-ui/](https://www.telerik.com/kendo-react-ui/?utm_medium=referral&utm_source=dev.to&utm_campaign=responsive-time-tracking-dashboard-kendoreact)) is an excellent library for quickly creating a user interface with React. Still, the question is, how exactly does KendoReact help a developer? It helps save time when building powerful, polished and swift UI for apps. It also ensures consistency in the look and feel of the UI.

KendoReact is a React UI library that ships more than 100 ready-to-use components, ranging from complex ones such as a data grid, scheduler and rich text editor all the way to buttons and checkboxes. It also has features that go beyond that and improve designer-developer collaboration, for example, their [Figma Design kits](https://www.telerik.com/kendo-react-ui/figma-design-kits/?utm_medium=referral&utm_source=dev.to&utm_campaign=responsive-time-tracking-dashboard-kendoreact). In this post, we will be building a responsive time-tracking dashboard its rich [React Layout Library](https://www.telerik.com/kendo-react-ui/components/layout/?utm_medium=referral&utm_source=dev.to&utm_campaign=responsive-time-tracking-dashboard-kendoreact).

## Prerequisites

To follow along with this tutorial, you will need to have:

- React v16 or newer
- A basic understanding of React
- A text editor

## Getting Started

If you are already familiar with scaffolding a React app using **npx**, skip this part of the post, but for those who aren't, follow the steps below to get your React app development server running on your local machine. Enter the following command into your terminal to quickly set up a React project.

```SHELL
    npx create-react-app kendo-ui-demo --use-npm
    cd kendo-ui-demo
    npm start
```

If you use yarn, use the following command:

```SHELL
    yarn create react-app kendo-ui-demo
    cd kendo-ui-demo
    yarn start
```

Now let's begin by stripping down the code in the App.js file to look like this.

```JS
    Import "./App.css"
    
    function App () {
      return <div className="App"></div>;
    }
    
    export default App;
```

Next, let's add the KendoReact packages we'll be using for this project. I will use the [KendoReact Default theme](https://www.telerik.com/kendo-react-ui/components/styling/theme-default/) for this project, but others options exist—for example, the [KendoReact Bootstrap](https://www.telerik.com/kendo-react-ui/components/styling/theme-bootstrap/) and the [KendoReact Material theme](https://www.telerik.com/kendo-react-ui/components/styling/theme-material/).

> **Note:** KendoReact is a commercial UI component library, and as a part of this you will need to provide a license key when you use the components in your React projects. You can snag a license key through a free trial or by owning a commercial license. For more information, you can head over to the [KendoReact Licensing page](https://www.telerik.com/kendo-react-ui/my-license/).

Let's install the KendoReact Default theme by running the following commands in your terminal.

```SHELL
    npm install --save @progress/kendo-theme-default
```

The `--save` command shown above indicates that this package should be a production dependency and not a development dependency; for dev dependency use  `--save-dev`.

If you use yarn, use the following command:

```SHELL
    yarn add @progress/kendo-theme-default
```

In the above commands, you will notice @progress precedes the default theme; this means that KendoReact is distributed as multiple npm packages, scoped to @progress. Therefore we will see this a lot when installing other packages from KendoReact. Now, let's import the CSS file from the package in `src/App.js`.

**Note:** Add this import before your existing `App.css` import:

```JS
    import '@progress/kendo-theme-default/dist/all.css';
```

The KendoReact UI components are designed so that they are not tightly coupled to a specific theme. You might be thinking, why do you need to include one of these three themes or your custom theme? Well, this allows you to change the look and feel of the application by modifying a Sass or CSS file or even swapping themes for your entire application by changing a single import.

If needed, any additional custom styles can go in the empty src/App.css file.

## Integrating Multiple KendoReact Components

KendoReact is a rich suite of many modular components. As mentioned earlier, in this demonstration, we will use multiple components imported from KendoReact to build a responsive time-tracking dashboard application. Before we begin, let’s install and import the [`React Layout`Library](https://www.npmjs.com/package/@progress/kendo-react-layout) package and its dependencies.

```SHELL
    npm install --save @progress/kendo-react-layout @progress/kendo-react-progressbars @progress/kendo-licensing @progress/kendo-react-intl
```

With that done, it's time to import the package into the project. Add the following code in the App.js file:

```JS
    import { Card, GridLayout, GridLayoutItem } from "@progress/kendo-react-layout";
```

The image below shows a finished copy of the project demo we will be building.

![](https://paper-attachments.dropbox.com/s_58D1EFB299078D3655326CFF9A64417B84D9E86ACEDB12856BD0266250A9AEF6_1636060553095_psq1SrWX.jpeg)

Let's start by creating a `data.json` file in the `src` folder and populate it with the static data we will be using for this demo; this eliminates the need for a server or an external API.

```SHELL
    touch data.json
```

```JS
    [
     {
      "id": 1,
      "on": "Work",
      "time": "32hrs",
      "lastWeek": "36hrs",
      "layoutColor": "hsl(15, 100%, 70%)",
      "row": "1",
      "col": "2"
     },
     {
      "id": 2,
      "on": "Play",
      "time": "10hrs",
      "lastWeek": "8hrs",
      "layoutColor": "hsl(195, 74%, 62%)",
      "row": "1",
      "col": "3"
     },
     {
      "id": 3,
      "on": "Study",
      "time": "4hrs",
      "lastWeek": "7hrs",
      "layoutColor": "hsl(348, 100%, 68%)",
      "row": "1",
      "col": "4"
     },
     {
      "id": 4,
      "on": "Exercise",
      "time": "4hrs",
      "lastWeek": "5hrs",
      "layoutColor": "hsl(145, 58%, 55%)",
      "row": "2",
      "col": "2"
     },
     {
      "id": 5,
      "on": "Social",
      "time": "5hrs",
      "lastWeek": "10hrs",
      "layoutColor": "hsl(264, 64%, 52%)",
      "row": "2",
      "col": "3"
     },
     {
      "id": 6,
      "on": "Self Care",
      "time": "2hrs",
      "lastWeek": "2hrs",
      "layoutColor": "hsl(43, 84%, 65%)",
      "row": "2",
      "col": "4"
     }
    ]
```

Now, let's import the data into the `App.js` file using the following command below:

```JS
    import Data from "./data.json";
```

Now that we are done creating and importing our `data.json` file, let’s start development.

In the `App.js` file, let’s create a function `App` and use it as our default export. After you’ve done that, you should have something that looks like this in your code editor.

```JS
    import { Card, GridLayout, GridLayoutItem } from "@progress/kendo-react-layout";
    import Data from "./data.json";
    import "@progress/kendo-theme-default/dist/all.css";
    import "./App.css";
    
    function App(){
    ...
    };
    export default App;
```

Now, paste the following code into the function `App`.

```JS
     let paddingScreen = 20;
     if (window.innerWidth < 600) {
      let col = 0;
      let row = 3;
      paddingScreen = 5;
      Data.map((item) => {
       if (col > 1) {
        col = 1;
        row = row + 1;
       } else {
        col = col + 1;
       }
       item.col = col;
       item.row = row;
      });
     }
     return (
      <div
       style={{
        height: "100%",
        width: "100%",
        paddingBottom: "3em",
        backgroundColor: "hsl(226, 43%, 10%)",
       }}
      >
       <GridLayout
        gap={{
         rows: 175,
         cols: 30,
        }}
        rows={[
         {
          height: 50,
         },
         {
          height: 50,
         },
         {
          height: 50,
         },
         {
          height: 50,
         },
        ]}
        cols={[
         {
          width: 200,
         },
         {
          width: 200,
         },
         {
          width: 200,
         },
         {
          width: 200,
         },
        ]}
        style={{ padding: `10% 0 0 ${paddingScreen}%` }}
       >
        <GridLayoutItem
         row={1}
         col={1}
         rowSpan={2}
         style={{ marginBottom: "20em" }}
        >
         <Card style={{ backgroundColor: "rgba(0,0,0,0)", border: "none" }}>
          <div
           style={{
            backgroundColor: "hsl(235, 46%, 20%)",
            borderRadius: 10,
           }}
          >
           <div
            style={{
             borderRadius: 10,
             padding: "1em 1em 3em 1.7em",
             backgroundColor: "hsl(246, 80%, 60%)",
            }}
           >
            <img
             src={`${process.env.PUBLIC_URL}/WhatsApp Image 2021-10-31 at 12.18.47 AM.jpeg`}
             style={{
              width: 65,
              height: 65,
              objectFit: "cover",
              borderRadius: 60,
              border: "2px solid white",
             }}
            />
            <p style={{ color: "white", marginBottom: "-1.3em" }}>
             Report for
            </p>
            <h1
             style={{
              color: "white",
              fontSize: "2rem",
              fontWeight: 400,
             }}
            >
             Fatima Usman
            </h1>
           </div>
           <div className="dwm">
            <p>Daily</p>
            <p>Weekly</p>
            <p>Monthly</p>
           </div>
          </div>
         </Card>
        </GridLayoutItem>
        {Data.map((item) => {
         const { id, on, time, lastWeek, layoutColor, row, col } = item;
         return (
          <GridLayoutItem row={row} col={col} colSpan={1} rowSpan={1} id={id}>
           <Card
            style={{
             border: "none",
             borderRadius: 10,
             backgroundColor: "rgba(0,0,0,0)",
            }}
           >
            <div
             style={{
              backgroundColor: layoutColor,
              height: 50,
              borderRadius: 0,
             }}
            ></div>
            <div className="ttc">
             <p>{on}</p>
             <h1>{time}</h1>
             <p>Last Week - {lastWeek}</p>
            </div>
           </Card>
          </GridLayoutItem>
         );
        })}
       </GridLayout>
      </div>
     );
```

The [React GridLayout component]([https://www.telerik.com/kendo-react-ui/components/layout/gridlayout/](https://www.telerik.com/kendo-react-ui/components/layout/gridlayout/)) imported from `@progress/kendo-react-layout` acts as a wrapper for `GridLayoutItem`, while `GridLayoutItem` is a container for the data we wish to display. Here's a visual aid to help you understand that statement.

![](https://paper-attachments.dropbox.com/s_58D1EFB299078D3655326CFF9A64417B84D9E86ACEDB12856BD0266250A9AEF6_1636060657115_FTsawDR3.jpeg)

In the code above, you will see gap, rows and cols passed in as props in the GridLayout. The GridLayout defines the number of rows and cols that will span across that entire section. The `gap` prop defines the gap between the rows and col. Therefore, the GridLayout defines the grid system while GridLayoutItem follows this grid system in allocating the number for its row, col, rowspan and colspan for each item. (rowspan and colspan define how many rows and cols a particular GridLayoutItem should occupy.)

The [React Card component]([https://www.telerik.com/kendo-react-ui/card/](https://www.telerik.com/kendo-react-ui/card/)) acts as a div wrapper for our items in the cards. There's nothing unusual about the Card component, but I think it is still nice because sometimes you won't have to make as much style alteration as I did, depending on your UI design.

You must have noticed we also passed style props to the components provided by Kendo UI. Although KendoReact comes with a set of predefined styles, we can also alter these components as we see fit. KendoReact allows both style props and className props, so you can use inline styles or external stylesheet or both, depending on your personal preference.

Now, empty the App.css file in the `src` directory, then copy and paste the following style:

```CSS
    .dwm {
     margin-top: 1.5em;
    }
    .dwm p {
     cursor: pointer;
     margin-left: 1em;
     width: fit-content;
     color: hsl(235, 45%, 61%);
    }
    .dwm p:hover {
     color: hsl(236, 100%, 87%);
    }
    .ttc {
     background-color: hsl(235, 46%, 20%);
     color: white;
     margin-top: -1.2em;
     padding-left: 1em;
     border-radius: 10px;
    }
    .ttc h1 {
     font-size: 3rem;
     font-weight: 400;
     margin-bottom: -0.2em;
    }
    .ttc :first-child {
     margin-bottom: -2em;
    }
```

In the code above, the styles are to create a pleasant and modern UI for the project. Thanks to KendoReact, we are not restricted to only their predefined styles.

The GridLayout takes items in the prop gap as an object, while the prop rows and cols take items as an array. Also, each item in the array represents a single row or col. If, for instance, you pass in an array like this:

```JS
    cols={[
      {
       width: 200,
      },
      {
       width: 200,
      },
      {
       width: 200,
      },
      {
       width: 200,
      },
    ]}
```

Each item in the array represents each col passed into the GridLayoutItem, so column one is the array's first index, while column two is the second index of the array, so on and so forth, be it width or height.

Finally, you will notice a conditional logic at the top section of the function `App`.

```JS
    if (window.innerWidth < 600) {
      let col = 0;
      let row = 3;
      paddingScreen = 5;
      Data.map((item) => {
       if (col > 1) {
        col = 1;
        row = row + 1;
       } else {
        col = col + 1;
       }
       item.col = col;
       item.row = row;
      });
    }
```

This logic helps us alter how the grid system is rendered depending on your screen width, similar to media queries in CSS. In this case, we are performing all the logic in App.js because that is the only way we could alter the cols and rows of each GridLayoutItem.

So all we did was adjust the col and row data in the data.json file, which altered the GridLayoutItem to fit the screen width. After following all the steps, you should have the same result as the image below.

![](https://paper-attachments.dropbox.com/s_58D1EFB299078D3655326CFF9A64417B84D9E86ACEDB12856BD0266250A9AEF6_1636060805848_vezKPIeb.jpeg)
![](https://paper-attachments.dropbox.com/s_58D1EFB299078D3655326CFF9A64417B84D9E86ACEDB12856BD0266250A9AEF6_1636060805857_ZdMSjZev.jpeg)

Kindly reload the page to see layout changes after resizing the screen width for both the desktop and mobile view. Still, for those who want dynamic responsiveness like that of media queries, you could use the `addEventListener` for windows resizing then run that logic from the callback passed into the event listener.

## Conclusion

In the demo, we imported all the components from just one module. Still, when using KendoReact for a larger project, you can use as many modules as you like and import as many components as you wish from whichever modules you want with zero restrictions. Here's an example.

```SHELL
    npm install --save @progress/kendo-react-grid @progress/kendo-data-query @progress/kendo-react-inputs @progress/kendo-react-intl @progress/kendo-react-dropdowns @progress/kendo-react-dateinputs @progress/kendo-drawing @progress/kendo-react-data-tools @progress/kendo-react-animation @progress/kendo-licensing @progress/kendo-react-treeview
```

Next, import it into your project like this:

```JS
    import { process } from '@progress/kendo-data-query';
    import { Grid, GridColumn } from '@progress/kendo-react-grid';
    import { DropDownList } from '@progress/kendo-react-dropdowns';
    import { Window } from '@progress/kendo-react-dialogs';
```

You can find what their plans are on the [KendoReact pricing page](https://www.telerik.com/kendo-react-ui/pricing/). Also, all KendoReact licenses come with customer support aiding a better developer experience.