3. Creating the button component using the cascading logic
Now, let’s get to work. Open a new design file in Figma and follow along with me. The first step is to create what I call a “base component”, which will have all the most basic elements of the button component. This first step will set the properties of size with 3 variants:
Step 1 —Base: To begin, create a frame, add a label, and an icon. You don’t need to pay attention to specific values, but you can follow the measurements in the image example above. To make the most of this method, add some properties and the crucial auto-layout feature. It’s also appropriate to use styles (color and text) here. If you want to make it exactly like in the example, follow the guide below:
First, create a frame of any size, add an icon (20x20px) to act as our
leading-icon, and a text (16pt body size/20pt line height) to be our
label. Keep in mind that the icon can be a component of its own, so you
can also add an instance swap feature.
Now, add the auto-layout feature (shift+A) and set these values:
- Space between items: 8px
- Horizontal padding: 24px
- Vertical padding: 10px
Set the following frame size constraints (at the top of the sidebar menu):
- Horizontal resizing: FIXED (to adjust to your own UI gridstyle)
- Vertical resizing: HUG
Inside the frame, select the icon frame, and in the sidebar menu panel
add the boolean property "show-leading_icon" in the layer section, so we
can choose whether the button will have a visible icon or not. You can
also add an instance swap property to the icon to change which icon will
Now, select the text, and in the layer section of the sidebar menu add
the boolean property "show-label" (so we can make icon buttons).
In the content section, add the text property "label_text" so you can
change the button label with ease
Now, we need to create two additional variants to establish the three different sizes. Set the button you created above as the “medium” sized one. Create a smaller and a larger version. Again, if you want to create it exactly like the example, follow the steps below:
In the "smaller" variant: set the size of the icon to 16x16px.
Set the text/label size to 14pt and line height to 16pt.
Set the vertical padding in the auto-layout to 8px.
Name the variant as "small".
In the "bigger" variant: set the size of the icon to 24x24px.
Set the text/label size to 18pt and line height to 24pt.
Set the vertical padding in the auto-layout to 12px.
Name the variant as "large".
Step 2 — Style: Now, let’s move on to our second step and begin with our cascading logic. Select any variant from the base component and copy it, pasting it to create an instance of it (make sure it’s an instance and not another component altogether; pasting it inside another frame usually helps). Now, select the instance you just copied and create a new component out of it (ctrl/cmd+alt+K), and name it “style”. The component’s layers should look like this:
Now things will begin to get interesting. In this new component, we will make some adjustments to the top layer and then some changes to the base component layer. Firstly, set the component auto-layout size constraints to horizontal = FIXED and vertical = HUG in the sidebar menu. Then, select the base layer inside the component and set the horizontal constraint to FILL (this will make sure the button will adjust to the horizontal size you set).
With these adjustments, the base component will fill the entire width of the parent container, allowing you to adjust the button width according to your grid, giving you more flexibility in terms of design. Additionally, the vertical size adjusts automatically according to the size of the selected variant, maintaining consistency in the vertical size as well.
After that, let’s create two different button styles: square and rounded. Simply create a new variant, make sure to select the base layer inside the component, and change the border radius to 200 (make it a big number so it’s rounded no matter the button size). Don’t forget to name the variants accordingly (“square” and “round”)
To finalize this step, let’s use another property: the newly added (and beta) “expose properties from nested instances”, and choose to show properties from the base instance. By doing this, you’ll be able to inherit the properties controls made in the base layer to the “style” component. Now, you should have something like the following:
I believe you can understand what’s happening now. The two button styles (square and rounded) are inheriting the size properties from the base component, without the need to explicitly create them.
Step 3 —Types and States: Our next and final step in the cascading ladder is to add types and states to our button component. To begin, do as in the last step and select a variant from our style component (it can be the rounded or squared one, it doesn’t matter), copy and paste it, making sure again it’s an instance and not a new component altogether.
Let’s create yet another component using the copied instance, naming it “button” (since it’s the last step, we need to give it the component’s true name). The layers should look like this:
Make sure to adjust the auto-layout constraints as we did in the last step: set the first/button layer horizontal constraint to FIXED and both layers inside (style and base) to FILL. Don’t forget to add the property “expose properties from nested instances” so you can easily control the inherited properties from the base and style components.
Going forth, we will create the different types of the component: contained, outline and text, and it’s states: idle, danger and disabled. So, create two new variant properties with the respective names: type which for the selected variant should be “contained” and state, which should be “idle”. Now, we will start creating the other states. Add a new variant and change it’s color to red, naming its state property to “danger”. Add another variant, name its state property “disabled”, change the button fill color to grey and the label/icon to a more darker grey (when dealing with disabled states, I usually change it’s opacity to 70%). The component should look like:
Right, now that we have established our states, copy one of the variants and name its type property to “outline”. To exact our changes and add the new type of the component, you will need to adapt it in the base layer, changing the icon and label/text color, removing its fill and adding a stroke of the same color (so, blue for the idle state, red for the danger state and grey for the disabled state). Create the 3 state variants for the outline type, so we can have our component with 6 variants:
Lastly, we need to create our final type variant: the text. Select all 3 outline variants, copy and paste it, renaming the type property name to “text”. Now, just remove the stroke of each one of the text type variants and voilà, your button component should be finalized:
Step 4 — What have we accomplished?: So, after all that effort, our component is ready to be used. Essentially, as stated in the beginning, we created a component with potential 54 variants but only using 14. But not only that, all changes you make to the base component will reverberate and be applied to the subsequent steps of the component. Feel free to experiment, add new elements and properties, or remove them, so you can observe the changes being applied as a cascade in real time.
Oh, and if you are using this component in a library file, just remember to hide the base and style components so only the final button component can be utilized. This will ensure that users of the library only have access to the final version of the component, making it easier for them to work with and reducing the risk of errors.