How to get CSS styles to work in a Fluent UI React Panel control

Sometimes this should be obvious and they just aren’t. I use the Panel component in Fluent UI React / Office Fabric from time to time. I’ve always struggled to work with styles there coming out of my web part’s module.scss file. That’s because they simply aren’t being applied.

Let’s look at this simple example web part:

import * as React from "react";
import { override } from "@microsoft/decorators";
import styles from './MyWebPart.module.scss';
import { Panel, PanelType } from 'office-ui-fabric-react/lib/Panel';


export default class ReportPanel extends React.Component<IMyWebPartProps, {
    showPanel: boolean
}> {

    constructor(props: IMyWebPartProps) {
        super(props);

        this.setState({
            showPanel: true
        });
    }


    @override
    public render(): React.ReactElement<{}> {
        return (
            <React.Fragment>
                <div className={styles.myWebPart}>
                    <Panel isOpen={this.state.showPanel}  onDismiss={() => { this.setState({ showPanel: false }); }} headerText={'My Panel Header'}>
                            <p className={styles.panelBody}>
                                Some text
                            </p>
                            <p className={styles.title}>
                                Page Analytics
                            </p>
                    </Panel>
                </div>
            </React.Fragment>);
    }
}

Note we have two styles in the body of the panel named panelBody and title. Here’s what our module.scss looks like:

@import '~office-ui-fabric-react/dist/sass/References.scss';

.myWebPart {
  .title {
        @include ms-font-l;
    }

  .panelBody {
        margin-top: 10px;
        margin-bottom: 10px;
    }

}

We would expect that our panelBody and title styles would be applied normally. That’s not he case though. Think of the panel as a whole new surface. That means you need to wrap your panel contents in a top-level div element first. You can use the same top level style as your web part, but you could probably create a new one if you wanted as well. Here’s the updated code snippet:

import * as React from "react";
import { override } from "@microsoft/decorators";
import styles from './MyWebPart.module.scss';
import { Panel, PanelType } from 'office-ui-fabric-react/lib/Panel';


export default class ReportPanel extends React.Component<IMyWebPartProps, {
    showPanel: boolean
}> {

    constructor(props: IMyWebPartProps) {
        super(props);

        this.setState({
            showPanel: true
        });
    }


    @override
    public render(): React.ReactElement<{}> {
        return (
            <React.Fragment>
                <div className={styles.myWebPart}>
                    <Panel isOpen={this.state.showPanel} isBlocking={false} type={PanelType.smallFixedFar} onDismiss={() => { this.setState({ showPanel: false }); }} headerText={'My Panel Header'}>
                        <div className={styles.myWebPart}>
                            <p className={styles.panelBody}>
                                Some text
                            </p>
                            <p className={styles.title}>
                                Page Analytics
                            </p>
                        </div>
                    </Panel>
                </div>
            </React.Fragment>);
    }
}

I suspected something like this was always the cause. Finally I found some validation in it. This issue was opened a few years ago. It was quickly closed because the Fluent teams doesn’t seem to use SPFx much even though SPFx developers are some of the largest users of Fluent. I suspect this also applies to other surface like Modal.

Published by coreyroth

Corey Roth is the Vice President of Engineering at UnlimitedViz where he helps build the tyGraph product line for data analytics in Microsoft 365. Corey is an eleven-time recipient of the Microsoft MVP award in Office Apps and Services. Corey helps ISVs develop mobile-first applications for Office 365 using technologies such as Ionic Framework and Azure. Corey has always focused on rapid adoption of new Microsoft technologies including Office 365 and Azure. In his spare time, Corey works with his wife, Jennifer, on their product BrewZap, a mobile app platform for breweries.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: