Lab 04: Button Variants - andreaswissel/design-systems-workshop GitHub Wiki

Hint: if you got lost, you can always check out the corresponding branch for the lab. If you want to start over, you can reset it by typing executing git reset --hard origin/lab-3

Lab

Now that we have our first component in place and made it function, we will want to apply some styling to it.

Design

  • Open the your Figma component library and select your previously created Button component and rename it

To rename the component, double click it in the layer explorer:

  • Next, go to the Design panel in Figma, and create a new component variant.

  • As we already learned that naming is important, we want to give accurate names to the variants

The naming syntax for variants follows a key value principle. Therefore, it's easy to rename them:

Double click the component variant in the explorer and rename Property 1 to Type, and rename Default to Primary. Do the same thing for Variant 2, but with the type being Secondary.

The button variants should now be visible when selecting the button component:

  • Now that we have specified our button variants, we need to style our new button variant, as well.

The only difference to building our very first button component lies in the component hierarchy. To style this specific variant, rather than the whole button component, you want to select the corresponding layer in the variant:

Now here comes a nifty little trick! I've prepared some Design Tokens for you to work with. We'll get learn what they are in just a second. For now, let's just accept this little gift, and style our button variant according to the following specs:

Background: Gray 100 Border: Gray 200 Foreground: Text Default

In your previously selected layer, you can already see some tokens iin the element explorer. Use the select boxes to change these values:

If there's no token (or "Style" as Figma calls them) present yet, you can explore them with this button:

Development

  • So we've prepared ourselves some design specs - but these need to be implemented in our code, as well!

Analog to the variant property we've just created, we want to implement an @Input on the Angular component, as well. We will follow the same nomenclature and implement after the label input. In the existing src/app/button/button.component.ts, we now want to add the following line, to add the type property:

import {Component, Input, OnInit} from '@angular/core';

@Component({
  selector: 'app-button',
  templateUrl: './button.component.html',
  styleUrls: ['./button.component.css']
})
export class ButtonComponent implements OnInit {
  @Input() public label: string = 'Button Label';
+  @Input() public type: 'primary' | 'secondary' = 'primary';

  constructor() { }

  ngOnInit() {
  }

}

With this new addition, we can now select our button type in Storybook:

This doesn't change anything in the UI yet, though. So let's build some CSS classes for our button types in src/app/button/button.component.scss (this is the same process as in the previous lab):

button {
  display: inline-flex;
  padding: 11px 16px;
  align-items: flex-start;

  border-radius: 5px;
  border: 1px solid var(--blue-700, #0357a3);
  background: #0085fc;
  box-shadow: 0px 2px 0px 0px rgba(255, 255, 255, 0.15) inset;

  color: var(--white, #fff);
  font-size: 13px;
  font-family: "Inter", Helvetica, Arial, Helvetica, sans-serif;

+  &.primary {
+    border: 1px solid var(--blue-700, #0357a3);
+    background: #0085fc;
+  }

+  &.secondary {
+    border: 1px solid var(--gray-200, #cbd0e1);
+    background: var(--gray-100, #e4e8f3);
+    color: var(--text-default, #041c31);
+  }
}

Following that, we created a conditional CSS class on the button element with the attr.class binding in src/app/button.component.html:

-<button>{{ label }}</button>
+<button [attr.class]="type">{{ label }}</button>

Switching back to Storybook, selecting the secondary type should lead to the following result:

  • Bonus level: The cherry on top

Try to extract the button types to a separate TypeScript Type, to make it more accessible in your IDE!

Self-check

Button SCSS

src/app/button/button.component.scss

button {
  display: inline-flex;
  padding: 11px 16px;
  align-items: flex-start;

  border-radius: 5px;
  border: 1px solid var(--blue-700, #0357a3);
  background: #0085fc;
  box-shadow: 0px 2px 0px 0px rgba(255, 255, 255, 0.15) inset;

  color: var(--white, #fff);
  font-size: 13px;
  font-family: "Inter", Helvetica, Arial, Helvetica, sans-serif;

  &.primary {
    border: 1px solid var(--blue-700, #0357a3);
    background: var(--blue-400, #0085fc);
  }

  &.secondary {
    border: 1px solid var(--gray-200, #cbd0e1);
    background: var(--gray-100, #e4e8f3);
    color: var(--text-default, #041c31);
  }
}
Button TS

src/app/button/button.component.ts

import { Component, Input, OnInit } from "@angular/core";

export type ButtonType = "primary" | "secondary";

@Component({
  selector: "app-button",
  templateUrl: "./button.component.html",
  styleUrls: ["./button.component.scss"],
})
export class ButtonComponent implements OnInit {
  @Input() public label: string = "Button Label";
  @Input() public type: ButtonType = "primary";

  constructor() {}

  ngOnInit(): void {}
}
Button HTML

src/app/button/button.component.html

<button [attr.class]="type">{{ label }}</button>

Hint: if you got lost, you can always check out the corresponding branch for the lab. If you want to start over, you can reset it by typing executing git reset --hard origin/lab-4

⚠️ **GitHub.com Fallback** ⚠️