Creating a WidgetRenderer
Explore how to create a WidgetRenderer component that displays all properties of a widget type. Learn to apply Bootstrap styles for improved UI presentation, including cards, padding, and custom classes for special widgets. Understand passing props with TypeScript and using React to render structured, styled data efficiently.
We'll cover the following...
It’s time to render more than just the title and description properties of our IWidget type. Let’s make a new component, WidgetRenderer. Unlike the previous components we’ve seen, WidgetRenderer will accept the IWidget type directly as its property type. This way, we can use
Unstyled rendering of all widget properties
First, let’s render all properties of our widgets, each within a <p> tag.
When we render all our widgets data, this is the result we see:
import * as React from "react";
import { IWidget } from "../../interfaces/IWidget";
export function WidgetRenderer(props: IWidget) {
const {
isSpecialCard,
title,
description,
rating,
created,
updated,
id,
} = props;
return (
<>
<p>{title}</p>
<p>{description}</p>
<p>Rating: {rating}/10</p>
<p>#{id}</p>
<p>Created: {created.toLocaleDateString()}</p>
<p>Updated: {updated.toLocaleDateString()}</p>
<p>isSpecialCard: {isSpecialCard}</p>
</>
);
}This isn’t much of an improvement over the title and description render we originally had. It just looks like a long list of random values. So let’s pull in some real styles to render our data nicely.
Use Bootstrap to style WidgetRenderer
Bootstrap is popular CSS styling framework that will help us quickly prototype styles.
Bootstrap comes with some built-in “card” styles, that are perfect for our widgets and people data. Let’s apply some of these styles to our existing WidgetRenderer.
We’ll make the following improvements:
- First, we’ll wrap all the rendered data in a
divwith classcol-12, to make it a full-width div, andp-3for some padding on all sides - We’ll then add a wrapping
divwith classcard, and an additional classspecialCardif this widget has anisSpecialCardvalue oftrue - We’ll segregate the card body and card footer with new divs having class
card-bodyandcard-footer, respectively. Finally, we’ll addcard-title, andcard-textto the actual text properties of our widget - We’ll make the
ratingproperty italic withfst-italic - We’ll put the
createddate,updateddate, andidon a single line, theidto the left withfloat-start, and the dates to the right withfloat-end.
Finally, let’s define that specialCard class. This isn’t a built-in class from Bootstrap. To make it fun, we can use a bright rainbow gradient background for the specialCard class. We can place this class in our own CSS file, which we’ll call custom.css.
Now our WidgetRenderer component now looks like this:
import * as React from "react";
import { IWidget } from "../../interfaces/IWidget";
export function WidgetRenderer(props: IWidget) {
const {
isSpecialCard,
title,
description,
rating,
created,
updated,
id,
} = props;
return (
<div className="col-12 p-3">
<div className={isSpecialCard ? "card specialCard" : "card"}>
<div className="card-body">
<h1 className="card-title">{title}</h1>
<p className="card-text">{description}</p>
<p className="card-text fst-italic">Rating: {rating}/10</p>
</div>
<div className="card-footer text-muted">
<span className="float-start">#{id}</span>
<span className="float-end">Created: {created.toLocaleDateString()} Updated: {updated.toLocaleDateString()}</span>
</div>
</div>
</div >
);
}