Browse Source

Merge aa1e34dad3 into 9387f5e1df

pull/3661/merge
Thomas Kaul 2 weeks ago
committed by GitHub
parent
commit
a091d70a63
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 6
      CHANGELOG.md
  2. 2
      apps/client/src/app/app.component.ts
  3. 60
      apps/client/src/app/components/header/header.component.html
  4. 2
      apps/client/src/app/components/header/header.component.scss
  5. 56
      apps/client/src/styles.scss
  6. 155
      apps/client/src/styles/m3-theme.scss
  7. 281
      apps/client/src/styles/theme.scss

6
CHANGELOG.md

@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Next
### Changed
- Migrated from _Material Design_ 2 to _Material Design_ 3
## 2.189.0 - 2025-08-05
### Changed

2
apps/client/src/app/app.component.ts

@ -366,7 +366,9 @@ export class AppComponent implements OnDestroy, OnInit {
if (isDarkTheme) {
this.document.body.classList.add('theme-dark');
this.document.body.classList.remove('theme-light');
} else {
this.document.body.classList.add('theme-light');
this.document.body.classList.remove('theme-dark');
}

60
apps/client/src/app/components/header/header.component.html

@ -2,7 +2,7 @@
@if (user) {
<div class="d-flex h-100 logo-container" [ngClass]="{ filled: hasTabs }">
<a
class="align-items-center justify-content-start rounded-0"
class="align-items-center h-100 justify-content-start rounded-0"
mat-button
[ngClass]="{ 'w-100': hasTabs }"
[routerLink]="['/']"
@ -15,9 +15,9 @@
<ul class="align-items-center d-flex list-inline m-0 px-2">
<li class="list-inline-item">
<a
class="d-none d-sm-block"
class="d-none d-sm-block rounded"
i18n
mat-flat-button
mat-button
[ngClass]="{
'font-weight-bold':
currentRoute === internalRoutes.home.path ||
@ -32,9 +32,9 @@
</li>
<li class="list-inline-item">
<a
class="d-none d-sm-block"
class="d-none d-sm-block rounded"
i18n
mat-flat-button
mat-button
[ngClass]="{
'font-weight-bold': currentRoute === internalRoutes.portfolio.path,
'text-decoration-underline':
@ -46,9 +46,9 @@
</li>
<li class="list-inline-item">
<a
class="d-none d-sm-block"
class="d-none d-sm-block rounded"
i18n
mat-flat-button
mat-button
[ngClass]="{
'font-weight-bold': currentRoute === internalRoutes.accounts.path,
'text-decoration-underline':
@ -61,9 +61,9 @@
@if (hasPermissionToAccessAdminControl) {
<li class="list-inline-item">
<a
class="d-none d-sm-block"
class="d-none d-sm-block rounded"
i18n
mat-flat-button
mat-button
[ngClass]="{
'font-weight-bold':
currentRoute === internalRoutes.adminControl.path,
@ -77,9 +77,9 @@
}
<li class="list-inline-item">
<a
class="d-none d-sm-block"
class="d-none d-sm-block rounded"
i18n
mat-flat-button
mat-button
[ngClass]="{
'font-weight-bold': currentRoute === routeResources,
'text-decoration-underline': currentRoute === routeResources
@ -93,8 +93,8 @@
) {
<li class="list-inline-item">
<a
class="d-none d-sm-block"
mat-flat-button
class="d-none d-sm-block rounded"
mat-button
[ngClass]="{
'font-weight-bold': currentRoute === routePricing,
'text-decoration-underline': currentRoute === routePricing
@ -112,9 +112,9 @@
}
<li class="list-inline-item">
<a
class="d-none d-sm-block"
class="d-none d-sm-block rounded"
i18n
mat-flat-button
mat-button
[ngClass]="{
'font-weight-bold': currentRoute === routeAbout,
'text-decoration-underline': currentRoute === routeAbout
@ -164,7 +164,7 @@
<li class="list-inline-item">
<button
class="no-min-width px-1"
mat-flat-button
mat-button
[matMenuTriggerFor]="accountMenu"
(menuClosed)="onMenuClosed()"
(menuOpened)="onMenuOpened()"
@ -334,7 +334,7 @@
@if (user === null) {
<div class="d-flex h-100 logo-container" [ngClass]="{ filled: hasTabs }">
<a
class="align-items-center justify-content-start rounded-0"
class="align-items-center h-100 justify-content-start rounded-0"
mat-button
[ngClass]="{ 'w-100': hasTabs }"
[routerLink]="['/']"
@ -350,9 +350,9 @@
<ul class="align-items-center d-flex list-inline m-0 px-2">
<li class="list-inline-item">
<a
class="d-none d-sm-block"
class="d-none d-sm-block rounded"
i18n
mat-flat-button
mat-button
[ngClass]="{
'font-weight-bold': currentRoute === routeFeatures,
'text-decoration-underline': currentRoute === routeFeatures
@ -363,9 +363,9 @@
</li>
<li class="list-inline-item">
<a
class="d-none d-sm-block"
class="d-none d-sm-block rounded"
i18n
mat-flat-button
mat-button
[ngClass]="{
'font-weight-bold': currentRoute === routeAbout,
'text-decoration-underline': currentRoute === routeAbout
@ -377,8 +377,8 @@
@if (hasPermissionForSubscription) {
<li class="list-inline-item">
<a
class="d-sm-block"
mat-flat-button
class="d-sm-block rounded"
mat-button
[ngClass]="{
'font-weight-bold': currentRoute === routePricing,
'text-decoration-underline': currentRoute === routePricing
@ -397,9 +397,9 @@
@if (hasPermissionToAccessFearAndGreedIndex) {
<li class="list-inline-item">
<a
class="d-none d-sm-block"
class="d-none d-sm-block rounded"
i18n
mat-flat-button
mat-button
[ngClass]="{
'font-weight-bold': currentRoute === routeMarkets,
'text-decoration-underline': currentRoute === routeMarkets
@ -413,19 +413,23 @@
<a
class="d-none d-sm-block no-min-width p-1"
href="https://github.com/ghostfolio/ghostfolio"
mat-flat-button
mat-button
><ion-icon name="logo-github"></ion-icon
></a>
</li>
<li class="list-inline-item">
<button class="d-sm-block" mat-flat-button (click)="openLoginDialog()">
<button
class="d-sm-block rounded"
mat-button
(click)="openLoginDialog()"
>
<ng-container i18n>Sign in</ng-container>
</button>
</li>
@if (currentRoute !== 'register' && hasPermissionToCreateUser) {
<li class="list-inline-item ml-1">
<a
class="d-none d-sm-block"
class="d-none d-sm-block px-3 rounded"
color="primary"
mat-flat-button
[routerLink]="routerLinkRegister"

2
apps/client/src/app/components/header/header.component.scss

@ -24,7 +24,7 @@
}
.mdc-button {
height: 100%;
color: var(--mdc-text-button-label-text-color);
&:not(.mat-primary) {
background-color: transparent;

56
apps/client/src/styles.scss

@ -251,46 +251,10 @@ body {
}
}
.mat-mdc-card {
--mat-card-elevated-container-color: var(--dark-background);
--mat-card-outlined-container-color: var(--dark-background);
}
.mat-mdc-fab {
&.mat-primary {
--mat-fab-icon-color: rgba(var(--dark-primary-text));
--mat-mdc-fab-color: rgba(var(--dark-primary-text));
}
}
.mat-mdc-paginator {
background-color: rgba(var(--palette-foreground-base-dark), 0.02);
}
.mat-mdc-slide-toggle {
.mdc-switch__track {
--mat-slide-toggle-selected-focus-track-color: rgba(
255,
255,
255,
0.12
);
--mat-slide-toggle-selected-hover-track-color: rgba(
255,
255,
255,
0.12
);
--mat-slide-toggle-selected-pressed-track-color: rgba(
255,
255,
255,
0.12
);
--mat-slide-toggle-selected-track-color: rgba(255, 255, 255, 0.12);
}
}
.mdc-button {
&.mat-accent,
&.mat-primary {
@ -438,8 +402,6 @@ ngx-skeleton-loader {
.mat-mdc-card {
.mat-mdc-card-title {
--mat-card-title-text-line-height: 1.2;
margin-bottom: 0.5rem;
}
}
@ -463,15 +425,6 @@ ngx-skeleton-loader {
}
}
.mat-mdc-fab {
color: var(--mat-mdc-fab-color, inherit) !important;
&.mat-primary {
--mat-fab-icon-color: rgba(var(--light-primary-text));
--mat-mdc-fab-color: rgba(var(--light-primary-text));
}
}
.mat-mdc-form-field {
&.without-hint {
.mat-mdc-form-field-subscript-wrapper {
@ -512,15 +465,6 @@ ngx-skeleton-loader {
}
}
.mat-mdc-slide-toggle {
.mdc-switch__track {
--mat-slide-toggle-selected-focus-track-color: rgba(0, 0, 0, 0.12);
--mat-slide-toggle-selected-hover-track-color: rgba(0, 0, 0, 0.12);
--mat-slide-toggle-selected-pressed-track-color: rgba(0, 0, 0, 0.12);
--mat-slide-toggle-selected-track-color: rgba(0, 0, 0, 0.12);
}
}
.mat-stepper-vertical,
.mat-stepper-horizontal {
background: transparent !important;

155
apps/client/src/styles/m3-theme.scss

@ -0,0 +1,155 @@
// This file was generated by running 'ng generate @angular/material:m3-theme'.
// Proceed with caution if making changes to this file.
@use 'sass:map';
@use '@angular/material' as mat;
// Note: Color palettes are generated from primary: #36cfcc, secondary: #3686cf
$_palettes: (
primary: (
0: #000000,
10: #00201f,
20: #003736,
25: #004342,
30: #00504e,
35: #005d5b,
40: #006a68,
50: #008583,
60: #00a19f,
70: #11bebc,
80: #47dbd7,
90: #6bf7f4,
95: #affffc,
98: #e3fffd,
99: #f2fffe,
100: #ffffff
),
secondary: (
0: #000000,
10: #001d36,
20: #003258,
25: #003d6a,
30: #00497c,
35: #00558f,
40: #0061a3,
50: #267bc3,
60: #4895df,
70: #66b0fb,
80: #9ecaff,
90: #d1e4ff,
95: #e9f1ff,
98: #f8f9ff,
99: #fdfcff,
100: #ffffff
),
tertiary: (
0: #000000,
10: #031d35,
20: #1b324b,
25: #273d57,
30: #324863,
35: #3e546f,
40: #4a607b,
50: #637995,
60: #7c92b0,
70: #97adcc,
80: #b2c8e8,
90: #d2e4ff,
95: #eaf1ff,
98: #f8f9ff,
99: #fdfcff,
100: #ffffff
),
neutral: (
0: #000000,
10: #191c1c,
20: #2d3131,
25: #383c3c,
30: #444747,
35: #4f5353,
40: #5b5f5e,
50: #747877,
60: #8e9191,
70: #a9acab,
80: #c4c7c6,
90: #e0e3e2,
95: #eff1f0,
98: #f7faf9,
99: #fafdfc,
100: #ffffff,
4: #0b0f0f,
6: #101414,
12: #1d2020,
17: #272b2a,
22: #323535,
24: #363a39,
87: #d8dada,
92: #e6e9e8,
94: #eceeed,
96: #f2f4f3
),
neutral-variant: (
0: #000000,
10: #141d1d,
20: #293232,
25: #343d3d,
30: #3f4948,
35: #4a5454,
40: #566060,
50: #6f7978,
60: #889392,
70: #a3adac,
80: #bec9c7,
90: #dae5e3,
95: #e8f3f2,
98: #f1fbfa,
99: #f4fefd,
100: #ffffff
),
error: (
0: #000000,
10: #410002,
20: #690005,
25: #7e0007,
30: #93000a,
35: #a80710,
40: #ba1a1a,
50: #de3730,
60: #ff5449,
70: #ff897d,
80: #ffb4ab,
90: #ffdad6,
95: #ffedea,
98: #fff8f7,
99: #fffbff,
100: #ffffff
)
);
$_rest: (
secondary: map.get($_palettes, secondary),
neutral: map.get($_palettes, neutral),
neutral-variant: map.get($_palettes, neutral-variant),
error: map.get($_palettes, error)
);
$_primary: map.merge(map.get($_palettes, primary), $_rest);
$_tertiary: map.merge(map.get($_palettes, tertiary), $_rest);
$light-theme: mat.define-theme(
(
color: (
theme-type: light,
primary: $_primary,
tertiary: $_tertiary
)
)
);
$dark-theme: mat.define-theme(
(
color: (
theme-type: dark,
primary: $_primary,
tertiary: $_tertiary
)
)
);

281
apps/client/src/styles/theme.scss

@ -1,112 +1,221 @@
@use '@angular/material' as mat;
@use 'sass:map';
$dark-primary-text: rgba(black, 0.87);
$light-primary-text: white;
$mat-css-dark-theme-selector: '.theme-dark';
$gf-primary: (
50: var(--gf-theme-primary-50),
100: var(--gf-theme-primary-100),
200: var(--gf-theme-primary-200),
300: var(--gf-theme-primary-300),
400: var(--gf-theme-primary-400),
500: var(--gf-theme-primary-500),
600: var(--gf-theme-primary-600),
700: var(--gf-theme-primary-700),
800: var(--gf-theme-primary-800),
900: var(--gf-theme-primary-900),
A100: var(--gf-theme-primary-A100),
A200: var(--gf-theme-primary-A200),
A400: var(--gf-theme-primary-A400),
A700: var(--gf-theme-primary-A700),
contrast: (
50: $dark-primary-text,
100: $dark-primary-text,
200: $dark-primary-text,
300: $light-primary-text,
400: $light-primary-text,
500: $light-primary-text,
600: $light-primary-text,
700: $light-primary-text,
800: $light-primary-text,
900: $light-primary-text,
A100: $dark-primary-text,
A200: $light-primary-text,
A400: $light-primary-text,
A700: $light-primary-text
$_palettes: (
primary: (
0: #000000,
10: #00201f,
20: #003736,
25: #004342,
30: #00504e,
35: #005d5b,
40: #006a68,
50: #008583,
60: #00a19f,
70: #11bebc,
80: #47dbd7,
90: #6bf7f4,
95: #affffc,
98: #e3fffd,
99: #f2fffe,
100: #ffffff
),
secondary: (
0: #000000,
10: #001d36,
20: #003258,
25: #003d6a,
30: #00497c,
35: #00558f,
40: #0061a3,
50: #267bc3,
60: #4895df,
70: #66b0fb,
80: #9ecaff,
90: #d1e4ff,
95: #e9f1ff,
98: #f8f9ff,
99: #fdfcff,
100: #ffffff
),
tertiary: (
0: #000000,
10: #031d35,
20: #1b324b,
25: #273d57,
30: #324863,
35: #3e546f,
40: #4a607b,
50: #637995,
60: #7c92b0,
70: #97adcc,
80: #b2c8e8,
90: #d2e4ff,
95: #eaf1ff,
98: #f8f9ff,
99: #fdfcff,
100: #ffffff
),
neutral: (
0: #000000,
10: #191c1c,
20: #2d3131,
25: #383c3c,
30: #444747,
35: #4f5353,
40: #5b5f5e,
50: #747877,
60: #8e9191,
70: #a9acab,
80: #c4c7c6,
90: #e0e3e2,
95: #eff1f0,
98: #f7faf9,
99: #fafdfc,
100: #ffffff,
4: #0b0f0f,
6: #101414,
12: #1d2020,
17: #272b2a,
22: #323535,
24: #363a39,
87: #d8dada,
92: #e6e9e8,
94: #eceeed,
96: #f2f4f3
),
neutral-variant: (
0: #000000,
10: #141d1d,
20: #293232,
25: #343d3d,
30: #3f4948,
35: #4a5454,
40: #566060,
50: #6f7978,
60: #889392,
70: #a3adac,
80: #bec9c7,
90: #dae5e3,
95: #e8f3f2,
98: #f1fbfa,
99: #f4fefd,
100: #ffffff
),
error: (
0: #000000,
10: #410002,
20: #690005,
25: #7e0007,
30: #93000a,
35: #a80710,
40: #ba1a1a,
50: #de3730,
60: #ff5449,
70: #ff897d,
80: #ffb4ab,
90: #ffdad6,
95: #ffedea,
98: #fff8f7,
99: #fffbff,
100: #ffffff
)
);
$gf-secondary: (
50: var(--gf-theme-secondary-50),
100: var(--gf-theme-secondary-100),
200: var(--gf-theme-secondary-200),
300: var(--gf-theme-secondary-300),
400: var(--gf-theme-secondary-400),
500: var(--gf-theme-secondary-500),
600: var(--gf-theme-secondary-600),
700: var(--gf-theme-secondary-700),
800: var(--gf-theme-secondary-800),
900: var(--gf-theme-secondary-900),
A100: var(--gf-theme-secondary-A100),
A200: var(--gf-theme-secondary-A200),
A400: var(--gf-theme-secondary-A400),
A700: var(--gf-theme-secondary-A700),
contrast: (
50: $dark-primary-text,
100: $dark-primary-text,
200: $dark-primary-text,
300: $light-primary-text,
400: $light-primary-text,
500: $light-primary-text,
600: $light-primary-text,
700: $light-primary-text,
800: $light-primary-text,
900: $light-primary-text,
A100: $dark-primary-text,
A200: $light-primary-text,
A400: $light-primary-text,
A700: $light-primary-text
)
$_rest: (
secondary: map.get($_palettes, secondary),
neutral: map.get($_palettes, neutral),
neutral-variant: map.get($_palettes, neutral-variant),
error: map.get($_palettes, error)
);
$_primary: map.merge(map.get($_palettes, primary), $_rest);
$_tertiary: map.merge(map.get($_palettes, tertiary), $_rest);
@include mat.app-background();
@include mat.button-density(0);
@include mat.elevation-classes();
@include mat.table-density(-1);
$gf-typography: mat.m2-define-typography-config();
// $gf-typography: mat.m2-define-typography-config();
// Create default theme
$gf-theme-default: mat.m2-define-light-theme(
.theme-light {
$gf-theme-default: mat.define-theme(
(
color: (
accent: mat.m2-define-palette($gf-secondary, 500, 900, A100),
primary: mat.m2-define-palette($gf-primary)
primary: $_primary,
theme-type: light,
tertiary: $_tertiary
),
density: (
scale: -3
),
density: -3,
typography: $gf-typography
// typography: $gf-typography
)
);
);
@include mat.all-component-themes($gf-theme-default);
@include mat.card-overrides(
(
outlined-container-color: var(--light-background),
outlined-outline-color: rgba(var(--dark-dividers)),
title-text-line-height: 1.2
)
);
@include mat.fab-overrides(
(
container-color: var(--gf-theme-primary-500)
)
);
@include mat.table-overrides(
(
row-item-outline-color: rgba(var(--dark-dividers))
)
);
@include mat.all-component-themes($gf-theme-default);
--mdc-outlined-card-container-color: unset;
}
// Create dark theme
$gf-theme-dark: mat.m2-define-dark-theme(
.theme-dark {
$gf-theme-dark: mat.define-theme(
(
color: (
accent: mat.m2-define-palette($gf-secondary, 500, 900, A100),
primary: mat.m2-define-palette($gf-primary)
primary: $_primary,
theme-type: dark,
tertiary: $_tertiary
),
density: (
scale: -3
),
density: -3,
typography: $gf-typography
// typography: $gf-typography
)
);
);
.theme-dark {
@include mat.all-component-colors($gf-theme-dark);
}
@include mat.all-component-themes($gf-theme-dark);
@include mat.button-density(0);
@include mat.elevation-classes();
@include mat.app-background();
@include mat.table-density(-1);
@include mat.card-overrides(
(
outlined-container-color: var(--dark-background),
outlined-outline-color: rgba(var(--light-dividers)),
title-text-line-height: 1.2
)
);
@include mat.fab-overrides(
(
container-color: var(--gf-theme-primary-500)
)
);
@include mat.table-overrides(
(
row-item-outline-color: rgba(var(--light-dividers))
)
);
--mdc-outlined-card-container-color: unset;
}
:root {
--gf-theme-alpha-hover: 0.04;

Loading…
Cancel
Save