Feel free to skip this section if you’re only here for the code.
I designed this simple app using Figma.
Our color scheme is made up of foreground, background, primary, and error colors. Each color group has several lighter and darker variants of the base color.
For our light/dark themes, the foreground and background colors will simply swap.
Next up is to create the components. Since our app is pretty small, we only have a couple of components.
The nav component, which will let our user toggle the theme.
The tile component which will display coin info.
Putting it all together, we get our target designs.
We are going to scaffold our app using the Angular CLI. First, we need to install it.
npm install -g @angular/cli
Then create our app.
ng new project-crypto
And finally, generate a module to hold our theming logic.
cd project-crypto
ng generate module theme
Alright, time for the good stuff.
Let’s start by defining out initial CSS variables. We can set them initially to reflect our light theme. Since we want our theme to be global, I have defined it using the :root
selector, which will match the html
element. You could use the body
or some other high-level element here if you wish.
@import url("https://fonts.googleapis.com/css?family=PT+Sans:400,700");
@import url("https://fonts.googleapis.com/css?family=Inconsolata:400,700");
:root {
/* Colors */
--foreground-default: #08090a;
--foreground-secondary: #41474d;
--foreground-tertiary: #797c80;
--foreground-quaternary: #f4faff;
--foreground-light: #41474d;
--background-default: #f4faff;
--background-secondary: #a3b9cc;
--background-tertiary: #5c7d99;
--background-light: #ffffff;
--primary-default: #5dfdcb;
--primary-dark: #24b286;
--primary-light: #b2ffe7;
--error-default: #ef3e36;
--error-dark: #800600;
--error-light: #ffcecc;
/* Shadows */
--background-tertiary-shadow: 0 1px 3px 0 rgba(92, 125, 153, 0.5);
}
body {
background: var(--background-default);
}
html,
body {
margin: 0;
padding: 0;
font-family: "PT Sans", sans-serif;
}
styles.css
Next, let’s define our themes in TypeScript. These will later be used to toggle the theme by an Angular service.
Under our newly created theme
module, create a new file: theme.ts
export interface Theme {
name: string;
properties: any;
}
export const light: Theme = {
name: "light",
properties: {
"--foreground-default": "#08090A",
"--foreground-secondary": "#41474D",
"--foreground-tertiary": "#797C80",
"--foreground-quaternary": "#F4FAFF",
"--foreground-light": "#41474D",
"--background-default": "#F4FAFF",
"--background-secondary": "#A3B9CC",
"--background-tertiary": "#5C7D99",
"--background-light": "#FFFFFF",
"--primary-default": "#5DFDCB",
"--primary-dark": "#24B286",
"--primary-light": "#B2FFE7",
"--error-default": "#EF3E36",
"--error-dark": "#800600",
"--error-light": "#FFCECC",
"--background-tertiary-shadow": "0 1px 3px 0 rgba(92, 125, 153, 0.5)"
}
};
export const dark: Theme = {
name: "dark",
properties: {
"--foreground-default": "#5C7D99",
"--foreground-secondary": "#A3B9CC",
"--foreground-tertiary": "#F4FAFF",
"--foreground-quaternary": "#E5E5E5",
"--foreground-light": "#FFFFFF",
"--background-default": "#797C80",
"--background-secondary": "#41474D",
"--background-tertiary": "#08090A",
"--background-light": "#41474D",
"--primary-default": "#5DFDCB",
"--primary-dark": "#24B286",
"--primary-light": "#B2FFE7",
"--error-default": "#EF3E36",
"--error-dark": "#800600",
"--error-light": "#FFCECC",
"--background-tertiary-shadow": "0 1px 3px 0 rgba(8, 9, 10, 0.5)"
}
};
theme.ts
We can add as many themes as we like here. For now, let’s just stick with light and dark themes.
Our service will be responsible for: tracking the active theme, and updating the CSS variables based on the active theme.
We can use the CLI to generate our new service. Under /src/app/theme
run
ng generate service theme
import { Injectable } from "@angular/core";
import { Theme, light, dark } from "./theme";
@Injectable({
providedIn: "root"
})
export class ThemeService {
private active: Theme = light;
private availableThemes: Theme[] = [light, dark];
getAvailableThemes(): Theme[] {
return this.availableThemes;
}
getActiveTheme(): Theme {
return this.active;
}
isDarkTheme(): boolean {
return this.active.name === dark.name;
}
setDarkTheme(): void {
this.setActiveTheme(dark);
}
setLightTheme(): void {
this.setActiveTheme(light);
}
setActiveTheme(theme: Theme): void {
this.active = theme;
Object.keys(this.active.properties).forEach(property => {
document.documentElement.style.setProperty(
property,
this.active.properties[property]
);
});
}
}
theme.service.ts
Some things to note here:
getAvailableThemes
and setActiveTheme
functions to change the theme dynamically based on user input instead.The hard work is done. Now we just need to put our building blocks together. Well, actually, first we need to create the building blocks 😁. Let’s create the components.
We will start with the nav component. Again, we can use the Angular CLI to give us a head start.
ng generate component nav
import { Component, OnInit } from "@angular/core";
import {
faLightbulb as faSolidLightbulb,
faDollarSign,
IconDefinition
} from "@fortawesome/free-solid-svg-icons";
import { faLightbulb as faRegularLightbulb } from "@fortawesome/free-regular-svg-icons";
import { ThemeService } from "src/app/theme/theme.service";
@Component({
selector: "app-nav",
templateUrl: "./nav.component.html",
styleUrls: ["./nav.component.css"]
})
export class NavComponent implements OnInit {
faLightbulb: IconDefinition;
faDollarSign = faDollarSign;
constructor(
private themeService: ThemeService
) {}
ngOnInit() {
this.setLightbulb();
}
setLightbulb() {
if (this.themeService.isDarkTheme()) {
this.faLightbulb = faRegularLightbulb;
} else {
this.faLightbulb = faSolidLightbulb;
}
}
toggleTheme() {
if (this.themeService.isDarkTheme()) {
this.themeService.setLightTheme();
} else {
this.themeService.setDarkTheme();
}
this.setLightbulb();
}
}
nav.component.ts
Note: I have used Font Awesome for the icons on the nav bar. If you want to do the same, you will need to install Font Awesome for Angular.
The logic for our nav component is pretty straight forward. We set our icon depending on the theme on initialization (line 22). Then we set up an event handler to toggle the theme. You can see it’s usage in the HTML below.
<nav>
<fa-icon [icon]="faDollarSign"></fa-icon>
<h5 class="title secondary-font">ProjectCrypto</h5>
<fa-icon [icon]="faLightbulb" (click)="toggleTheme()"></fa-icon>
</nav>
nav.component.html
nav {
height: 4rem;
display: flex;
align-items: center;
padding-left: 1rem;
padding-right: 1rem;
background-color: var(--background-tertiary);
color: var(--foreground-quaternary);
font-size: 1rem;
}
nav .title {
margin-left: auto;
margin-right: auto;
}
nav.component.css
Notes on the nav component CSS:
Next, the tile component.
<div class="container">
<h5 class="name">{{ name }}</h5>
<h5 class="price">
<fa-icon [icon]="currencyIcon"></fa-icon>
{{ price | number }}
</h5>
<fa-icon
[icon]="faHeart"
(click)="onToggleFavourite()"
class="favouriteIcon icon"
[ngClass]="{ isFavourite: isFavourite }"
></fa-icon>
</div>
tile.component.html
.container {
display: grid;
grid-template-columns: 0.5fr 1fr 0.5fr;
align-items: center;
border-radius: 0.5rem;
background: var(--background-light);
color: var(--foreground-tertiary);
padding-left: 0.5rem;
padding-right: 0.5rem;
margin-bottom: 1rem;
min-height: 8rem;
box-shadow: var(--background-tertiary-shadow);
}
.container .name {
justify-self: start;
}
.container .price {
justify-self: center;
}
.container .icon {
justify-self: end;
}
.favouriteIcon {
font-size: 1.5rem;
}
.isFavourite {
color: var(--primary-default);
}
tile.component.css
Notes:
And that’s it! You now have the components and theme created. You can add the components to your base app component to wire everything up with some test data.
You can find the repo here.
Learn more about CSS Variables here.
Thanks for reading!
✅ 30s ad
☞ Angular (Full App) with Angular Material, Angularfire & NgRx
☞ Angular 7 with Angular Material and Firebase Cloud Firestore
☞ Angular 5 - A 3-Step Process to Master Angular for Beginners
☞ Angular 6 (Angular 2+) & React 16 - The Complete App Guide
☞ Angular Tutorial - Learn Angular from Scratch
☞ JavaScript Programming Tutorial Full Course for Beginners
☞ Learn JavaScript - Become a Zero to Hero
☞ Web Development Tutorial - JavaScript, HTML, CSS