In one of my current projects, we’re working on a canvas app where user experience is an essential part of the project. We teamed up with a designer to make sure that the app fits into the company’s styling guidelines and that the UI was as intuitive and attractive as possible. One of the elements present in the resulting design is a button with an icon on it in addition to the label.
In the standard button control, it’s not possible to add an icon. If we just added the icon on top of the button, the colors will differ when hovering over the button or the icon which is not ideal for user experience. Since we didn’t want to create a custom component with code to add the possibility of an icon, I created a button component using only standard controls.
The resulting button will look and behave like this:
Keep reading for the steps to create this button!
Buttons can be used for many different things in an app: submit a form, navigate to another screen, apply a filter to a gallery, etc. Typically, when a button is pressed, an action needs to happen. Since canvas components currently don’t support specifying actions as their inputs or outputs, we are limited in what we can do with a button component. In this project’s requirements, the buttons would be used to navigate to a different screen.
Creating the component
💡 It’s not required to create the button as a component, but I prefer to do this to have less controls in my actual app later on.
You can create the component in any canvas app you have or in a dedicated component library. After creating the component, I’m renaming the it to btnNavWithIcon so it’s easily identifiable when I want to use it in my app. I’m also changing the height and width to a commonly used button shape and size.
I am then adding the four controls I need to create the button: the background button (btnBottom), a label (lblNavButton), a random icon (icnNavButton) and the top button (btnTop). The reason I’m adding two buttons is to make sure that the top button (which will be transparent) and background (which will have a color) will be exactly the same shape. At this point, it doesn’t matter where they are placed inside the screen since that will all be determined dynamically. What is important is that the top button control is in front so that that can actually be selected when the component is used in an app. We can see which control is at the front of the component in the Tree view (higher position in the tree = higher layer in the app/component).
I’m defining three custom input properties for my control:
- Label (text): the label that will be visible in the final button
- Icon (text): the icon that will be used
- Screen (screen): the screen to navigate to when the button is pressed
The next thing to do is link these input properties to the controls in our component, remove the labels from the button controls and disable the bottom button.
- Set the “Text” property of lblNavButton to btnNavWithIcon.Label
- Set the ‘Icon” property of icnNavButton to btnNavWithIcon.Icon
- Set the “OnSelect” property of btnTop to Navigate(btnNavWithIcon.Screen, ScreenTransition.None)
- Set the “DisplayMode” property of btnBottom to DisplayMode.View
- Set the “Text” property of btnTop and btnBottom to “”
Let’s complete the basic functionality and styling of the button as well.
- Set the size of btnTop to the size of the component
- Set the “X” and “Y” properties of btnTop to 0
- Set “Height”, “Width”, “X” and “Y” of btnBottom to the corresponding properties of btnTop
- Resize and position the icon and label so they fit nicely inside the component
- Set “Fill” of btnTop to Transparent
- Set “HoverFill” of btnTop to RGBA(255,255,255,0.1) – This is 90% transparent white, meaning the color behind it will be about 10% lighter
- Set “PressedFill” of btnTop to RGBA(0,0,0,0.1) – This is 90% transparent black, meaning the color behind it will be about 10% darker
The last 3 properties will make it appear that the icon and label are part of one button, since their color will change together with the background color (the fill color of the bottom button).
The button will look like this:
💡 You can test the component by setting the input properties you defined using the formula bar. In this case, I’ve set “Icon” to Icon.Settings (without quotation marks) and “Label” to “Settings”.
Styling the button
To determine the styling of the button, there are plenty of options. You can fix colors, position and size of the icon and label inside the button, you can make their position and size dynamic based on the height and width of your component, or you can specify additional input properties so that whoever will use your component has control over it.
In my case, I’m choosing a dynamic styling based on user inputs. This means I need to add a couple more input properties for the location and size of my controls: IconLocation, IconSize and FontSize. I’m also adding two color input properties: ButtonFill and TextColor. For the IconLocation and IconSize, I’m specifying the possible values in the description: Top, Bottom, Left and Right for location and Small, Medium and Large for size.
To apply the styling on the controls, we first need to decide what we want the styling to be. Colors is easy, they will be defined when someone adds the control to their app. Apply the below settings to btnBottom, icnNavButton and lblNavButton.text
But what does “Top” or “Left” mean? And what size is “Large” compared to “Small”? I’m using the following definition:
- If the position of the icon is “Top” or “Bottom”, the label and icon will be centered inside the component
- Horizontal margins are 10% of the width of the control, vertical will be 10% of the height of the component
- “Small” means the icon’s height and width is 30% of the minimum of height and width of the component, “Medium” 50% and “Large” 70%
- Default position is “Left” and size “Medium”
Let’s break this down for the “X” property of the icon.
- If the position of the icon is “Top” or “Bottom”, the center of the icon should be in the center of the button. Using the below image, we can work out what that means in terms of known properties.
- If the position of the icon is left the margin compared to the left side of the button should be 10% of the width of the button. This translated directly to the X-coordinate of the icon.
- If the position of the icon is right, the margin compared to the right side of the button should be 10% of the width of the button. We can again use an image to figure out what this means in terms of known properties.
Bringing these three together, we get the following formula for the X-coordinate of the icon.
By not specifying “Left”, this will act as the default location of the icon and will also work if no or an incorrect value is specified.
Using similar reasoning and the styling rules defined, the remaining position and size properties of the icon and label can be specified.
That’s it! The button component is now ready to be used!
We can easily test the resulting component by changing the input properties using the formula bar. Changing height, width and icon position could yield the result in the following animation.
We have successfully created a button component with a label and an icon with a couple of styling options to make it flexible. If we add this button to an app and specify the “Screen” property we can navigate to that screen by pressing the button. In the below animation I have created a simple test app with 3 screens and some buttons to navigate between them.
I hope this helps in creating your own custom button component with an icon. Good luck!