Theming in Canvas Apps

In this post, Iā€™ll show you how to make branding your controls 10x easier after one step of creating custom theming in your app, where youā€™re then after able to brand all your controls by changing code in one place or by doing thingsā€¦ READ MORE [https://lewisdoes.dev/blog/theming-in-canvas-apps]
multicolored paint drippings
Photo by Alexander Grey on Pexels.com
In: Low Code Lewis Content šŸš€

In this post, Iā€™ll show you how to make branding your controls 10x easier after one step of creating custom theming in your app, where youā€™re then after able to brand all your controls by changing code in one place or by doing things like ā€˜selecting another themeā€™!

Creating the theme

So to create our themes, we could do this in our App OnStart property. You could alternatively do this in a timerā€™s OnTimerStart property and using the OnTimerEnd property use the Navigate() function to navigate to your intended homescreen. This way if your app doesnā€™t load your themes in time, which could well be the case, youā€™ve created time for this where it loads your themes and you donā€™t get any flicker between controls looking odd and them being rendered as they should be. Iā€™d definitely recommend doing this if youā€™re going to take this to the next level and store your users preferences in a data table so that you can do a LookUp() on the record their marked against and then reflect their preferences in your app when they come back to it.

Anywayā€¦ moving onto creating our theme. Some people like to use collections to do this, Iā€™m going to use global variables and records, because I find it easier to then use variables and the dot notation to access my theme values.

In my timer OnTimerStart property, Iā€™m going to set a global variable with a record holding all the colours Iā€™ll want to use in my theme.

// Theme settings - Colours
Set(
    gblColours,
    {
        DarkBlue: ColorValue("#1c2d47"),
        MidBlue: ColorValue("#0066AF"),
        LightBlue: ColorValue("#41B6EB"),
        DarkGrey: ColorValue("#4D5054"),
        MidGrey: ColorValue("#B1B3B3"),
        DarkYellow: ColorValue("#F7A800"),
        Green: ColorValue("#99BD12"),
        Purple: ColorValue("#9D1D96"),
        Turquoise: ColorValue("#71DBD4"),
        Orange: ColorValue("#F26703"),
        Teal: ColorValue("#005E62"),
        TransparentWhite: RGBA(
            255,
            255,
            255,
            0.5
        ),
        White: White
    }
);

Here you can see Iā€™ve set the global variable ā€˜gblColoursā€™ with a record that has a field for each colour I want to store. Then the value Iā€™m storing against each field is the hex value of the colour I want to use inside the ColorValue() function.

Now Iā€™ve built out the colours Iā€™m going to use, I can build out my theme in a similar way. Iā€™m going to set a global variable with a record that has a number of nested records for each of the controls Iā€™ll theme in my app! This is a short snippet of something I might use in a theme like situationā€¦

Set(
    gblTheme,
    {
            TitleLabel: {
                Weight: Bold,
                Size: 12,
                Colour: varColours.White
            },
            Text: {
                Weight: Normal,
                Size: 12,
                Colour: varColours.White
            },
            Form: {
                RequiredMarker: {Colour: varColours.Orange},
                Label: {
                     Size: 12,
                     Height: 22,
                     Weight: Bold,
                     Colour: varColours.DarkBlue
                },
                Field: {Outline: varColours.LightBlue}
            }
   }
)

Now Iā€™ve set the variable gblTheme with this data. All I need to do is head to the controls I want to style and instead of using hard coded values, reference the values in my variable.

For example, if I want to style a TitleLabel. Iā€™ll take the label control I want to use and instead of using ā€™12ā€™ in the Font Size property, Iā€™ll useā€¦

gblTheme.TitleLabel.Size

Now I can continue to use this same idea with all of my other controls, referencing the records and values in my gblTheme variable to style them.

Now if I ever need to change my theme I can do this by changing the code in one place and not needing to worry about changing every control.

Multiple Themes

But hold onā€¦ what if I want multiple themesā€¦ thatā€™s easy! All I need to do is use another variable and an Switch() statement to determine how my controls get themed.

Iā€™ll create a settings screen in my app with a dropdown that lets me change my theme. Using that dropdown Iā€™ll use the OnChange property to set a global variable with the choice I selected. Letā€™s say I chose ā€œLight Modeā€ in my dropdown and now Iā€™ve set the variable gblChosenTheme to ā€œLight Modeā€.

Now in my timer OnTimerStart property Iā€™ll use an If() statement and sayā€¦

Switch(gblChosenTheme, "Light Mode", Set(gblTheme, {the appropriate theme JSON},"Dark Mode",Set(gblTheme,{the appropriate theme JSON}, "Monochrome", Set(gblTheme,{the appropriate theme JSON},Set(gblTheme,{the appropriate theme JSON for light mode})

In this Switch() function, Iā€™m saying that if the chosen theme is equal to light mode, Iā€™ll set my gblTheme variable to the correct styling for a light theme. Then Iā€™m saying if itā€™s equal to dark mode, Iā€™ll set my gblTheme variable to the correct styling for a dark theme, and then Iā€™m saying that if itā€™s equal to monochrome Iā€™ll set gblTheme with the correct styling for a monochrome theme. Now my controls are being styled based on the theme Iā€™ve chosen, and Iā€™m also using a backup of light mode in case one of the values ā€œLight Modeā€, ā€œDark Modeā€, or ā€œMonochromeā€ isnā€™t matched in my Switch().

User Preferences

This is an important step with the way Iā€™ve implemented this here, but will also add some extra functionality. In your screen where youā€™re setting your theme, using the OnChange property of the dropdown, weā€™ll want to do a LookUp() on a table where we can store theme values. All we need to store is a string of the personā€™s email and a string of the value chosen for theme.

Weā€™ll create a new record using Patch() and set the theme to ā€œLight Modeā€ at the start of our timer OnTimerStart if there isnā€™t already a record found using LookUp() in our OnTimerStart.

Now using our OnChange of our dropdown on our screen to change the theme, weā€™ll patch that record and do a lookup against the users email using User().Email to pass the data in, to change the theme in that record to the one theyā€™ve chosen.

Now back to our timerā€™s OnTimerStart when we launch our app, in here when we do a LookUp() on our user preferences table, if in fact we do find a record, we wonā€™t create another one now, but weā€™ll take the value in the theme field and set our variable gblChosenTheme with this value.

Now further down in our syntax, weā€™re setting gblTheme in our Switch() using the chosen theme in gblChosenTheme.

Here we end up with functionality where our user can set the theme in their app and have it remembered for when they return šŸ™‚

Written by
Lewis Baybutt
Microsoft Business Applications MVP ā€¢ Power Platform Consultant ā€¢ Blogger ā€¢ Community Contributor ā€¢ #CommunityRocks ā€¢ #SharingIsCaring
Great! Youā€™ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to LewisDoesDev.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.