Adding common components. Card, Button, Input, List, ListItem
Using previously configured Storybook in this lesson we will create and prepare a few common components that later we’ll use in apps.
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
This lesson preview is part of the Next-Level Angular Apps with NX course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to Next-Level Angular Apps with NX, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

[00:00 - 00:13] In this lesson, we will create the most of reusable components that we will later use in the lessons. Before we start, we need to add styles to our new Storybook application and then configure Storybook application to use them.
[00:14 - 00:30] To do this, go to styles.css and paste styles that I provided. In the next step, go to that Storybook directory in Storybook application, open preview.ts and import that style, adding Style Loader and CSS Loader.
[00:31 - 00:42] The thing that you see on the screen right now is inline Webpack configuration for this file. So it will compile size CSS to CSS and then we'll add it to Storybook instance.
[00:43 - 00:54] If Style Loader is not installed, you can simply add it using yarn at -D, Style Loader. So you will get additional line in FilePacketJSON called Style Loader.
[00:55 - 01:05] Okay, so now it's time to run Storybook. To do this, we need to execute comment. Yarn and X Storybook as a target for application Storybook.
[01:06 - 01:13] It looks strange because we repeat Storybook word, but this is how it works. We have target Storybook for application Storybook.
[01:14 - 01:21] So let's again execute it and check if it works. As you can see, Storybook started in 15 seconds.
[01:22 - 01:26] So let's check how it looks like in the browser. And of course, we don't have any Story.
[01:27 - 01:38] So let's start by creating the first one for a button component. And I will first create Story and then I will start implementing my component.
[01:39 - 02:05] I want to work similar to Test So in app directory in StorybookedSource, I'm creating a new directory called " button". And then I will create a new file called "button_stories.ts".
[02:06 - 02:14] Okay, so I will implement the Story and then I will walk you through the code so you will check out how it works. So in the Story file, we have to import.
[02:15 - 02:34] I'm importing meta from Storybook Angular and I'm importing Storybook button component that I have just created as convenient way of presenting Storybook components. So we have a meta of button component that is using Storybook button component and a very simple component function at the end.
[02:35 - 02:46] The main of code is in Storybook button component.ts. So I have a new component that I'm using to present everything that I want in Storybook in the way I like.
[02:47 - 03:01] So I have a blog here and I'm using "shirt component" with "click me" text inside. And then I have a second blog where I have my shirt component with Unicode arrow for back button or something.
[03:02 - 03:10] This component, this Storybook button component is used only for presentation in Storybook. Let's check how it looks like.
[03:11 - 03:16] So as you can see, we have two buttons. Both of them, they have button works text inside.
[03:17 - 03:33] So it's because our button is not implemented yet. So now we can go to our "leap" directory, "shirt components" button, "source" and inside of "leap", we have our component and we need to edit it.
[03:34 - 03:47] So I'm going to do this right now and again, I will walk you through the code. I've removed most of the files that were unnecessary for this component and I decided to put everything in one file so it's easier to read.
[03:48 - 04:10] So we have a standalone component with without style encapsulation, we've selected a "shirt button" and it's a simple button from native HTML with ng-content inside. Every that most of the styles come from that global styles.css file that I provided.
[04:11 - 04:16] So let's check how it looks like after the change. And as you can see, we have our buttons.
[04:17 - 04:24] First one is with "click me" text and second one with arrow. So button component is done and we can go to the next component which is card component.
[04:25 - 04:35] So similar to button, I have two files. I have card stories.ts file that is very simple, it's only meta and again a simple renderer for component.
[04:36 - 04:47] And then I have my storybook card component that I'm using to present everything that I want. As you can see, it's a simple blog with "shirt cards" inside.
[04:48 - 04:56] We can check how it looks like after the change. So we have our card component and at the moment it looks empty.
[04:57 - 05:02] So we need to add implementation. So my implementation is a bit more complicated than a button.
[05:03 - 05:07] So first of all, let's start with the template. I have an image which is optional.
[05:08 - 05:14] You can provide it or not. And then I have a blog with "class card" body and then ng-content.
[05:15 - 05:26] So basically card is a blog where you can have an image as a heading and then you can have any content you want. And I have two inputs.
[05:27 - 05:32] First one is of course image. And the second input is active so card can be active and not active.
[05:33 - 05:39] So let's check how it works on the storybook. And as you can see, we have all the options here.
[05:40 - 05:46] We have basic card without any additional classes and so on. We have a basic card with image.
[05:47 - 05:54] We have a card that has component inside of the content. And we have an active card with that shadow.
[05:55 - 06:10] Please remember that all these styles, everything that I want to show on the storybook is in that storybook card component.ts. So I have a basic card here, card with an image, card with an image and div inside.
[06:11 - 06:17] And of course I have that shared card with active flag untrue. The next component is list component.
[06:18 - 06:26] And again, I will create a code and then I walk you through it. So let's start with storybook list.component.ts file.
[06:27 - 06:34] So my list will have a wrapper component like here. So I have shared list.
[06:35 - 06:41] And then I will put inside shared list item. I have created this component in list package.
[06:42 - 06:52] So if we scroll down to the list, you can see that I've added a new file and it 's empty at the moment. And then you need to export it from index.ts.
[06:53 - 07:01] So index.ts is that public API of the package. If you're going to use something outside of the package, you have to export it from index.ts.
[07:02 - 07:10] So let's go back to the storybook list component.ts. So as you can see, in the list item, you can put anything you want.
[07:11 - 07:17] So probably you will use ng-content once again here. And as you may notice, it's nothing really complicated.
[07:18 - 07:27] So I will add necessary code to shared list and shared list item components right now. As you can see, list component is almost empty.
[07:28 - 07:37] All we have is ng-content here, but I'm using this wrapper component to add necessary styles for list. So it's important.
[07:38 - 07:51] Again, all styles are in that global style.css file. List item is a bit more complicated.
[07:52 - 07:54] So again, I'm using ng-content because you can put anything you want inside of list item. So here is the important part.
[07:55 - 08:04] I'm preventing usage of shared list item component outside of list component. So you can use it only inside of the list component.
[08:05 - 08:22] I'm injecting optional list component and I will warn user that list item component should be used only inside of list component. If you have ever wondered how to access a parent component from the child, easiest way is to inject it.
[08:23 - 08:30] Like here. And again, let's check how it works in the storybook instance.
[08:31 - 08:36] As you can see, it's a very simple list. Nothing really fancy or complicated, but it works.
[08:37 - 08:44] You probably noticed that the pattern component, card component, list component are extremely simple. Most of the work is done by styles.
[08:45 - 08:49] And you may wonder, do we need that simple components? And in my opinion, yes, we want them.
[08:50 - 08:57] First of all, you reduce the code repetition. You don't need to add CSS classes, every button that you have and so on.
[08:58 - 09:13] The second reason is that it's easier to work with designers because you provide them a small building box and you can say that these are the buttons that we are going to use. And the final reason why these components are so simple is the fact that I just like to have simple components.
[09:14 - 09:18] I think it's easier to maintain them. It's easier to keep them in the same repo.
[09:19 - 09:30] And the chance that you will generate some kind of technical depth with that simple components is really small. So in the next lesson, we're going to focus on more complex components.