4

We are developing modern webparts for O365 Communication Sites using Office UI Fabric React. I want to use the new ts-based approach to styling my components(see here). Everything works quite well, except that it's not using the current theme of the SharePoint site it's deployed to.

My webpart was created using standard Yeoman scaffolding for SharePoint webparts (selecting React as the framework).

My styling code looks like this:

import { getTheme, FontWeights, mergeStyleSets } from 'office-ui-fabric-react/lib/Styling';

export interface IComponentClassNames {
    locationBanner: string;
    locationLabel: string;
    locationValue: string;
    editLocationButton: string;
    findLocationButton: string;
}

const theme = getTheme();

export const getClassNames = (): IComponentClassNames => {
    return mergeStyleSets({
        locationBanner: {
            display: 'inline-flex',
            paddingLeft: '8px',
        },
        locationLabel: [
            theme.fonts.large,
            {
                color: theme.palette.neutralPrimary
            }
        ],
        locationValue: {
            color: theme.palette.themeDark
        },
        editLocationButton: {
            paddingLeft: '20px'
        },
        findLocationButton: {
            paddingLeft: '10px'
        }
    });
};

And then in the render part of my component I do the following:

const {locationBanner, editLocationButton, findLocationButton, locationLabel, locationValue} = getClassNames();

And then apply that in the className-attributes. This works fine and the style is applied - however: getTheme() returns the default theme (i.e. mainly blue), not what is currently set on the SharePoint site. Do I somehow have to pass the theme down to my component (from the webpart ts) or how should this work?

dominikk
  • 356
  • 3
  • 11

2 Answers2

4

My solution was to pull the theme from the window object, build a theme object, and pass it around to the components as needed

Like this:

Build the theme at the root ts file

const ThemeColorsFromWindow: any = (window as any).__themeState__.theme;
const siteTheme: ITheme = createTheme({ //pass this object to your components
  palette: ThemeColorsFromWindow
});

Then I passed the theme to my components where needed.

<MyButton
    ButtonText={this.props.itemButtonText}
    ButtonType={'dark'}
    ButtonURL={this.props.itemButtonURL}
    siteTheme={siteTheme} //site theme is passed to component
/>

Build my CSS-in-JS object

  const siteTheme: IReadonlyTheme = this.props.siteTheme; //shortening the path a little

  ButtonStyles: IButtonStyles = { //the interface here varies by component
    root:{
      backgroundColor: siteTheme.palette.themeTertiary, //get theme colors like this
    },
    label:{
      color: siteTheme.palette.white,
    },
    rootHovered:{
      backgroundColor: siteTheme.palette.themePrimary,
    },
    labelHovered:{
      color: siteTheme.palette.white
    }
  };

Then I set the styles prop of the component

<PrimaryButton
    styles={ButtonStyles} //pass the styles to the component here
    onClick={() => GoToPage(this.props.ButtonURL)}
    text={this.props.ButtonText ? this.props.ButtonText : 'BUTTON TEXT'}
/>

If you want to adjust to variants, or section backgrounds, check this blog post. https://learn.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/guidance/supporting-section-backgrounds

Which uses the ThemeProvider service.

Arknev
  • 141
  • 5
0

It seems to me like you are using the office-ui-fabric-react library. The getTheme method you import comes from there. I can't see how office-ui-fabric-react queries SharePoint for the current theme. It may be tracking its own. I would try getting the theme through the SharePoint component libraries. https://learn.microsoft.com/en-us/javascript/api/sp-component-base/themeprovider

jens
  • 2,075
  • 10
  • 15
  • Yes we looked into that too and were not able to get it working. Strange that there is absolutely no sample code out there considering that by now some people should have adopted this for their modern webparts (that should normally be thread aware) – dominikk May 14 '19 at 12:06
  • Looks like the "provider" approach is not working for full-screen WebParts. – Nikolay Aug 25 '20 at 15:40