com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_link3' is unknown.

Resolving CSS style conflicts

A widget developer can use CSS styles for styling the widget in different ways, such as inline styles, external stylesheet, etc. 

Since a dashboard is a collection of multiple widgets each using its own set of styles, if the styling is not done correctly there is a probability of final dashboard ending up with stylesheet conflicts.

There are several approaches that we can take in order to prevent this.

Using inline styles

Inline styles are one of the safest approaches to prevent style conflicts. In this method the respective CSS styles are bound with the underline markup and only affect that specific tag hence there won’t be style conflicts.

Using CSS modules

Inline styles lack in maintainability. Inability to share common styles among elements end up in a huge pile of duplicate code. This can be avoided by using CSS as classes. But since all the widgets are rendered in the un-sandboxed environment probably there will be style conflicts.

This can be avoided by using CSS modules.

CSS modules allow to style a component via CSS stylesheet like approach, but the class names are scoped to the local ReactJS component. This is achieved by prefixing each CSS class name with a random string at the build-time. Please follow the following steps to enable CSS modules.

For implement CSS modules webpack build system, style-loader, and the css-loader need to be installed in within the widget. Use the following command to install the above modules.

  1. Open the webpack.config.js file in the widget root directory.
  2. We need to configure the Webpack css-loader to load CSS as CSS modules. Add the following configuration into the webpack.config.js file.

    module.exports = {
        ...
        module: {
            loaders: [
                ...
                {
                    test: /\.css$/,
                    loader: 'style-loader!css-loader?modules=true&localIndentName=[name]__[local]___[hash:base64:5]'
                },
                ...
            ]
            ...
        }
        ...
    }
  3. Now open the widget JSX file and use the CSS styles/classes defined in the external CSS file as follows.

    ...
    import styles from './MyComponent.css';
    
    class MyComponent extends React.component {
        /* ... */
        render() {
            return (
                <button className={styles.myButton} />
            )
        }
        /* ... */
    }
com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links2' is unknown.