I love 🌈colorful apps! To create beautiful apps, also the self created code components must align to the app theming. Recently the docs got extended with explanations on how to use theming , and we’ve got an example ho wto use it Modern theming API.

It is a preview feature, but I had to try it out, and I’ve chosen to apply the theming to my ToDo dataset example, which is based on Fluent UI v9. In the docs (links above) there are also explanations on how to convert the theme and use it with Fluent UI v8, but this is not the subject of this blog.

Theming in Canvas Apps/ Custom Pages

If you are aware of theming possibilities in Power Apps (Canvas Apps and Model-Driven App) you can skip until the fun part: about applying theming to PCFs.

In Canvas Apps and Custom Pages we can enable the Modern Controls in App (or Page) settings.

That will allow us to use the modern controls on which we can apply one of the available themes. The modern controls are based on Fluent 2 design system.

App showing the PCF-Theming example and a few more controls where the Steel Theme is applied

Reza Dorrani made a post, where we can see even more themes (also SharePoint and Teams themes) (source):

You can find here more details about the modern controls and theming on Canvas Apps (and Custom Pages)

Theming in Model-Driven Apps

For model-driven apps there are two ways to apply theming.

For classic controls in model-driven apps, we had since quite a while theming customization (classic).

Apply classing theming on classic look

When we switch to “new look”, there is a new theming available. The modern theming for model-driven apps is based on a XML WebResource which we can upload and apply as a setting for your app. Unfortunately for now only the App Header theming can be defined. You can find more details about modern themes here

Defining custom theme for App Header in model-driven apps (New Look)

Apply theming to PCFs using Fluent UI React v9 (Fluent 2)

Using theming in PCFs is very easy. We get the current theming by simply reading it from the PCF context.fluentDesignLanguage:

const myTheme = context.fluentDesignLanguage.tokenTheme;

To use it with Fluent UI v9 components, we just wrap the component inside a “FluentProvider”. For instance, to apply the Theming to a DataGrid from Fluent UI React v9, we just need:


   
    //......
   

And here is the result in a Canvas App/Custom Page:

Applying the “Red” theme to my ToDo dataset PCF using Fluent UI v9 DataGrid
Switching to Green theme

And this is my ToDo PCF on a Model-Driven form (since with modern controls we can define only the App Header, the theming provided is the same with the standard controls):

ToDo dataset PCF
Power Apps Grid

Define your own theme

Let’s have a look how this context.fluentDesignLangauge is looking like.

We are using the “tokenTheme” which is of type “Theme”

import {  
  Theme , 
} from "@fluentui/react-components";

But we see there also the “brand”, which is a list of 16 colors. And that’s because of the way the Fluent UI React v9 (Fluent 2) works. Have a look to the Theme Designer for Fluent UI v9. You pick one color, and the Theme Designer is defining a palette of 16 colors

When we click on “Export”, we get all 16 colors (BrandVariants), together with some other styles for light or dark mode

We can even preview the chosen theme in light and dark mode, using the CodeSandbox link

Generating a theme by using the BrandVariants

I’ve picked a color, and took the BrandVariants generated with the Theme Designer

const myNewTheme: BrandVariants = { 
  10: "#040204",
  20: "#1C141F",
  30: "#2F1F35",
  40: "#3F2848",
  50: "#50315C",
  60: "#613A70",
  70: "#724385",
  80: "#854D9B",
  90: "#9757B1",
  100: "#A467BC",
  110: "#AF78C4",
  120: "#BA89CC",
  130: "#C59BD4",
  140: "#D0ACDC",
  150: "#DABEE4",
  160: "#E5D0EB"
};

Using this palette, we can generate a theme with the function “createLightTheme”

import {  
  Theme , 
  createLightTheme, 
  createDarkTheme,
  BrandVariants
} from "@fluentui/react-components";

And the theme generated that way, can be used for the FluentProvider, just like I did with the theme provided from the context. Now I have a ToDo on a purple theme:

You can find here more details about customizing themes based on a Brand ramp here

Generating the Brand ramp, based on a “base palette color”

So we can generate the theme based on these color palette…but it’s a little hard to make the PCF customizbar using this Brand ramp. One way would be to define another dataset parameter for my PCF, and provide the colors using a Collection in PowerFX. But that doesn’t work in model-driven apps. Besides that, is not really nice. My target would be to be able to define a “Base palette color”, like the other “Modern controls” in Canvas Apps.

Base palette color for Badge component in Custom Page

The inspiration for this I’ve found in the CodeSandbox. The base idea is to use an npm library “tinycolor2”: https://www.npmjs.com/package/tinycolor2. This is a small, fast library for color manipulation. Using it, we can lighten or darken the color. This way we can generate the 16 colors for brand ramp. You cand find my implementation for generateBrandVariants here. I’m not sure which step to use for lightning/darkning , but I find my theme pretty close to what I wanted.

So my theme is generated now using

 createLightTheme(generateBrandVariants(basePaletteColor)) 

In my Custom Page I can have now two several themes: the app theme (ToDo PCF on the left side) and a custom color (the green one – on the right).

And now we can use custom themes in model-driven forms too, by defining the base color.

Customizing base palette color for ToDo PCF (I had issues with the modern form designer – but it could be because of other features I’ve defined for this PCF, which are available only in canvas apps), so I’ve used the classic customizing)
My ToDo PCF with a green theme, on a model-driven form

Generating brand ramp for dark mode

Right now we don’t have dark mode for apps, but I suppose we’ll get that in the future. For that I’ve created another parameter for my PCF “isLightTheme”. When I set it to false, I’ll generate the the theme using

createDarkTheme(generateBrandVariants(basePaletteColor)) 

Putting it all together would be

  const [myTheme, setTheme] = React.useState(theme);
  React.useEffect(() => {    
    setTheme(basePaletteColor!=null && basePaletteColor.length > 0 ? 
        isLightTheme ?
            createLightTheme(generateBrandVariants(basePaletteColor)) 
          : createDarkTheme(generateBrandVariants(basePaletteColor))
       : theme);
  }, [basePaletteColor, isLightTheme]);  

In the future, I guess we can use the context.fluentDesignLanguage.isDarkTheme to detect if the app is in dark mode (the isDarkTheme we saw using the developer tools above )

Experimenting dark mode for theme generation

The complete code for this blog can be found in my github project: ToDosDataGridFluent9

Conclusion

Out of the box, the platform provides now a theme for PCF. We just have to use it.

We can use the theme designer for Fluent UI React v9 to generate a custom theme. Or we can even generate a theme using a base color. My way of generation might be not perfect but I think it works pretty good already… and I’m sure there is more to discover on this subject. Looking forward for beautiful and 🌈 colorful apps.

Blog image was generated using Microsoft Designer