style & theme options in canvas (part 2)

If you read through part 1 of the style & theme options series, then you may have come to the conclusion that a Style Guide Screen is not the method you want to use to add a custom color theme to your canvas apps, since you may be concerned about the cross-screen linking performance issue.

As we explore a few other options in part 2, another area of concern is how flexible the color theme is to future changes. Let’s review an example using the style guide screen from part 1.

flexibility: another consideration

When I put together the style guide screen, I set all of the following properties to SecondaryColor.Fill:

  • btnTemplate_Secondary.Fill
  • btnTemplate_Primary.HoverFill
  • txtTemplate.HoverFill
  • cmbTemplate.SelectionFill
  • cmbTemplate.PressedFill

It’s easy enough to change the color of all of these properties at once: I just have to update the swatch rectangle SecondaryColor.Fill, and voilà! New theme is implemented!

look at that bulk recoloring action!

But what if I wanted to individually change the color of the cmbTemplate.SelectionFill property, without affecting the colors of the other components?

better: style collection

My go-to method of managing colors within canvas apps is a Style Collection. (Alternatively: Style Variables. The syntax is moderately different, but end result is more-or-less the same.) Declared on App Start, the collection / variable set is available globally throughout your app without any performance drag.

And, since you’re creating your color theme through canvas app code, it becomes a great deal easier to control the colors at a granular level! The code can easily be copied and pasted to create color value entries in the collection for every color property your app requires with a minimum of manual effort.

how to implement

  1. In the App.OnStart property, declare and set a collection describing your color theme(s). The collection code you write could be as high level or detailed as you like, depending on your needs.
    • ❗ Only declaring a high level color theme will not address the flexibility issue described above!
    • You could take this all the way down to creating a separate collection for each type of component, as shown in the below code snippet. (Or even nested collections, if you dare!)
high level color theme
ClearCollect(
     StyleCollection,
     {
         Name: "PrimaryColor",
         Value: "#75adaf"
     },
     {
         Name: "SecondaryColor",
         Value: "#a6f1f3"
     },
     {
         Name: "TertiaryColor",
         Value: "#373737"
     }
 )
detailed level color theme
ClearCollect(
     SecondaryButtonStyle,
     {
         Name: "Fill",
         Value: "#a6f1f3"
     },
     {
         Name: "Color",
         Value: "#555555"
     },
     {
         Name: "HoverFill",
         Value: "#a6f1f3"
     },
     {
         Name: "HoverColor",
         Value: "#ffffff"
     }
 )
  1. Create your app components.
  2. Set the color properties of your components by looking up the desired color value in the collection.
    • high level example:
      • ColorValue(LookUp(StyleCollection, Name = "SecondaryColor").Value)
    • detailed level example:
      • ColorValue(LookUp(SecondaryButtonStyle, Name = "Fill").Value)
    • Make sure to include all color properties, including the Hover, Pressed and Disabled states as well as special properties like chevrons.
  3. Start building your app. For each new component, use the color value lookup code instead of manually setting the color properties.
    • 💡 You could still use a style guide screen and component templates to make this easier. When you need a component, copy it from your template screen. The key difference here is that your components are independent, with no direct references to other screens. When you’re done building your app, you can simply delete the template screen.
can I use RGBA values instead of hex?

You’re better off inserting hex values (# and all) as text in your collections, and wrapping the ColorValue() expression around your LookUp() to convert them. While it is possible to use RGB values and the RGBA() expression, it’s quite impractical:

I don’t really feel like writing nested collections to individually hold onto the red, blue, green and alpha values of each color in my theme— do you?

collections vs variables

As I mentioned, you can use Style Variables in the same manner as collections to achieve similar outcomes. For best results, you’ll declare global variables on app start like this:

Concurrent(
     Set(
         SecondaryButton_Fill,
         "#a6f1f3"
     ),
     Set(
         SecondaryButton_Color,
         "#555555"
     ),
     Set(
         SecondaryButton_HoverFill,
         "#a6f1f3"
     ),
     Set(
         SecondaryButton_HoverColor,
         "#a6f1f3"
     )
 )

Note: Wrapping all these variable expressions in Concurrent() is a best practice for app start performance, and I recommend you use it whenever you have independent statements in your code.

This will streamline the necessary color property code to simply: ColorValue(SecondaryButton_Fill)

Whether you go for a collection or set of variables will largely depend on the complexity of your color theme and your preferences. Collections are better organized if you need a very detailed theme and/or require multiple themes for components within the same app. Variables are a little easier to work as they have less “syntax overhead” when writing the formulas.

downsides

Combining the component template concept with a style collection or variable set relieves most of the pain points we uncovered with the style guide screen approach. However, there are still a few things to consider:

1. Future Updates

We are able to solve the issues of changing color themes in the future by writing robust collections for each color property, but we still have to open the canvas app in order to make any changes to those colors. If your company has multiple brands and multiple color themes, every canvas app you create needs to have the style collection code added to App.OnStart— and it needs to be maintained!

This may work well for a standalone app or one that does not need to follow a standard brand theme. But for larger scale production apps, when marketing changes the brand colors, you’ll need to update your app, too.

2. “Uncustomizable” Elements

To the Power App community’s great dismay, there are some component color properties which are not exposed in the App Studio. Without further care or intervention, these component colors can clash with your beautiful custom color scheme.

I went through each and every color property for this date picker component to reference my custom theme. There were no options to control the color of the calendar itself!

Infuriatingly, the date picker calendar colors can be changed by selecting a different out-of-the-box theme! However, the theme applies globally across your entire app and will override any color properties you did not manually set.

Note: the product group marked this idea as “PLANNED” as far back as Aug 2018… there are several duplicate ideas in the community forum, but you can vote on the custom theme idea here.

where did all that standard blue come from?!
applying this theme put my app into dark mode 😐

best: style data source

One intriguing idea for managing the future updates and maintenance of your canvas app theme is bringing in external data sources. Whether you’re using OneDrive for Business, SharePoint, Dynamics 365, Microsoft Dataverse, Salesforce.com, Azure SQL or something else for your business data, one thing canvas apps excel at is hooking in data sources. Last I checked, there were more than 400 standard or premium connectors available, so any maker at any organization should be able to leverage this option.

The idea is the same as the style collection or variable set, except that instead of declaring and setting the data manually within the app, you’re maintaining the collection list in an external data source.

This opens up a delightful range of new possibilities!

  • Do you have multiple themes that might vary based on conditions like the user logging into your app, the device location or even the time of day?
  • Will your color themes be often changed throughout the year, or new themes added?
  • Does your organization need to separately manage the permissions of app makers and brand managers (marketing team)?
  • Do you have a large number of apps to maintain which all need color themes?
  • Do you want to offer multiple color theme options to your users, and let them save their preference?

These requirements would be a headache to manage with a standard style collection. With an external data source, however, you can add layers of complexity without creating overly complex canvas apps. I’ll explain an example using Microsoft Dataverse, but the same concepts can easily be applied to other data sources.

how to implement

  1. In your data source, model the color theme data. Include attributes based on your conditional requirements.
Column NameData TypeDefinition (Example)
Attribute NameString/Primary FieldName of the canvas app attribute (SecondaryButton_Fill)
Color ValueStringColor value in hex code format (#a6f1f3)
Color Theme NameStringName of your color theme (Joy’s Teal Theme)
Region / Business UnitLook Up to other tableRegion where the theme is applied (West Region)
For example, I could use this data model to conditionally apply Joy’s Teal Theme to users who belong to the West Region Business Unit.
  1. Add the data source into your canvas app.

  1. In your App.OnStart code, fetch the appropriate color theme based on your conditions.
    • With your data sources connected, you can leverage sources like the Office 365 Users connector or the Users table in Dataverse to write the logic.
    • 💡 I recommend storing these in a collection rather than directly calling the external data source with LookUp() expressions on all of your components. This will cut down on API calls when your users navigate between screens and will be more performant.
ClearCollect(
     ColorTheme,
     Filter(
         Styles,
         'Color Theme Name' = "Joy's Teal Theme"
     )
 );
  1. Continue building your app following the pattern described in the Style Collection section.

extra credit: branding template

But what about the date picker?

Fellow Power App blogger Sancho Harker, otherwise known as iAm_ManCat, cracked this one for us.

He deconstructed the .MSApp file that is created when you export your canvas app and save the file locally. He did a little surgery on the file package, found the Theme JSON and painstakingly located each and every color property in the JSON schema. The result is over 3,000 lines of code that allows you to easily create your own app theme (not just a style collection) with control over colors for even the date picker, the pen input and other components we can’t customize manually.

Sancho’s method combines the best of the style guide screen, with what he calls the “Template Tester”, allowing you to visualize your theme as you make changes to the colors; and the style collection, with a collection already created for you leveraging his app assets. His efforts allow us to go a step further, because he has hardcoded all default color properties to variables on the back-end.

The best benefit of his method is that, after setting your color theme, all new components have the proper colors when they are inserted. No need to manually create & copy template components!

The drawback is that it does not leverage an external data source for the color theme, so you aren’t able to get the flexibility described in the Style Data Source section.

Check out his blog post detailing the effort and access the Branding Template V2 assets to get started.

According to Sancho’s blog, he may be releasing a V3 sometime soon. If the links change, I’ll try to remember to update them here.

don’t forget: custom components!

While I won’t get into detail about them here, I would be remiss if I didn’t mention custom components and their impact on the style & color theme topic.

Organizations which want to manage many canvas apps while maintaining consistent branding can leverage custom components. This allows common items like headers, menus, sidebars and buttons to be created and updated individually, generally by a centralized team (Marketing and/or IT). These components can be imported as managed components (soon to be replaced by component libraries) into other canvas apps. App makers receive a notification when their managed components have published changes so they can update their component versions.

conclusions

The takeaway: there are many different options for implementing your own custom color themes and branding within canvas apps.

The right one to choose depends on your app requirements, your organization’s structure, your skill level and your preferences.

Hopefully you now have all the information you need in order to choose wisely!

One thought on “style & theme options in canvas (part 2)

Add yours

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 )

Google photo

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

Twitter picture

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

Facebook photo

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

Connecting to %s

Blog at WordPress.com.

Up ↑

%d bloggers like this: