Skip to main content

Command Palette

Search for a command to run...

Beyond Dark Mode

The UX Decisions Behind My Grocery CRM Dashboard

Published
6 min read
Beyond Dark Mode
U

I specialize in building production-ready web applications using the MERN stack, Next.js, and modern UI frameworks. My work spans full-stack development, dashboard systems, authentication flows, and deployment on VPS environments.

On this blog, I share practical experiences, lessons learned from real projects, and insights into building scalable, user-centric digital products.

The "Dashboard" Trap

As developers, when we hear the word "Dashboard," our instinct is usually to find the coolest charting library we can find, throw 20 widgets on the screen, and call it a day. We want it to look like the control center of a spaceship.

But when I started designing the Grocery CRM for my latest project, I had to stop myself.

A grocery store manager doesn't need a spaceship. They need to know three things immediately:

  1. How much money did we make today?

  2. Are we running out of stock?

  3. Is the business growing or shrinking?

If the dashboard takes more than 5 seconds to answer those questions, the design has failed.

Here is a breakdown of the UI/UX decisions that went into building the dashboard you see above, covering everything from Color Theory to React Component Architecture.

Decision 1: The "Dark Mode First" Approach

You’ll notice the interface defaults to a deep, blue-black theme (specifically #0f172a family colors). This wasn't just because "Dark Mode is cool."

The Context:
Grocery store back-offices are often dimly lit, or conversely, have harsh fluorescent lighting. A blinding white screen causes eye strain during long inventory sessions.

The Execution:
I used a high-contrast palette.

  • Background: Deep Navy/Black to recede into the distance.

  • Text: Pure White (#ffffff) for primary metrics, Grey (#94a3b8) for labels.

  • Accents: I used "Neon" variants of primary colors. Standard green or blue often looks muddy on dark backgrounds. I bumped up the saturation to ensure the charts pop against the void.

This reduces "cognitive load." The user's eye isn't fighting the background; it's drawn immediately to the colored data points.

Decision 2: The "Sparkline" Cards (Immediate Health Check)

At the very top of the dashboard, I placed four key cards: Sales, Purchases, Products, and Inventory.

<img src="YOUR_DASHBOARD_IMAGE_HERE" alt="CRM Dashboard Header" />

The UX Problem:
A raw number (e.g., "23,601 Sales") is meaningless without context. Is that good? Is that bad? Did we crash yesterday?

The Solution:
I implemented Sparklines (mini-charts) inside the cards.
Look at the Sales card. It doesn't just say "23,601". It shows a jagged line graph next to it.

  • Upward trend? Good.

  • Flatline? Stable.

  • Downward spike? Problem.

I also added a percentage indicator (e.g., 4230.5% this month in green). This uses a classic "Traffic Light" system: Green text means positive growth, Red text (like in the Products card) means a drop.

The Tech Stack:
To render these efficiently in React without killing performance, I used Recharts. I stripped away the axes, grids, and tooltips for these mini-charts to keep the DOM lightweight.

Decision 3: The "Area Chart" Overlap

The centerpiece of the dashboard is the large Sales/Purchases graph.

Why an Area Chart?
I could have used a Bar chart, but I chose an Area chart with a gradient fill.

  • Psychology: Area charts imply volume and accumulation. It feels like "money in the bank."

  • Comparison: By overlaying Sales (Purple) and Purchases (Green), the user can instantly see the gap between them.

    • If Purple is higher than Green = Profit.

    • If Green covers Purple = Loss.

The Transparency Hack:
Notice the opacity in the chart fill. If I used solid colors, the data in the back would be hidden. By using fillOpacity={0.5}, I created a "Ven Diagram" effect where the intersection of data is visible.

Decision 4: The Navigation Architecture (Sidebar)

I stuck to the classic Left Sidebar pattern.

In web design, we read in an F-Pattern:

  1. Start top left (Logo/Brand).

  2. Scan down the left (Navigation).

  3. Scan across the top (Headline/Metrics).

The Hierarchy:
I grouped the navigation items by "Frequency of Use."

  • Sales & Purchases: The daily operations. Top of the list.

  • Inventory & Products: The management tasks. Middle.

  • Reports & Employees: Admin tasks. Bottom.

I also added a Collapse Button (<) at the top of the sidebar. On smaller screens or tablets (common in retail environments), the user can collapse the menu to give the data more room to breathe.

Decision 5: The "Donut" vs. "Pie" Debate

On the right side, there is a Stocks by Category chart.

I specifically chose a Donut Chart over a standard Pie Chart.
Why?

  • Data Density: A Pie chart is a solid circle. A Donut chart has a hole in the middle.

  • The Hole: That empty space is valuable real estate. In future updates, I plan to put the "Total Items" number inside the donut hole.

  • Aesthetics: It simply looks lighter and more modern. It doesn't feel like a heavy blob of color on the screen.

Decision 6: The "Quick Action" Button (Fitts's Law)

Look at the bottom right: "Add New Sale".

This is the only button on the entire dashboard that uses a solid, bright purple fill.
In UX, this is called the Primary Call to Action (CTA).

According to Fitts's Law, the time required to move to a target is a function of the distance to the target and the size of the target.

  • I made the button wide.

  • I placed it in a distinct container.

  • I used an icon (Chart icon) + Text.

Even if a user is rushing, their eye hits that purple button immediately. It is the "Start" button for their most common task.

The Technical Challenge: Performance

Building a dashboard like this in React comes with a hidden cost: Re-renders.

If the Sales data updates via a WebSocket or an API poll, we don't want the Sidebar or the Header to re-render. That causes UI lag.

How I optimized it:

  1. Component Isolation: The Charts are isolated in their own components (<SalesChart />, <StatsCard />).

  2. useMemo: I used the useMemo hook to calculate the total totals (e.g., summing up the Sales array) only when the data actually changes, not when the user toggles the sidebar.

  3. Lazy Loading: The charts are heavy. I load them lazily so the skeleton of the page appears instantly, and the charts pop in 200ms later.

Summary

A dashboard isn't just about showing data; it's about hiding data. It's about stripping away the noise until only the signal remains.

For this Grocery CRM, every pixel—from the neon green stroke on the chart to the collapsible sidebar—was chosen to help a busy manager make a decision in under 5 seconds.

If you want to see the code behind these charts, check out the project on my portfolio.

Thanks for reading!

If you enjoyed this breakdown, you might like my project Grocery CRM. It’s a full-stack dashboard built with React and the MERN stack.

🚀 Check out the Live Demo on my Portfolio at uzairalam.me

👋 Connect with me on Twitter/X or LinkedIn for more updates.