Blog / 30 Days Frontend Design&Coding Challange
Jul 06, 2024 · 4 mins read
93 views
Welcome to my 30-day frontend design challenge! Over the next month, I will be diving deep into the world of frontend development, creating and showcasing a new design component or feature each day. This journey aims to sharpen my skills, explore new technologies, and share my progress with the community. Follow along to see the highs, the lows, and everything in between as I tackle this exciting challenge.
Kicking off the challenge, I started with a HeatMap.js component. Heatmaps are an excellent way to visualize data density or intensity. For this component, I focused on creating an interactive heatmap that responds to user input. I used a dataset representing website click data to highlight popular areas of a webpage. This exercise helped me understand how to manipulate data for visual impact and improve my skills in using JavaScript libraries for data visualization.
Key Features:
Technologies Used:
// components/Heatmap.js
import React from "react";
import { twMerge } from "tailwind-merge";
const Heatmap = ({ data, xLabels, yLabels }) => {
const getHeatmapColor = (value) => {
const max = Math.max(...data.flat());
const min = Math.min(...data.flat());
const intensity = (value - min) / (max - min);
const colorClasses = [
"bg-violet-100", // Lightest shade
"bg-violet-200",
"bg-violet-300",
"bg-violet-400",
"bg-violet-500",
"bg-violet-600",
"bg-violet-700", // Darkest shade
];
const colorIndex = Math.floor(intensity * (colorClasses.length - 1));
return colorClasses[colorIndex];
};
// Calculate the number of columns based on the length of the longest row
const numColumns = Math.max(...data.map((row) => row.length));
// Calculate the number of rows based on the length of the data array
const numRows = data.length;
return (
<>
<div className="bg-white px-8 pb-8 pt-4 rounded-xl">
<p className="font-bold text-xl text-center font-mono"> HeatMap</p>
<div
className="grid gap-2 font-mono "
style={{
gridTemplateColumns: `repeat(${numColumns + 1}, minmax(0, 1fr))`,
gridTemplateRows: `repeat(${numRows + 1}, minmax(0, 1fr))`,
}}
>
{/* Empty top-left corner */}
<div></div>
{/* X-axis labels */}
{xLabels.map((label, index) => (
<div
key={index}
className="flex font-mono items-end px-1 justify-center h-full text-sm font-bold"
>
{label}
</div>
))}
{/* Y-axis labels and heatmap cells */}
{data.map((row, rowIndex) => (
<>
{/* Y-axis label */}
<div
key={`y-${rowIndex}`}
className="flex font-mono items-center justify-center text-sm font-bold"
>
{yLabels[rowIndex]}
</div>
{/* Heatmap row */}
{row.map((value, colIndex) => (
<div
key={`${rowIndex}-${colIndex}`}
className={twMerge(
"heatmap-cell flex items-center m-auto rounded-lg justify-center p-2",
getHeatmapColor(value)
)}
style={{ width: "2.5rem", height: "2.5rem" }} // Ensuring fixed size for alignment
>
{value}
</div>
))}
</>
))}
</div>
</div>
</>
);
};
export default Heatmap;
Usage Example: Ensure you pass the correct props (data, labels, legends, and orientation) when using the BarGraph component in your application:
// pages/index.js
import Head from "next/head";
import Heatmap from "@/components/HeatMap";
import BarGraph from "@/components/BarGraph";
export default function Home() {
const heatmapData = [
[35, 42, 56, 78, 91, 84, 69, 53],
[82, 31, 45, 67, 22, 73, 58, 41],
[40, 55, 68, 74, 45, 19, 74, 60],
[18, 87, 41, 33, 78, 69, 54, 37],
[58, 37, 51, 73, 38, 79, 64, 47],
];
const yLabels = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
const xLabels = [
"8 AM",
"10 AM",
"12 PM",
"2 PM",
"4 PM",
"7 PM",
"10 PM",
"2 PM",
];
return (
<div className="flex gap-4 items-center justify-center min-h-screen bg-gray-100">
<Head>
<title>Heatmap</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<Heatmap data={heatmapData} xLabels={xLabels} yLabels={yLabels} />
</div>
);
}
These first few days have been incredibly rewarding. Each project has challenged me to think critically about design, data visualization, and user interaction. Here are a few key takeaways so far: