challenges

React Components: Part 2

Workshop context

Before this workshop

  • In the previous workshop, you created files for three low-level components (Button, Card and Spinner).

This workshop

  • In this workshop, we’ll add props with types to the Button and Card components, along with a skeleton JSX structure.

After this workshop

  • The application itself will be created in the next two series, Next.js Data Fetching and AI Style Generator .
  • For context, at the end of the AI Style Generator series, the application will look like this. You can see the Button variants in the upper part, and a orange Card in the lower part.
UI with options to enter a quote, submit the quote, clear the quote or generate a random quote. A styled quote is shown beneath the form.

Workshop goal

By the end of this workshop:

  1. Both the Button and Card components will be set up to take props with defined types.
  2. Card will have these required props:
    • textColor: color of the text for the card
    • backgroundColor: color of the background for the card
  3. Button will have this optional prop:
    • variant: either “filled” (a button with a dark-colored background) or “outline” (a button with a light-colored background that’s similar to the page background). The default variant value should be “filled”.
  4. Both of the components will also take children as one of the props, and return an element that wraps the children.
    • See screenshot and description above for a preview of these components in the eventual UI.
    • Don’t worry about styling for now. That will come in future workshops in this series.

Hints

Hint 1 For the Card component, both textColor and backgroundColor can be typed as string.

For the Button component, variant can be defined as one of the two specific strings, like this:

Button.tsx

export interface ButtonProps {
  variant: "filled" | "outline";
};

Hint 2 The top-level element for the Button component should be button. Using semantic HTML , the top level component for the Card component can be article. A card fits the “independent item of content” description in the MDN docs .

Hint 3 To add the children prop, you can use React.ComponentProps (as described in Matt Pocock’s article ):

Button.tsx

export interface ButtonProps 
  extends ComponentProps<"button"> {
    variant: "filled" | "outline";
  };

Then you can destructure any props that a button element accepts. For example, children:

Button.tsx

function Button({
  variant,
  children,
}: ButtonProps) {
  // component code here...
};

Hint 4 To add the children to the return value, put them inside the parent element that’s returned. for example:

Button.tsx

function Button({
  variant = "filled",
  children,
}: CardProps) {
  <button>{children}</button>
};

Hint 5 To make the variant prop optional, add a ? to the type declaration:

Button.tsx

export interface ButtonProps 
  extends ComponentProps<"button"> {
    variant?: "filled" | "outline";
  };

Specify “filled” as the default value when the props are destructured:

Button.tsx

function Button({
  variant = "filled",
  children,
}: CardProps) {
  // component code here...
};

Resources