Commons components and props

Contents

In this chapter you will add global styling and a footer component to the site

Global CSS

To make the site more appealing, we’ll need some style. By adding a global CSS file, we avoid repeating general styling for each component.

Follow the steps below:

  1. Create CSS file in the component directory:

    react4xp/components/globalStyles.css
    html {
      background-color: #071622;
      color: ghostwhite;
      font-family: "Helvetica Neue", Verdana, Arial, sans-serif;
      padding: 0;
    }
    
    body {
      margin: 0 auto 0 auto;
    
    }
    
    #PageView {
      width: 100%;
    }
    
    .contentContainer > div {
      margin-bottom: calc(6vh - 16px);
      min-height: 86vh;
      padding: 8px;
      max-width: 1400px;
      padding-inline: 2.5vw;
      margin-inline: auto;
    }
    
    h1 {
      color: #0892D4;
      font-size: 3rem;
      margin: 0 0 3rem 0;
      padding-top: 3rem;
      text-align: left;
      line-height: normal;
    }
    
    h2 {
      color: #EF82F0;
      font-size: 2rem;
    }
    
    h3 {
      color: #61DBFB;
      font-size: 1.4rem;
    }
    
    a {
      color: #61DBFB;
    }
    
    img {
      object-fit: cover;
      object-position: 50% 50%;
      max-width: 1600px;
    }
    
    p {
      font-size: 22px;
    }
    
    .editor-align-justify {
      margin-inline: auto;
    }
  2. Register the file in App.tsx by adding the following line

    react4xp/entries/App.tsx
    import '../components/globalStyles.css';

Refresh the Hello page to see the what happened:

hello

App.tsx is the common starting point for all rendering, and can be used for more than simply styling, for instance by adding a footer.

Follow the steps below to get a glorious new footer across all pages in the site.

  1. Add the footer component:

    react4xp/components/common/Footer.tsx
    import React from 'react';
    import styles from './Footer.module.css';
    
    
    export interface FooterProps {
        logoUrl: string;
    }
    
    const Footer = ({logoUrl}: FooterProps) => (
        <footer className={styles.footer}>
            <div className={styles.footerContainer}>
                <p>
                    <span className={styles.rotateRight}>©</span>
                    {` ${new Date().getFullYear()}, Built with `}
                    <a href="https://reactjs.org">React4XP</a>
                </p>
            </div>
            {logoUrl && (
                <div className={styles.logoContainer}>
                    <img src={logoUrl}
                         width={32}
                         height={42}
                         alt="Enonic XP logo"/>
                </div>
            )}
        </footer>
    );
    
    export default Footer;
  2. Add a dedicated CSS module for the footer.

    react4xp/components/common/Footer.module.css
    .footer {
      margin: 1vh auto auto auto;
      width: 100%;
      text-align: center;
      background-color: black;
      position: absolute;
      left: 0;
      font-size: 18px;
      height: 7vh;
      min-height: 45px;
      align-content: center;
    }
    
    .footer a {
      color: #61dbfb;
      text-decoration: none;
      font-weight: 500;
    }
    
    .footer a:hover {
      color: #0892D4;
      text-decoration: underline;
    }
    
    .footer p {
      margin: 0 .5rem;
    }
    
    
    .logoContainer {
      position: absolute;
      bottom: 1.5vh;
      right: 1.5rem;
    }
    
    .logoContainer img {
      max-width: 2.6vh;
      min-width: 20px;
      height: auto;
    }
    
    .rotateRight {
      display: inline-block;
      transform: rotate(90deg);
    }
  3. Add the Footer component to App.tsx:

    react4xp/entries/App.tsx
    import Footer from "/react4xp/components/common/Footer";
    import '../components/globalStyles.css'
    import type {AppProps} from '/types/AppProps';
    import {BaseComponent} from '@enonic/react-components';
    import * as React from 'react';
    import {componentRegistry} from '../componentRegistry';
    
    const App: React.FC<AppProps> = (props) => {
        return (
            <>
                <BaseComponent componentRegistry={componentRegistry} data={props}/>
                {
                    (props.type == "page" || props.type == "contentType") &&
                    <Footer logoUrl={props.commonProps.logoUrl as string}/>
                }
            </>
        );
    }
    
    App.displayName = 'App';
    
    export default App;

We are not entirely done yet, as the Footer component requires some props, in order to work properly (pun intended).

Static asset

To make thigs a bit more interesting, the Footer will render the React4XP logo. This means we will need a URL to a static file.

The logo already exists in resources/assets/react4xp.svg

The Footer is not part of the ComponentRegistry, but it can still use the dataFetcher to get props. For this case, a data processor can be registered as a common processor. Props from the common processor can be accessed across components.

  1. Create a processor:

    react4xp/components/common/CommonProcessor.ts
    import {assetUrl} from '/lib/enonic/asset';
    import type {ComponentProcessorFunction} from '@enonic-types/lib-react4xp/DataFetcher';
    
    export const commonProcessor: ComponentProcessorFunction<'com.enonic.app.hmdb:main'> = (props) => {
    
        const logoUrl = assetUrl({path: 'react4xp.svg'});
    
        return {
            logoUrl
        };
    };

    It invokes assetUrl() to get the URL for the logo, and returns it as a prop.

  2. Register the processor in the data fetcher:

    react4xp/dataFetcher.ts
    import {DataFetcher} from '/lib/enonic/react4xp';
    import {commonProcessor} from '/react4xp/components/common/CommonProcessor';
    import {helloProcessor} from './components/HelloProcessor';
    
    export const dataFetcher = new DataFetcher();
    dataFetcher.addContentType('portal:site', {processor: helloProcessor});
    dataFetcher.addCommon({processor: commonProcessor});

    Using addCommon ensures this will be executed for every rendering request.

    Be careful to only get the props you need, or else this may slow down rendering of all pages.

hello

Sweet! You now have a stylish site with a footer component on all pages. The footer also brings it own CSS via a CSS module.

Next

You are on a roll, in the next chapter we’ll be rendering content.


Contents

Contents

AI-powered search

Juke AI