style(navigation): implement basic navigation bar
This commit is contained in:
2385
package-lock.json
generated
2385
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -58,7 +58,7 @@ export const Theme = definePreset(Aura, {
|
|||||||
},
|
},
|
||||||
dark: {
|
dark: {
|
||||||
surface: {
|
surface: {
|
||||||
0: "#0a0a0a",
|
0: "#030303",
|
||||||
50: "#171717",
|
50: "#171717",
|
||||||
100: "#262626",
|
100: "#262626",
|
||||||
200: "#404040",
|
200: "#404040",
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
<app-background/>
|
<app-background/>
|
||||||
|
<app-navigation-bar/>
|
||||||
<router-outlet/>
|
<router-outlet/>
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
import { Routes } from '@angular/router';
|
import { Routes } from '@angular/router';
|
||||||
|
import { Home } from './pages/home/home';
|
||||||
|
import { About } from './pages/about/about';
|
||||||
|
|
||||||
export const routes: Routes = [];
|
export const routes: Routes = [
|
||||||
|
{ path: '', component: Home },
|
||||||
|
{ path: 'about', component: About },
|
||||||
|
{ path: '**', redirectTo: '', pathMatch: 'full' },
|
||||||
|
];
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ import { Component } from '@angular/core';
|
|||||||
import { RouterOutlet } from '@angular/router';
|
import { RouterOutlet } from '@angular/router';
|
||||||
import { ThemeSwitchService } from './core/service/theme-switch.service';
|
import { ThemeSwitchService } from './core/service/theme-switch.service';
|
||||||
import { Background } from "./core/components/background/background";
|
import { Background } from "./core/components/background/background";
|
||||||
|
import { NavigationBar } from "./core/components/navigation-bar/navigation-bar";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
imports: [RouterOutlet, Background],
|
imports: [RouterOutlet, Background, NavigationBar],
|
||||||
templateUrl: './app.html',
|
templateUrl: './app.html',
|
||||||
})
|
})
|
||||||
export class App {
|
export class App {
|
||||||
|
|||||||
73
src/app/core/components/navigation-bar/navigation-bar.html
Normal file
73
src/app/core/components/navigation-bar/navigation-bar.html
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<nav class="sticky top-0 p-[30px] flex flex-row justify-between relative z-5000">
|
||||||
|
<div class="logo grid place-items-center">
|
||||||
|
<span class="font-semibold text-3xl">BH</span>
|
||||||
|
</div>
|
||||||
|
<div class="navigation grid place-items-center">
|
||||||
|
@if (themeSwitchService.darkMode()) {
|
||||||
|
<ul class="relative hidden items-center space-x-1 rounded-full border border-black/10 bg-black/5 px-1.5 py-1 backdrop-blur-md md:flex border-white/10 bg-white/10">
|
||||||
|
<li class="relative list-none">
|
||||||
|
<a class="block px-4 py-1.5 text-sm font-light text-black transition hover:text-black/80 text-white/70 hover:text-white" routerLink="/">
|
||||||
|
Home
|
||||||
|
</a>
|
||||||
|
@if (isActive('/')) {
|
||||||
|
<ng-container *ngTemplateOutlet="activeNavItem"/>
|
||||||
|
}
|
||||||
|
</li>
|
||||||
|
<li class="relative list-none">
|
||||||
|
<a class="block px-4 py-1.5 text-sm font-light text-black transition hover:text-black/80 text-white/70 hover:text-white" routerLink="/about">
|
||||||
|
About
|
||||||
|
</a>
|
||||||
|
@if (isActive('/about')) {
|
||||||
|
<ng-container *ngTemplateOutlet="activeNavItem"/>
|
||||||
|
}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ng-template #activeNavItem>
|
||||||
|
<span class="bg-white/5 absolute inset-0 -z-5000 w-full rounded-full">
|
||||||
|
<div class="bg-white absolute -top-[9px] left-1/2 h-1 w-8 -translate-x-1/2 rounded-t-full">
|
||||||
|
<div class="bg-white/20 absolute -top-2 -left-2 h-6 w-12 rounded-full blur-md"></div>
|
||||||
|
<div class="bg-white/20 absolute -top-1 h-6 w-8 rounded-full blur-md"></div>
|
||||||
|
<div class="bg-white/20 absolute top-0 left-2 h-4 w-4 rounded-full blur-sm"></div>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</ng-template>
|
||||||
|
} @else {
|
||||||
|
<ul class="relative hidden items-center space-x-1 rounded-full border border-black/10 bg-black/5 px-1.5 py-1 backdrop-blur-md md:flex">
|
||||||
|
<li class="relative list-none">
|
||||||
|
<a class="block px-4 py-1.5 text-sm font-light text-black transition hover:text-black/80" routerLink="/">
|
||||||
|
Home
|
||||||
|
</a>
|
||||||
|
@if (isActive('/')) {
|
||||||
|
<ng-container *ngTemplateOutlet="activeNavItem"/>
|
||||||
|
}
|
||||||
|
</li>
|
||||||
|
<li class="relative list-none">
|
||||||
|
<a class="block px-4 py-1.5 text-sm font-light text-black transition hover:text-black/80" routerLink="/about">
|
||||||
|
About
|
||||||
|
</a>
|
||||||
|
@if (isActive('/about')) {
|
||||||
|
<ng-container *ngTemplateOutlet="activeNavItem"/>
|
||||||
|
}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ng-template #activeNavItem>
|
||||||
|
<span class="bg-black/5 absolute inset-0 -z-5000 w-full rounded-full">
|
||||||
|
<div class="bg-black absolute -top-[9px] left-1/2 h-1 w-8 -translate-x-1/2 rounded-t-full">
|
||||||
|
<div class="bg-black/20 absolute -top-2 -left-2 h-6 w-12 rounded-full blur-md"></div>
|
||||||
|
<div class="bg-black/20 absolute -top-1 h-6 w-8 rounded-full blur-md"></div>
|
||||||
|
<div class="bg-black/20 absolute top-0 left-2 h-4 w-4 rounded-full blur-sm"></div>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</ng-template>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class="options flex flex-row gap-[10px]">
|
||||||
|
<div class="dark-mode size-[50px]">
|
||||||
|
<fa-icon [icon]="faMoon"/>
|
||||||
|
</div>
|
||||||
|
<div class="language size-[50px]">EN</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="blur blur1"></div>
|
||||||
|
<div class="blur blur2"></div>
|
||||||
41
src/app/core/components/navigation-bar/navigation-bar.scss
Normal file
41
src/app/core/components/navigation-bar/navigation-bar.scss
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
nav {
|
||||||
|
.options > div {
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
transition: border .5s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--surface-100);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
border-color: var(--surface-500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.blur {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 120px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blur1 {
|
||||||
|
z-index: 10;
|
||||||
|
backdrop-filter: blur(3px);
|
||||||
|
mask-image: linear-gradient(to top, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 40%, rgba(0, 0, 0, 1) 70%, rgba(0, 0, 0, 0) 100%);
|
||||||
|
-webkit-mask-image: linear-gradient(to top, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 40%, rgba(0, 0, 0, 1) 70%, rgba(0, 0, 0, 0) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.blur2 {
|
||||||
|
z-index: 20;
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
|
mask-image: linear-gradient(to top, rgba(0, 0, 0, 0) 60%, rgba(0, 0, 0, 1) 85%, rgba(0, 0, 0, 1) 100%);
|
||||||
|
-webkit-mask-image: linear-gradient(to top, rgba(0, 0, 0, 0) 60%, rgba(0, 0, 0, 1) 85%, rgba(0, 0, 0, 1) 100%);
|
||||||
|
}
|
||||||
29
src/app/core/components/navigation-bar/navigation-bar.ts
Normal file
29
src/app/core/components/navigation-bar/navigation-bar.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { NgTemplateOutlet } from '@angular/common';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { Router, RouterLink } from '@angular/router';
|
||||||
|
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
|
||||||
|
import { faMoon } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import { faSun } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import { ThemeSwitchService } from '../../service/theme-switch.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-navigation-bar',
|
||||||
|
imports: [FontAwesomeModule, RouterLink, NgTemplateOutlet ],
|
||||||
|
templateUrl: './navigation-bar.html',
|
||||||
|
styleUrl: './navigation-bar.scss'
|
||||||
|
})
|
||||||
|
export class NavigationBar {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private router: Router,
|
||||||
|
protected themeSwitchService: ThemeSwitchService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
isActive(route: string): boolean {
|
||||||
|
return this.router.url === route;
|
||||||
|
}
|
||||||
|
|
||||||
|
faMoon = faMoon;
|
||||||
|
faSun = faSun;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import {effect, Injectable, signal, WritableSignal} from '@angular/core';
|
import {computed, effect, Injectable, signal, WritableSignal} from '@angular/core';
|
||||||
import {Theme} from "../models/theme";
|
import {Theme} from "../models/theme";
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
@@ -8,6 +8,9 @@ export class ThemeSwitchService {
|
|||||||
private readonly THEME_KEY = 'app-theme-mode';
|
private readonly THEME_KEY = 'app-theme-mode';
|
||||||
|
|
||||||
public theme: WritableSignal<Theme> = signal(Theme.DEFAULT_THEME);
|
public theme: WritableSignal<Theme> = signal(Theme.DEFAULT_THEME);
|
||||||
|
public darkMode = computed(() => {
|
||||||
|
return this.theme().code === 'dark' || (this.theme().code === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||||||
|
});
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
effect(() => {
|
effect(() => {
|
||||||
@@ -49,8 +52,4 @@ export class ThemeSwitchService {
|
|||||||
console.info(`switching to theme: ${theme.name}`);
|
console.info(`switching to theme: ${theme.name}`);
|
||||||
this.theme.set(theme);
|
this.theme.set(theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
isDarkMode(): boolean {
|
|
||||||
return this.theme().code === 'dark' || (this.theme().code === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
1
src/app/pages/about/about.html
Normal file
1
src/app/pages/about/about.html
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<p>about works!</p>
|
||||||
0
src/app/pages/about/about.scss
Normal file
0
src/app/pages/about/about.scss
Normal file
11
src/app/pages/about/about.ts
Normal file
11
src/app/pages/about/about.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-about',
|
||||||
|
imports: [],
|
||||||
|
templateUrl: './about.html',
|
||||||
|
styleUrl: './about.scss'
|
||||||
|
})
|
||||||
|
export class About {
|
||||||
|
|
||||||
|
}
|
||||||
1
src/app/pages/home/home.html
Normal file
1
src/app/pages/home/home.html
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<p>home works!</p>
|
||||||
0
src/app/pages/home/home.scss
Normal file
0
src/app/pages/home/home.scss
Normal file
11
src/app/pages/home/home.ts
Normal file
11
src/app/pages/home/home.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-home',
|
||||||
|
imports: [],
|
||||||
|
templateUrl: './home.html',
|
||||||
|
styleUrl: './home.scss'
|
||||||
|
})
|
||||||
|
export class Home {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'Open Sans Variable', sans-serif;
|
font-family: 'Open Sans Variable', sans-serif;
|
||||||
width: 100vw;
|
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 15px;
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
overflow: auto;
|
||||||
|
background-color: var(--surface-0);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user