Search⌘ K
AI Features

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.

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 spread syntaxAllows an iterable such as an array expression or string to be expanded in places where zero or more arguments are to be used. to pass in each widget directly.

Unstyled rendering of all widget properties

First, let’s render all properties of our widgets, each within a <p> tag.

TypeScript 3.3.4
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>
</>
);
}

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>
    </>
  );
}
Our WidgetRenderer rendering all properties of IWidget

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 div with class col-12, to make it a full-width div, and p-3 for some padding on all sides
  • We’ll then add a wrapping div with class card, and an additional class specialCard if this widget has an isSpecialCard value of true
  • We’ll segregate the card body and card footer with new divs having class card-body and card-footer, respectively. Finally, we’ll add card-title, and card-text to the actual text properties of our widget
  • We’ll make the rating property italic with fst-italic
  • We’ll put the created date, updated date, and id on a single line, the id to the left with float-start, and the dates to the right with float-end.
TypeScript 3.3.4
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()}&nbsp;Updated: {updated.toLocaleDateString()}</span>
</div>
</div>
</div >
);
}

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.

NAME_
CSS
.specialCard {
background: linear-gradient(64deg, rgba(255,0,0,1) 0%, rgba(255,255,0,1) 30%, rgba(5,193,255,1)70%, rgba(158,31,255,1) 100%);
}

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()}&nbsp;Updated: {updated.toLocaleDateString()}</span>
        </div>
      </div>
    </div >
  );
}
Rendering all widgets through the new WidgetRenderer component