From Raw HTML to Blazor Magic: Building David’s Cool Components
I wanted to keep rolling with my series on turning raw HTML, CSS, and JavaScript into clean Blazor components—and honestly, I just wanted to build something fun for a change. So, I put together a little playground I'm calling David's Cool Components.
It's got a colorful countdown timer, a sleek digital clock, a rotating testimonial slider, and a slide-out navigation menu tying it all together. No grand enterprise architecture here. Sometimes you just want to make stuff move on the screen, watch numbers tick down, and say, "Hey, that actually looks pretty slick!"
But beneath the fun stuff, it turned out to be a solid exercise in taking plain web component behaviors and expressing them naturally in Blazor.
Four Colorful Boxes and Something to Look Forward To
The countdown is the first thing you see when you land on the app. It features four chunky, rounded cards displaying days, hours, minutes, and seconds against a dark background. Red, green, yellow, and blue cards with bold white numbers and long diagonal shadows give it a genuinely playful vibe.
You could use it to count down to a well-deserved vacation, a product launch, your next blog drop, or that moment you finally promise yourself you'll stop adding features to a demo.
Here's a fun little interactive touch I snuck in: right-click the Days card to set your target date and time. That pops open an editor where you can pick a future date right in your local time zone. (Don't worry, clicking, tapping, or hitting it via keyboard works too, so mice aren't strictly mandatory.)
Your target gets safely stashed in the browser's local storage, meaning a page refresh won't nuke your countdown. And once zero hits? It politely stops rather than marching off into depressing negative numbers.
In Blazor, those values are driven entirely by component state. A periodic timer handles the heartbeat, but the remaining time is calculated live from the target date versus right now. That distinction is huge—counting timer callbacks is definitely not the same as measuring true elapsed time, especially when your browser tab gets throttled in the background.
Making It Reusable
Once I got the countdown working, I wrapped it up into a neat little Countdown.razor component. Now, my home page just looks like this:
@using NexCorp.Client.Components
<Countdown />
Need another one somewhere else with a different target date and storage key? Easy:
<Countdown StorageKey="next-launch"
InitialTargetDate="@new DateTimeOffset(2027, 1, 1, 0, 0, 0, TimeSpan.Zero)" />
Different storage keys let multiple countdowns mind their own business. The styling stays bundled safely in Countdown.razor.css, and the cards automatically scale down to a tidy two-by-two grid on smaller viewports.
That is peak component reuse for me: drop it on a page without having to copy-paste markup, timer logic, or stylesheets.
A Digital Clock: Watching Time Go the Other Direction
If the countdown tells you how long you have to wait, the digital clock tells you what century you're currently stuck in.
It displays the current date right above separate hour, minute, and second blocks, defaulting to a classic 12-hour format complete with an AM/PM badge. Because this is a Blazor WebAssembly app running locally, it grabs the time straight from your device—no heavy server sync required.
The DigitalClock component also comes loaded with parameters:
<DigitalClock Title="TIME TO BUILD SOMETHING"
ShowDate="true"
ShowSeconds="true"
Use24HourFormat="true" />
Flip the title, drop the seconds, toggle 24-hour time—do whatever floats your boat. Under the hood, a C# PeriodicTimer refreshes the UI every second by pulling a fresh time reading instead of risking drift by just adding one second blindly.
Simple? Extremely. Still deeply satisfying to watch tick? Absolutely.
Testimonials with a Little Personality
Next up: the testimonial slider.
The original HTML version used raw JavaScript to swap an image, quote, and name every ten seconds. I brought that logic right into Blazor, wrapping it in the app's signature dark theme, blue cards, and clean typography.
It cycles through three sample testimonials, each rocking a circular portrait overlapping the card edge. I also threw in pause/resume controls and slide-selection dots because moving text should never force-read faster than humanly possible.
In Blazor, sliding to the next item is as clean as an array index lookup:
_index = (_index + 1) % Testimonials.Length;
Razor handles the rendering of the active portrait and text seamlessly. No hunting down DOM nodes or manually swapping innerHTML strings.
And yes, my sample comments heavily praise Coding with David, utilizing generated portraits stored locally. (Disclaimer: these are totally fictional customers. My imaginary audience is wildly enthusiastic about component styling!)
A Hamburger That Opens More Than Lunch
A multi-page playground needs a solid navigation menu.
The shared header displays the app name and logo, anchored by a crisp red hamburger button in the top-right corner. Tapping it slides a clean white sidebar right into view, housing links to:
- Countdown
- Digital clock
- Testimonials
You can dismiss it via the X button, the Escape key, clicking outside the panel, or simply clicking a destination link.
The drawer leans on a native HTML dialog opened as a modal, ensuring accessibility features like focus trapping work out of the box. A tiny JavaScript module handles the slick slide animation, which gracefully respects the browser's prefers-reduced-motion media query.
What Changes When Raw HTML Becomes Blazor?
The point of this exercise wasn't just slapping a .razor extension on an old HTML file and calling it a day.
In plain web pages, JavaScript drives the entire UI—it hunts down elements, mutates text nodes, swaps class lists, and schedules loops. In Blazor, state drives the interface. Razor reflects your variables, and event handlers update them.
That means:
- The countdown renders calculated numbers instead of rewriting text manually.
- The digital clock exposes clean component parameters instead of forcing markup edits.
- The slider tracks an active record index rather than manipulating separate DOM elements.
JavaScript isn't banned, though. I still lean on it for browser-specific plumbing like LocalStorage, local time zone parsing, and driving the modal animation. The goal isn't zero JS; it's letting Blazor manage the UI while keeping interop laser-focused.
The Less Glamorous Part: Cleanup
Timers are wonderfully easy to spin up and terrifyingly easy to forget about.
Every single one of these components implements IAsyncDisposable. When you navigate away, their background loops are canceled and resources get cleaned up. Leaving background loops running for components that aren't even on screen anymore is definitely not the vibe we want.
CSS styling also keeps you humble. Moving markup into an isolated component file can completely shift how scoped styles behave. And let's be honest: moving a closing div to the wrong line can instantly turn a neat four-card countdown into a towering skyscraper of broken boxes. (Yes, that happened. A successful compile doesn't mean your CSS survived contact with the browser!)
Why Build Little Things Like This?
Small visual projects are the absolute best way to practice component design without getting bogged down by a massive enterprise application's baggage.
Each piece teaches a unique lesson: state updates, parameters, browser storage, conditional rendering, accessibility, responsive design, and targeted JS interop. They remind us that learning doesn't always have to look like a soul-crushing database form with twelve required fields.
Sometimes, learning looks like four colorful boxes, a ticking clock, three fictional cheerleaders, and a slick slide-out menu.
Keep coding, keep experimenting, and go give your next component a little personality!

Comments
Post a Comment