Macros

Contents

Rich Text also supports custom components - aka Macros.

Background

In order to support more complex structure within Enonic’s Rich Text editor, you can define macros.

Details on defining macros can be found in the XP documentation.

Default macro handling

The sample content contains an example macro called Factbox, which has been added to the Lea Seydoux bio.

By default, the RichText component will simply render a fallback placeholder:

no macro

To improve the situation, start by implementing a FactBox component.

The FactBox component

Add the following files to your project:

src/components/FactBox.tsx
import styles from './FactBox.module.css';

declare type FactBoxProps = {
    config: Record<string, any>
    children: React.ReactNode
};

export const FactBox = ({config, children}: FactBoxProps) => (<>
    <ins className={styles.factbox}>
        <strong className={styles.header}>{config.header?.length ? config.header : 'Fact Box'}</strong>
        <br/>
        {children}
    </ins>
</>)
The optional body of a macro is available as a React component called children.
src/components/FactBox.module.css
.icon {
    speak: none;
    font-style: normal;
    font-weight: normal;
    font-variant: normal;
    text-transform: none;
    line-height: 1;

    /* Better Font Rendering =========== */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

.factbox {
    background-color: rgb(235, 249, 249);
    display: block;
    text-decoration: none;
    -webkit-border-radius: 2px;
    -moz-border-radius: 2px;
    border-radius: 2px;
    clear: both;

    -webkit-box-shadow: 0 2px 3px rgba(0, 0, 0, .3);
    -moz-box-shadow: 0 2px 3px rgba(0, 0, 0, .3);
    box-shadow: 0 2px 3px rgba(0, 0, 0, .3);

    min-height: 24px;
    line-height: 24px;

    font-family: sans-serif;
    font-size: 14px;
    color: #333;

    padding: 10px 20px 10px 44px;
    width: 75%;
    margin: 20px auto;
    position: relative;
}

.factbox .header {
    font-size: 14px;
    font-weight: bold;
    line-height: 24px;
    margin: 0;
    color: #1f71a1;
}

.factbox .body ul {
    padding-left: 0;
}

.factbox .body ul li {
    margin: 5px 0;
}

@media screen and (max-width: 720px) {
    .factbox {
        width: 90%;
    }
}

Like other components, you may also declare a query for your Macro - but in this case we already have everything we need in the data returned from the original bio query.

The Macro component

We now have a FactBox component, but we still need to map it to the Enonic macro definition. This can be solved by implementing a generic Macro component where you map specific macro descriptors to corresponding macro components.

src/components/Macro.tsx
import type {MacroComponent} from '@enonic/react-components';


import {FactBox} from './FactBox';


export const Macro: MacroComponent = ({
    config,
    descriptor,
    children,
    ...rest
}) => {
    if (descriptor === 'com.enonic.app.intro:factbox') {
        const props = {...rest, config};
        return <FactBox {...props}>{children}</FactBox>;
    }
    throw new Error(`Macro not found: ${descriptor}`);
}

This component takes care of mapping each macro to its corresponding React component. In our case, FactBox component implements the macro called com.enonic.app.intro:factbox in Enonic.

It will throw an error otherwise, which will cause the RichText component’s ErrorBoundary to render an Error placeholder.

Use in RichText

Just like with Link and Image components, import Macro component and pass it to the RichText component:

src/components/Person.tsx
import {Macro} from './Macro';

// ..

<RichText
  // ...
  Macro={Macro}
  // ...
/>

If you did everything correctly, you should now see the FactBox macro rendered inside the biography on the Lea Seydoux page:

factbox macro

A final tip

You may pass additional parameters, such as personID to the RichText component by supplying a generic interface declaring them:

<RichText<RestProps>
  ...
  personID="paramValue"
  ...
/>

interface RestProps {
  personID: string;
}

These params will be passed on to the Image, Link and Macro components as well.

Next steps

Congratulations on completing this tutorial!

For more details on our React Components library, visit the NPM documentation.

To learn more about Enonic’s CMS capabilities, we recommend the Developer 101 tutorial.

To dive deeper into React and building sites with Enonic, have a look at our Next.js integration.


Contents

Contents

AI-powered search

Juke AI