Play

Creating a UI Library

Let’s start by creating a UI library. We will create a new Angular library project.

Terminal window
ng g lib @app/ui

Creating stats component

The stats component will be a simple component that displays a list of pending and completed tasks.

Terminal window
ng g c components/stats --project=@app/ui --style=scss
stats.component.html
<div class="stats-container">
@for (item of list; track item) {
<div
class="stats-item stats-item-{{ item }}"
[class.done]="count()[item].done === count()[item].total"
>
<div class="stats-item-title">{{ item }}</div>
<div class="stats-item-value">
{{ count()[item].done }}
<span class="stats-item-value-total">/ {{ count()[item].total }}</span>
</div>
</div>
}
</div>

Exporting the component

projects/app/ui/src/public-api.ts
export * from './lib/components/stats/stats.component';

Script for library

Add below scripts in root package.json file.

package.json
{
"scripts": {
"prebuild": "ng build --project=@app/ui",
"watch:lib": "ng build @app/ui --watch --configuration development"
}
}

Then run npm run watch:lib to start watching for changes and rebuilding the library.

Applying Angular Material styles

stats.component.scss
@use "sass:map";
@use "@angular/material" as mat;
.stats-container {
display: grid;
border-radius: var(--mat-sys-corner-medium);
overflow: hidden;
grid-template-columns: repeat(1, 1fr);
margin: 1rem;
box-shadow: var(--mat-sys-level1);
@media (min-width: 960px) {
grid-template-columns: repeat(3, 1fr);
}
}
$priority-colors: (
low: (
background: var(--mat-sys-surface-container),
foreground: var(--mat-sys-on-surface),
),
medium: (
background: var(--mat-sys-secondary-container),
foreground: var(--mat-sys-on-secondary-container),
),
high: (
background: var(--mat-sys-error-container),
foreground: var(--mat-sys-on-error-container),
),
);
.stats-item {
padding: 8px 16px;
&.done {
opacity: 0.5;
}
}
@each $priority, $colors in $priority-colors {
.stats-item-#{$priority} {
background-color: map.get($colors, background);
color: map.get($colors, foreground);
}
}
.stats-item-value {
font: var(--mat-sys-headline-large);
letter-spacing: var(--mat-sys-headline-large-tracking);
}
.stats-item-title {
font: var(--mat-sys-title-medium);
letter-spacing: var(--mat-sys-title-medium-tracking);
margin-bottom: 12px;
}
.stats-item-value-total {
font: var(--mat-sys-title-small);
letter-spacing: var(--mat-sys-title-small-tracking);
}

Importing in app component

app.component.html
<main class="container">
<lib-stats [count]="count()"></lib-stats>
<app-todo-list></app-todo-list>
</main>

Taking care of density

1. Create a new file _stats.density.scss

Create a new file at projects/app/ui/src/lib/components/stats/_stats.density.scss and add the density mixin.

_stats.density.scss
@use "sass:map";
@mixin density($density) {
$spacing: (-1: 6px 12px, -2: 4px 8px, -3: 4px 8px, -4: 4px 8px, -5: 4px 8px);
$scale-spacing: map.get($spacing, $density);
.stats-item {
padding: $scale-spacing !important;
}
}

2. Export the density mixin from _index.scss

Create a new barrel file at projects/app/ui/src/_index.scss and export the density mixin.

_index.scss
@forward "./lib/components/stats/stats.density" as stats-*;

3. (Optional) SASS entry in library’s package.json

This is needed only if you’re planning to publish your library. Add below in projects/app/ui/package.json:

package.json
{
"exports": {
".": {
"sass": "./_index.scss"
}
}
}

4. Include projects path in angular.json

This change will make sure that all the styles from projects directory are included in the build process.

angular.json
{
"projects": {
"my-app": {
"architect": {
"build": {
"options": {
"stylePreprocessorOptions": {
"includePaths": ["projects"]
}
}
}
}
}
}
}

After above change, you will have to restart the dev server.

5. Use the stats density mixin

Now we can use the density mixin in the src/styles/_density.scss file.

_density.scss
@use "@angular/material" as mat;
@use "app/ui/src" as ui;
$density-list: (0, -1, -2, -3, -4, -5);
@each $density in $density-list {
.density-#{$density} {
@include mat.theme((density: $density));
@include ui.stats-density($density);
}
}
Next arrow_forward Adding More Colors We will learn how to add more colors to the theme.