loading...
Cover image for 3 Reusable components with Angular and tailwindcss

3 Reusable components with Angular and tailwindcss

maurogarcia_19 profile image Mauro Garcia ・4 min read

In a previous post, I wrote about 4 useful snippets for tailwindcss.

As I mentioned on that article, when you're working with tailwindcss you will find certain scenarios where you could think "Too much duplicated code". But if you are working with any modern JS framework like Angular, you will drastically reduce this duplication by extracting reusable components.

So I thought it could be useful to show you how to do this using the same tailwindcss snippets from my past article.

1- Colorful notes

colorful notes

This component is super simple and will allow us to customize both color and content

// colorful-note.component.ts
@Component({
    selector: 'colorful-note',
    templateUrl: './colorful-note.component.html',
    styleUrls: ['./colorful-note.component.css']
})
export class ColorfulNoteComponent implements OnInit {

    @Input() color: string = "teal"
    @Input() title: string
    @Input() description: string

    constructor() { }

    ngOnInit() {
    }

}
<!-- colorful-note.component.html -->
<div class="bg-{{color}}-100 text-{{color}}-500 border-l-8 border-{{color}}-500 p-4 mb-2">
    <p class="font-bold">{{title}}</p>
    <p>{{description}}</p>
</div>

Usage

<colorful-note color="red" title="Note" description="Lorem ipsum dolor sit amet..."></colorful-note>
<colorful-note color="blue" title="Note" description="Lorem ipsum dolor sit amet..."></colorful-note>
<colorful-note color="green" title="Note" description="Lorem ipsum dolor sit amet..."></colorful-note>
<colorful-note color="yellow" title="Note" description="Lorem ipsum dolor sit amet..."></colorful-note>

2- Three columns card grid

Three columns card grid

For this component, I'm gonna use the Smart/Dumb pattern. If you don't know this pattern, please checkout this article.

TL;DR

  • Dumb component: It is a component that for received data (inputs), will always look and behave the same, possibly also producing other data
  • Smart components: It is not only dependant on its’ inputs, but also on some kind of external data (“the outer world”), which is not passed directly via @Input(). It might also produce some side effects that are not emitted through the @Output() interface

My smart component for this implementation will be called Grid component, and will we be used for:

  • Retrieving a list of articles
  • Displaying each article using the dumb component

Finally, my dumb component will be called Grid item component and will be used to render each article using the data received from the smart component.

What's really powerful about this dumb component is that it's super generic, so you'll be able to use it in other scenarios.

Grid component (Smart):

// Class used to transfer data between components
export class Article {
    title: string;
    description: string;
    imgUrl: string;
    link: string;
}

// grid.component.ts
@Component({
    selector: 'grid',
    templateUrl: './grid.component.html',
    styleUrls: ['./grid.component.css']
})
export class GridComponent implements OnInit {

    articles: Article[] = []

    constructor() { }

    ngOnInit() {
        this.getArticles()
    }

    getArticles() {
        // Get data and set articles...
    }
}
<!-- grid.component.html -->
<div class="flex flex-wrap mt-2 mx-2">
    <!-- Items -->
    <app-grid-item *ngFor="let article of articles" 
        [title]="article.title"
        [description]="article.description"
        [imgUrl]="article.imgUrl"
        [link]="article.link"
        class="w-full md:w-1/2 lg:w-1/3 px-2 my-2">
    </app-grid-item>
</div>

Grid item component (Dumb):

// grid-item.component.ts
@Component({
    selector: 'grid-item',
    templateUrl: './grid-item.component.html',
    styleUrls: ['./grid-item.component.css']
})
export class GridItemComponent implements OnInit {

    @Input() title: string
    @Input() description: string
    @Input() imgUrl: string
    @Input() link: string

    constructor() { }

    ngOnInit() {
    }

}
<!-- grid-item.component.html -->
<div class="shadow-md bg-white">
    <img class="h-48 w-full object-cover" [src]="imgUrl" alt="">
    <div class="flex flex-col p-4">
        <p class="text-lg">{{title}}</p>
        <p class="text-gray-600">{{description}}</p>
        <a [href]="link" class="self-end mt-4">Show more...</a>
    </div>
</div>

Buttons

buttons

Another simple and practical example. We will use only one component to setup content, color and style for our buttons

// button.component.ts
@Component({
    selector: 'app-button',
    templateUrl: './button.component.html',
    styleUrls: ['./button.component.css']
})
export class ButtonComponent implements OnInit {

    @Input() type: string = 'simple'
    @Input() color: string = 'teal'
    @Input() text: string
    constructor() { }

    ngOnInit() {
    }

    getStyles() {
        switch(this.type) {
            case 'simple': 
                return `bg-${this.color}-500 hover:bg-${this.color}-700 text-white font-bold py-2 px-4 rounded mb-2 border border-${this.color} mx-2`
            case 'outline':
                return `hover:bg-${this.color}-500 text-${this.color}-700 font-semibold hover:text-white py-2 px-4 border border-${this.color}-500 hover:border-transparent rounded mb-2 mx-2`
        }
    }

}
<!-- button.component.html -->
<button [class]="getStyles()">{{text}}</button>

Usage

<app-button text="Simple teal button"></app-button>
<app-button text="Outline teal button" type="outline"></app-button>
<app-button text="Simple red button" color="red"></app-button>
<app-button text="Outline red button" type="outline" color="red"></app-button>
<app-button text="Simple indigo button" color="indigo"></app-button>
<app-button text="Outline indigo button" type="outline" color="indigo"></app-button>

If you want to checkout the code, here is my github repo

GitHub logo mauro-codes / reusable-angular-tailwindcss-components

A collection of reusable components built with Angular and tailwindcss

Reusable components

This project was generated with Angular CLI version 8.0.3.

Development server

Run ng serve for a dev server. Navigate to http://localhost:4200/. The app will automatically reload if you change any of the source files.

Code scaffolding

Run ng generate component component-name to generate a new component. You can also use ng generate directive|pipe|service|class|guard|interface|enum|module.

Build

Run ng build to build the project. The build artifacts will be stored in the dist/ directory. Use the --prod flag for a production build.

Running unit tests

Run ng test to execute the unit tests via Karma.

Running end-to-end tests

Run ng e2e to execute the end-to-end tests via Protractor.

Further help

To get more help on the Angular CLI use ng help or go check out the Angular CLI README.

Discussion

pic
Editor guide