Skip to content

`HeroCallToAction` component

In this guide, we will learn how to use and build custom components for your site.

The Epic News starter project comes with several custom components that you can start to build your site with.

Let’s take a look at some of these.

A hero section is a large, prominent section at the top of a page that is used to grab the user’s attention.

Typically, there are two main styles of hero image:

  1. The first is an image that is placed to one side of the page with a call to action section on the other:

    Hero Image To Side

  2. The second is a full-width image that spans the width of the page, sometimes overlaid with custom content:

    Full Width Hero Image

There are two main hero components in the Epic News starter project.

In this first guide, we will look at the HeroCallToAction component.

The HeroCallToAction component offers a quick way to display a hero section that places an image to one side of the page, and custom content of your own on the other.

  1. Open app/root.tsx

  2. Add the following to the end of your import list:

app/root.tsx
6 collapsed lines
import { useLoaderData } from 'react-router'
import { type Route } from './+types/root.ts'
import { type loader } from './__root.server.tsx'
import { GeneralErrorBoundary } from './components/error-boundary.tsx'
import FooterMenuRight from './components/organisms/Footer/FooterMenuRight'
import HeaderWithSearch from './components/organisms/HeaderWithSearch'
import Document from './components/shared-layout/Document.tsx'
import { ThemeSwitch, useTheme } from './routes/resources+/theme-switch.tsx'
import { useNonce } from './utils/nonce-provider.ts'
import rootLinkElements from './utils/providers/rootLinkElements.ts'
import HeroCallToAction from './components/organisms/Hero/HeroCallToAction.tsx'
  1. Next, slot this component just below the h1 tag in the JSX being returned by the App component.

    Don’t worry about the red underline that appears under the HeaderWithSearch component for now - we will fix this in a moment:

app/root.tsx
17 collapsed lines
import { useLoaderData } from 'react-router'
import { type Route } from './+types/root.ts'
import { type loader } from './__root.server.tsx'
import { GeneralErrorBoundary } from './components/error-boundary.tsx'
import FooterMenuRight from './components/organisms/Footer/FooterMenuRight'
import HeaderWithSearch from './components/organisms/HeaderWithSearch'
import Document from './components/shared-layout/Document.tsx'
import { ThemeSwitch, useTheme } from './routes/resources+/theme-switch.tsx'
import { useNonce } from './utils/nonce-provider.ts'
import rootLinkElements from './utils/providers/rootLinkElements.ts'
import HeroCallToAction from './components/organisms/Hero/HeroCallToAction.tsx'
export const links: Route.LinksFunction = () => {
return rootLinkElements
}
export { meta } from './__root.client.tsx'
export { headers, loader } from './__root.server.tsx'
export default function App() {
const data = useLoaderData<typeof loader | null>()
const nonce = useNonce()
const theme = useTheme()
return (
<Document theme={theme} nonce={nonce} honeyProps={data?.honeyProps}>
<div className="flex h-screen flex-col justify-between">
<HeaderWithSearch />
<div className="flex-1">
<main className="grid h-full place-items-center">
<h1 className="text-mega">Welcome to Epic News!</h1>
<div className="w-full py-16">
<HeroCallToAction />
</div>
</main>
</div>
<div className="container flex justify-between pb-5">
<ThemeSwitch userPreference={data?.requestInfo.userPrefs.theme} />
</div>
<FooterMenuRight />
</div>
</Document>
)
}
export const ErrorBoundary = GeneralErrorBoundary
  1. You will notice that the HeroCallToAction component is underlined in red. Let’s find out why by hovering our mouse over it:

Hero Call To Action Missing Props

The error message is telling us that the component is expecting two props to be passed to it: image and children.

Let’s add these now.

  1. Delete the line shown in red, and add the section of JSX code shown in green below:
app/root.tsx
export default function App() {
const data = useLoaderData<typeof loader | null>()
const nonce = useNonce()
const theme = useTheme()
return (
<Document nonce={nonce} theme={theme} honeyProps={data?.honeyProps}>
<div className="flex h-screen flex-col justify-between">
<HeaderWithSearch />
<div className="flex-1">
<main className="grid h-full place-items-center">
<h1 className="text-mega">Welcome to Epic News!</h1>
<div className="w-full py-16">
<HeroCallToAction />
<HeroCallToAction image="https://www.helpguide.org/wp-content/uploads/2020/01/Social-Media-and-Mental-Health.webp">
<div className="flex flex-col gap-8 px-8">
<h2 className="text-h2">Welcome to Epic News</h2>
<p className="text-lg">
Keep up to date with the latest tech news.
</p>
</div>
</HeroCallToAction>
</div>
</main>
</div>
<div className="container flex justify-between pb-5">
<ThemeSwitch userPreference={data?.requestInfo.userPrefs.theme} />
</div>
</div>
</Document>
)
}

Save the changes to your file and head back to your browser.

You should now see the HeroCallToAction component displayed correctly on your site:

Hero Call To Action

  1. Open the component file at app/components/organisms/Hero/HeroCallToAction.tsx (if you haven’t already).

  2. If you look inside the HeroCallToAction component code, you will see that it has something called an interface defined at the very top of the file.

    This interface describes the props that the component expects to receive.

    Let’s take a look:

    app/components/organisms/Hero/HeroCallToAction.tsx
    interface HeroCallToActionProps {
    image: string
    imageRight?: boolean
    hasBackgroundColour?: boolean
    children: React.ReactNode
    }
    const HeroCallToAction = ({
    26 collapsed lines
    children,
    image,
    imageRight = false,
    hasBackgroundColour = false,
    }: HeroCallToActionProps) => {
    return (
    <div
    className={`md:mx-auto md:flex md:max-w-6xl ${
    imageRight && 'md:flex-row-reverse'
    }`}
    >
    <div className="relative flex h-96 items-center justify-center overflow-hidden md:h-[32rem] md:w-1/2">
    <img
    src={image}
    alt="A hero with a call to action."
    className="absolute min-h-full min-w-full object-cover object-center"
    />
    </div>
    <div className="relative flex h-96 items-center justify-center md:h-[32rem] md:w-1/2">
    {children}
    </div>
    </div>
    )
    }
    export default HeroCallToAction

    This tells us that the component has two optional props as well as the mandatory ones we’ve been using already.

    Optional props are those that don’t have to be passed to the component when it is used, but can be if needed.

    We can tell which props are optional by the ? symbol after the prop name:

    app/components/organisms/Hero/HeroCallToAction.tsx
    interface HeroCallToActionProps {
    image: string
    imageRight?: boolean
    hasBackgroundColour?: boolean
    children: React.ReactNode
    }

    The imageRight prop is a boolean that determines whether the image should be displayed on the right or left side of the component.

    The hasBackgroundColour prop is another boolean, but this one determines whether the component should have a background colour.

  3. Let’s try adding an imageRight prop to the component where we call it in app/root.tsx:

app/root.tsx
<HeroCallToAction
image="https://www.helpguide.org/wp-content/uploads/2020/01/Social-Media-and-Mental-Health.webp"
imageRight={true}
>
<div className="flex flex-col gap-8 px-8">
<h2 className="text-h2">Welcome to Epic News</h2>
<p className="text-lg">
Keep up to date with the latest tech news.
</p>
</div>
</HeroCallToAction>

With this change saved, check your browser again:

Hero Call To Action Image Right

Notice how the picture has shifted from the left to the right?

Looking at the interface expected by a component will help you understand what props you need to pass into it.

You’ll notice that, as we’ve been adding more imports to the top of app/root.tsx, a few of these have been underlined with yellow squiggly lines.

This is because ESLint wants us to organise our imports in a certain way.

Organise imports

To fix this, hover your mouse over an underlined import and, after a moment, select Quick Fix > Fix all auto-fixable problems from the options that appear:

Fix all auto-fixable problems

VS Code will automatically organise your imports for you, and the yellow underlines will disappear.

In this step, we have:

  • Used the HeroCallToAction component to display a hero section on our site.
  • Explored the HeroCallToAction component’s props and how to pass them to the component.
  • Customised the HeroCallToAction component by adding our own custom content and styling.

In the next step, we will import and use another custom component - the ParallaxBackground hero component.