diff --git a/src/app/layout/topbar/topbar.component.html b/src/app/layout/topbar/topbar.component.html index 19c1a4e..5b3701f 100644 --- a/src/app/layout/topbar/topbar.component.html +++ b/src/app/layout/topbar/topbar.component.html @@ -6,10 +6,10 @@ diff --git a/src/app/layout/topbar/topbar.component.scss b/src/app/layout/topbar/topbar.component.scss index 6055d18..1518279 100644 --- a/src/app/layout/topbar/topbar.component.scss +++ b/src/app/layout/topbar/topbar.component.scss @@ -52,6 +52,37 @@ justify-content: center; } +.nav a { + opacity: 0.72; + transition: opacity 150ms ease; + position: relative; + + &::after { + content: ''; + position: absolute; + bottom: 4px; + left: 10px; + right: 10px; + height: 2px; + background: currentColor; + border-radius: 2px; + transform: scaleX(0); + transition: transform 200ms ease; + } + + &:hover { + opacity: 1; + } + + &.active { + opacity: 1; + + &::after { + transform: scaleX(1); + } + } +} + .nav-menu-btn { display: none; } diff --git a/src/app/layout/topbar/topbar.component.ts b/src/app/layout/topbar/topbar.component.ts index 014738d..f1ebb6c 100644 --- a/src/app/layout/topbar/topbar.component.ts +++ b/src/app/layout/topbar/topbar.component.ts @@ -1,5 +1,5 @@ import { Component, computed, inject } from '@angular/core'; -import { RouterLink } from '@angular/router'; +import { RouterLink, RouterLinkActive } from '@angular/router'; import { MatToolbarModule } from '@angular/material/toolbar'; import { MatIconModule } from '@angular/material/icon'; import { MatButtonModule } from '@angular/material/button'; @@ -15,7 +15,7 @@ import {RouterConstants} from '../../constants/RouterConstants'; @Component({ selector: 'app-topbar', imports: [ - RouterLink, + RouterLink, RouterLinkActive, MatToolbarModule, MatIconModule, MatButtonModule, MatMenuModule, MatTooltipModule, TranslateModule, MatDivider ], diff --git a/src/app/pages/algorithms/algorithm-category.ts b/src/app/pages/algorithms/algorithm-category.ts index 15971f6..046b232 100644 --- a/src/app/pages/algorithms/algorithm-category.ts +++ b/src/app/pages/algorithms/algorithm-category.ts @@ -3,4 +3,5 @@ export interface AlgorithmCategory { title: string; description: string; routerLink: string; + icon: string; } diff --git a/src/app/pages/algorithms/algorithms.component.html b/src/app/pages/algorithms/algorithms.component.html index 2e2efcb..838b550 100644 --- a/src/app/pages/algorithms/algorithms.component.html +++ b/src/app/pages/algorithms/algorithms.component.html @@ -1,15 +1,16 @@
-

{{ 'ALGORITHM.TITLE' |translate }}

+

{{ 'ALGORITHM.TITLE' | translate }}

-@for (category of categories; track category.id) { + @for (category of categories; track category.id) { - - {{ category.title | translate }} - -

{{ category.description | translate}}

+
+ {{ category.icon }} +
+

{{ category.title | translate }}

+

{{ category.description | translate }}

} -
+ diff --git a/src/app/pages/algorithms/algorithms.component.ts b/src/app/pages/algorithms/algorithms.component.ts index 3dc2ee2..7ebb2a4 100644 --- a/src/app/pages/algorithms/algorithms.component.ts +++ b/src/app/pages/algorithms/algorithms.component.ts @@ -3,13 +3,14 @@ import { AlgorithmsService } from './algorithms.service'; import { AlgorithmCategory } from './algorithm-category'; import { RouterLink } from '@angular/router'; import { MatCardModule } from '@angular/material/card'; +import { MatIconModule } from '@angular/material/icon'; import {TranslatePipe} from '@ngx-translate/core'; @Component({ selector: 'app-algorithms', templateUrl: './algorithms.component.html', styleUrl: './algorithms.component.scss', - imports: [RouterLink, MatCardModule, TranslatePipe], + imports: [RouterLink, MatCardModule, MatIconModule, TranslatePipe], }) export class AlgorithmsComponent { private readonly algorithmsService = inject(AlgorithmsService); diff --git a/src/app/pages/algorithms/algorithms.service.ts b/src/app/pages/algorithms/algorithms.service.ts index 83b8cdb..9459254 100644 --- a/src/app/pages/algorithms/algorithms.service.ts +++ b/src/app/pages/algorithms/algorithms.service.ts @@ -12,49 +12,57 @@ export class AlgorithmsService { id: 'pathfinding', title: 'ALGORITHM.PATHFINDING.TITLE', description: 'ALGORITHM.PATHFINDING.DESCRIPTION', - routerLink: RouterConstants.PATHFINDING.LINK + routerLink: RouterConstants.PATHFINDING.LINK, + icon: 'route' }, { id: 'sorting', title: 'ALGORITHM.SORTING.TITLE', description: 'ALGORITHM.SORTING.DESCRIPTION', - routerLink: RouterConstants.SORTING.LINK + routerLink: RouterConstants.SORTING.LINK, + icon: 'sort' }, { id: 'gameOfLife', title: 'ALGORITHM.GOL.TITLE', description: 'ALGORITHM.GOL.DESCRIPTION', - routerLink: RouterConstants.GOL.LINK + routerLink: RouterConstants.GOL.LINK, + icon: 'grid_on' }, { id: 'labyrinth', title: 'ALGORITHM.LABYRINTH.TITLE', description: 'ALGORITHM.LABYRINTH.DESCRIPTION', - routerLink: RouterConstants.LABYRINTH.LINK + routerLink: RouterConstants.LABYRINTH.LINK, + icon: 'grid_view' }, { id: 'fractal', title: 'ALGORITHM.FRACTAL.TITLE', description: 'ALGORITHM.FRACTAL.DESCRIPTION', - routerLink: RouterConstants.FRACTAL.LINK + routerLink: RouterConstants.FRACTAL.LINK, + icon: 'blur_on' }, { id: 'fractal3d', title: 'ALGORITHM.FRACTAL3D.TITLE', description: 'ALGORITHM.FRACTAL3D.DESCRIPTION', - routerLink: RouterConstants.FRACTAL3d.LINK + routerLink: RouterConstants.FRACTAL3d.LINK, + icon: 'view_in_ar' }, { id: 'pendulum', title: 'ALGORITHM.PENDULUM.TITLE', description: 'ALGORITHM.PENDULUM.DESCRIPTION', - routerLink: RouterConstants.PENDULUM.LINK + routerLink: RouterConstants.PENDULUM.LINK, + icon: 'rotate_right' }, { id: 'cloth', title: 'ALGORITHM.CLOTH.TITLE', description: 'ALGORITHM.CLOTH.DESCRIPTION', - routerLink: RouterConstants.CLOTH.LINK + routerLink: RouterConstants.CLOTH.LINK, + icon: 'texture' } ]; diff --git a/src/styles.scss b/src/styles.scss index 7144ca5..14f5545 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -50,6 +50,10 @@ $dark-theme: mat.define-theme((color: (theme-type: dark, primary: mat.$cyan-pale --link-color-hover: #9ad2ff; } +.dark body { + background: radial-gradient(ellipse at 50% 0%, #1e2530 0%, #1a1a1a 65%); +} + /* ---- global background and tests ---- */ html, body { @@ -287,12 +291,17 @@ a { } canvas { - border: 1px solid lightgray; + border: none; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1); display: block; margin: 0 auto; max-width: 100%; } +.dark canvas { + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08); +} + .legend { display: flex; flex-wrap: wrap; @@ -518,6 +527,10 @@ app-root { margin-top: 0; margin-bottom: 0.5rem; font-size: clamp(1.5rem, 5vw, 2.5rem); + background: linear-gradient(135deg, var(--mat-sys-primary), var(--mat-sys-tertiary)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; } .hero .intro .lead { @@ -706,6 +719,57 @@ app-root { display: flex; flex-direction: column; cursor: pointer; + + &:hover { + transform: translateY(-4px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); + } +} + +.algo-card::after, .project-card::after { + inset: unset; + top: 0; + left: 0; + right: 0; + height: 3px; + background: linear-gradient(90deg, var(--mat-sys-primary), var(--mat-sys-tertiary)); + border-radius: var(--card-radius) var(--card-radius) 0 0; +} + +.algo-icon-wrap { + width: 48px; + height: 48px; + border-radius: 12px; + display: flex; + align-items: center; + justify-content: center; + background: color-mix(in oklab, var(--mat-sys-primary) 15%, transparent); + color: var(--mat-sys-primary); + margin-bottom: 1rem; + + mat-icon { + font-size: 26px; + width: 26px; + height: 26px; + } +} + +.algo-page-title { + margin: 0 0 0.5rem 0; + font-size: clamp(1.4rem, 4vw, 2rem); +} + +.algo-card-title { + font-size: 1.05rem; + font-weight: 600; + margin: 0 0 0.5rem 0; +} + +.algo-card-desc { + margin: 0; + opacity: 0.75; + font-size: 0.9rem; + line-height: 1.55; } .project-card {