From d52b3b13aa677b441c3ee23661a892bd72ef1d0e Mon Sep 17 00:00:00 2001 From: Marcin Stelmaszyk Date: Tue, 13 May 2025 08:07:33 +0200 Subject: [PATCH 01/11] Reapply "feat: enable light mode (#255)" (#443) This reverts commit 3be6ade501e8cae1d4aed3131db96b3dc6bdc21c. --- apps/blog/src/assets/icons/arrow-down.svg | 2 +- .../feature-about-us.component.html | 6 +- .../feature-latest-articles.component.ts | 1 - .../article-compact-card.component.html | 19 +- .../article-compact-card.component.ts | 11 +- .../article-hero-card-skeleton.component.ts | 2 +- .../article-horizontal-card.component.html | 2 +- .../article-regular-card.component.html | 18 +- .../ui-article-card.component.html | 5 +- .../ui-article-list-title.component.html | 2 +- .../author-card-template.component.ts | 5 +- .../author-card/author-card.component.html | 2 +- .../become-author-page.component.html | 4 +- .../become-author-list-item.component.html | 6 +- .../components/footer-logo.component.ts | 9 +- .../footer-social-media-icons.component.ts | 2 +- .../src/lib/footer/footer.component.html | 13 +- .../src/lib/footer/footer.component.scss | 18 +- .../lib/navigation/navigation.component.html | 10 +- .../lib/navigation/navigation.component.ts | 2 + .../newsletter.component.html | 2 +- .../partners-list.component.html | 2 +- .../shared/ui-card/src/lib/card.component.ts | 4 +- .../shared/ui-card/src/lib/card.stories.ts | 2 +- .../src/lib/ui-difficulty.component.ts | 11 +- .../shared/ui-pill/src/lib/pill.directive.ts | 2 +- .../src/lib/social-media-icons.component.html | 5 +- .../lib/rules-row/rules-row.component.html | 4 +- libs/shared/assets/src/lib/styles/main.scss | 15 + package.json | 1 + pnpm-lock.yaml | 9530 ++++++++--------- tailwind.preset.js | 26 +- 32 files changed, 4652 insertions(+), 5091 deletions(-) diff --git a/apps/blog/src/assets/icons/arrow-down.svg b/apps/blog/src/assets/icons/arrow-down.svg index e185563aa..62a34851b 100644 --- a/apps/blog/src/assets/icons/arrow-down.svg +++ b/apps/blog/src/assets/icons/arrow-down.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.html b/libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.html index f4e1957f8..871b50e05 100644 --- a/libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.html +++ b/libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.html @@ -1,9 +1,9 @@ -

+

{{ t('title') }}

- +
-

+

{{ t('authorsTitle') }}

diff --git a/libs/blog/articles/feature-latest-articles/src/lib/feature-latest-articles/feature-latest-articles.component.ts b/libs/blog/articles/feature-latest-articles/src/lib/feature-latest-articles/feature-latest-articles.component.ts index 5663766e9..c49e13dae 100644 --- a/libs/blog/articles/feature-latest-articles/src/lib/feature-latest-articles/feature-latest-articles.component.ts +++ b/libs/blog/articles/feature-latest-articles/src/lib/feature-latest-articles/feature-latest-articles.component.ts @@ -38,7 +38,6 @@ import { CategoryListItem, injectCategories } from './categories.const'; NgClass, TranslocoDirective, ArticleRegularCardSkeletonComponent, - CardComponent, RepeatDirective, RouterLink, ButtonComponent, diff --git a/libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.html b/libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.html index b640f9a37..bb0deb591 100644 --- a/libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.html +++ b/libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.html @@ -1,16 +1,17 @@
-
+ Post featured image +
diff --git a/libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.ts b/libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.ts index 3a3b38cc3..ffe7f561a 100644 --- a/libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.ts +++ b/libs/blog/articles/ui-article-card/src/lib/components/article-compact-card/article-compact-card.component.ts @@ -1,3 +1,4 @@ +import { NgOptimizedImage } from '@angular/common'; import { ChangeDetectionStrategy, Component, input } from '@angular/core'; import { RouterLink } from '@angular/router'; import { FastSvgComponent } from '@push-based/ngx-fast-svg'; @@ -9,9 +10,17 @@ import { AvatarComponent } from '@angular-love/blog/shared/ui-avatar'; @Component({ selector: 'al-article-compact-card', changeDetection: ChangeDetectionStrategy.OnPush, - imports: [AvatarComponent, RouterLink, AlLocalizePipe, FastSvgComponent], + standalone: true, + imports: [ + AvatarComponent, + RouterLink, + AlLocalizePipe, + FastSvgComponent, + NgOptimizedImage, + ], templateUrl: './article-compact-card.component.html', }) export class ArticleCompactCardComponent { readonly article = input.required(); + readonly imagePriority = input(null); } diff --git a/libs/blog/articles/ui-article-card/src/lib/components/article-hero-card/article-hero-card-skeleton.component.ts b/libs/blog/articles/ui-article-card/src/lib/components/article-hero-card/article-hero-card-skeleton.component.ts index 9bbe59787..bfc4063b8 100644 --- a/libs/blog/articles/ui-article-card/src/lib/components/article-hero-card/article-hero-card-skeleton.component.ts +++ b/libs/blog/articles/ui-article-card/src/lib/components/article-hero-card/article-hero-card-skeleton.component.ts @@ -7,7 +7,7 @@ import { CardComponent } from '@angular-love/blog/shared/ui-card'; selector: 'al-article-hero-card-skeleton', imports: [NgxSkeletonLoaderModule, CardComponent], template: ` - +
diff --git a/libs/blog/articles/ui-article-card/src/lib/components/article-horizontal-card/article-horizontal-card.component.html b/libs/blog/articles/ui-article-card/src/lib/components/article-horizontal-card/article-horizontal-card.component.html index 5e6de07f9..43aedf05d 100644 --- a/libs/blog/articles/ui-article-card/src/lib/components/article-horizontal-card/article-horizontal-card.component.html +++ b/libs/blog/articles/ui-article-card/src/lib/components/article-horizontal-card/article-horizontal-card.component.html @@ -1,6 +1,6 @@
- - + + {{ article().author.name }}
@@ -34,10 +38,14 @@
-

+

{{ article().title }}

-

+

{{ article().excerpt }}

diff --git a/libs/blog/articles/ui-article-card/src/lib/ui-article-card/ui-article-card.component.html b/libs/blog/articles/ui-article-card/src/lib/ui-article-card/ui-article-card.component.html index 666ac200d..262b5f722 100644 --- a/libs/blog/articles/ui-article-card/src/lib/ui-article-card/ui-article-card.component.html +++ b/libs/blog/articles/ui-article-card/src/lib/ui-article-card/ui-article-card.component.html @@ -12,6 +12,9 @@ /> } @case ('compact') { - + } } diff --git a/libs/blog/articles/ui-article-list-title/src/lib/ui-article-list-title/ui-article-list-title.component.html b/libs/blog/articles/ui-article-list-title/src/lib/ui-article-list-title/ui-article-list-title.component.html index 99262fbc1..44234e6eb 100644 --- a/libs/blog/articles/ui-article-list-title/src/lib/ui-article-list-title/ui-article-list-title.component.html +++ b/libs/blog/articles/ui-article-list-title/src/lib/ui-article-list-title/ui-article-list-title.component.html @@ -1,7 +1,7 @@

{{ title() }}

diff --git a/libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts b/libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts index 48f8244cd..c121d602a 100644 --- a/libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts +++ b/libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts @@ -8,6 +8,7 @@ import { @Component({ selector: 'al-author-card-template', + standalone: true, imports: [CardComponent, CardContentDirective, GradientCardDirective], host: { class: 'block @container', @@ -19,9 +20,11 @@ import { class="@3xl:flex-row @3xl:border-none flex w-full flex-col items-center rounded-lg border" >
diff --git a/libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.html b/libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.html index 73b2947d1..08807e6b8 100644 --- a/libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.html +++ b/libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.html @@ -42,7 +42,7 @@
{{ author().name }} diff --git a/libs/blog/become-author/feature-become-author-page/src/lib/become-author-page/become-author-page.component.html b/libs/blog/become-author/feature-become-author-page/src/lib/become-author-page/become-author-page.component.html index 1dc9a2da1..355da1d31 100644 --- a/libs/blog/become-author/feature-become-author-page/src/lib/become-author-page/become-author-page.component.html +++ b/libs/blog/become-author/feature-become-author-page/src/lib/become-author-page/become-author-page.component.html @@ -31,7 +31,7 @@

href="https://form.typeform.com/to/Zzf1Girt?typeform-source=angular.love" target="_blank" > -

+

{{ t('becomeAuthorCard.buttonText') }}

@@ -61,7 +61,7 @@

class="bg-al-pink flex h-[46px] w-full items-center justify-center rounded-lg md:w-4/5 lg:w-full" [routerLink]="'/writing-rules' | alLocalize" > -

+

{{ t('articleWritingRules.buttonText') }}

diff --git a/libs/blog/become-author/feature-become-author-page/src/lib/components/become-author-list-item/become-author-list-item.component.html b/libs/blog/become-author/feature-become-author-page/src/lib/components/become-author-list-item/become-author-list-item.component.html index 233a64d46..d9b2544d2 100644 --- a/libs/blog/become-author/feature-become-author-page/src/lib/components/become-author-list-item/become-author-list-item.component.html +++ b/libs/blog/become-author/feature-become-author-page/src/lib/components/become-author-list-item/become-author-list-item.component.html @@ -1,18 +1,18 @@
@if (index()) {
-

{{ index() }}

+

{{ index() }}

} @else {
- +
}

diff --git a/libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-logo.component.ts b/libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-logo.component.ts index dee112d74..ea0383de6 100644 --- a/libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-logo.component.ts +++ b/libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-logo.component.ts @@ -1,5 +1,5 @@ import { NgOptimizedImage } from '@angular/common'; -import { ChangeDetectionStrategy, Component, input } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; @Component({ selector: 'al-footer-logo', @@ -16,13 +16,8 @@ import { ChangeDetectionStrategy, Component, input } from '@angular/core'; /> angular.love

-

`, changeDetection: ChangeDetectionStrategy.OnPush, }) -export class FooterLogoComponent { - readonly currentYear = input.required(); -} +export class FooterLogoComponent {} diff --git a/libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-social-media-icons.component.ts b/libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-social-media-icons.component.ts index 52137a0c7..5f2975052 100644 --- a/libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-social-media-icons.component.ts +++ b/libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-social-media-icons.component.ts @@ -9,7 +9,7 @@ import { SocialMediaIconsComponent } from '@angular-love/blog/shared/ui-social-m
diff --git a/libs/blog/layouts/ui-layouts/src/lib/footer/footer.component.html b/libs/blog/layouts/ui-layouts/src/lib/footer/footer.component.html index 02203540f..a42c92fd9 100644 --- a/libs/blog/layouts/ui-layouts/src/lib/footer/footer.component.html +++ b/libs/blog/layouts/ui-layouts/src/lib/footer/footer.component.html @@ -1,17 +1,16 @@ -
-
diff --git a/libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts b/libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts index aff147c22..c191a4930 100644 --- a/libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts +++ b/libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts @@ -3,13 +3,12 @@ import { Component } from '@angular/core'; import { CardComponent, CardContentDirective, - GradientCardDirective, } from '@angular-love/blog/shared/ui-card'; @Component({ selector: 'al-author-card-template', standalone: true, - imports: [CardComponent, CardContentDirective, GradientCardDirective], + imports: [CardComponent, CardContentDirective], host: { class: 'block @container', }, @@ -20,11 +19,9 @@ import { class="@3xl:flex-row @3xl:border-none flex w-full flex-col items-center rounded-lg border" >
From 38ca2d3b94edb8c49d40756ad146362d86776854 Mon Sep 17 00:00:00 2001 From: Marcin Stelmaszyk Date: Mon, 19 May 2025 14:08:47 +0200 Subject: [PATCH 04/11] fix: hamburger-button color --- .../src/lib/header/components/header-hamburger.component.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/blog/layouts/ui-layouts/src/lib/header/components/header-hamburger.component.ts b/libs/blog/layouts/ui-layouts/src/lib/header/components/header-hamburger.component.ts index e9b1e27ed..42a45b449 100644 --- a/libs/blog/layouts/ui-layouts/src/lib/header/components/header-hamburger.component.ts +++ b/libs/blog/layouts/ui-layouts/src/lib/header/components/header-hamburger.component.ts @@ -19,9 +19,9 @@ import { FastSvgComponent } from '@push-based/ngx-fast-svg'; @if (isOpened()) { } @else { -
-
-
+
+
+
} `, From e97641f97737189a46c6e83c80108fc7dd34ea83 Mon Sep 17 00:00:00 2001 From: Marcin Stelmaszyk Date: Mon, 19 May 2025 21:24:58 +0200 Subject: [PATCH 05/11] feat: added theme switcher - wip --- apps/blog/src/assets/icons/moon.svg | 1 + apps/blog/src/assets/icons/sun.svg | 1 + .../src/app-theme.store.ts | 25 +++++++++---------- .../src/lib/header/header.component.ts | 23 +++++++++++++++++ .../ui-icon/src/lib/icon/icon.component.ts | 4 ++- .../src/lib/root-shell.component.ts | 15 +++++++++++ libs/shared/assets/src/lib/styles/main.scss | 22 ++++++++-------- 7 files changed, 65 insertions(+), 26 deletions(-) create mode 100644 apps/blog/src/assets/icons/moon.svg create mode 100644 apps/blog/src/assets/icons/sun.svg diff --git a/apps/blog/src/assets/icons/moon.svg b/apps/blog/src/assets/icons/moon.svg new file mode 100644 index 000000000..75c6b5174 --- /dev/null +++ b/apps/blog/src/assets/icons/moon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/blog/src/assets/icons/sun.svg b/apps/blog/src/assets/icons/sun.svg new file mode 100644 index 000000000..cd8f68d5f --- /dev/null +++ b/apps/blog/src/assets/icons/sun.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts b/libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts index c7cdaebe9..010ed5f4c 100644 --- a/libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts +++ b/libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts @@ -1,8 +1,8 @@ import { isPlatformBrowser } from '@angular/common'; import { inject, Injectable, PLATFORM_ID } from '@angular/core'; -import { signalStore, withMethods, withState } from '@ngrx/signals'; +import { patchState, signalStore, withMethods, withState } from '@ngrx/signals'; -type Theme = 'dark' | 'light'; +export type Theme = 'dark' | 'light'; interface AppThemeStore { theme: Theme; @@ -19,9 +19,16 @@ export const AppThemeStore = signalStore( ) => ({ syncWithSystemTheme: () => { if (isPlatformBrowser(platformId)) { - ccConsumer.setThemeClass(getSystemTheme()); + const theme = getSystemTheme(); + ccConsumer.setThemeAttribute(theme); + patchState(store, { theme: theme }); } }, + toggleTheme: () => { + const theme = store.theme() === 'dark' ? 'light' : 'dark'; + ccConsumer.setThemeAttribute(theme); + patchState(store, { theme: theme }); + }, }), ), ); @@ -35,15 +42,7 @@ function getSystemTheme(): Theme { /* todo: create consumer interface and decouple AppThemeStore from CCAppThemeConsumer*/ @Injectable({ providedIn: 'root' }) export class CCAppThemeConsumer { - setThemeClass(theme: Theme): void { - const htmlElement = document.documentElement; - switch (theme) { - case 'dark': - htmlElement.classList.add('cc--darkmode'); - break; - case 'light': - htmlElement.classList.remove('cc--darkmode'); - break; - } + setThemeAttribute(theme: Theme): void { + document.documentElement.setAttribute('data-theme', theme); } } diff --git a/libs/blog/layouts/ui-layouts/src/lib/header/header.component.ts b/libs/blog/layouts/ui-layouts/src/lib/header/header.component.ts index 4d2836528..d5ac0782f 100644 --- a/libs/blog/layouts/ui-layouts/src/lib/header/header.component.ts +++ b/libs/blog/layouts/ui-layouts/src/lib/header/header.component.ts @@ -1,10 +1,12 @@ import { ChangeDetectionStrategy, Component, + computed, input, output, signal, } from '@angular/core'; +import { FastSvgComponent } from '@push-based/ngx-fast-svg'; import { LanguagePickerComponent, @@ -36,6 +38,19 @@ import { (languageChange)="languageChange.emit($event)" /> + + (); + readonly theme = input.required<'light' | 'dark'>(); protected languageChange = output(); + protected themeToggle = output(); + protected showNav = signal(false); + protected readonly themeSwitchIcon = computed(() => + this.theme() === 'light' ? 'moon' : 'sun', + ); + protected toggleNav(): void { this.showNav.set(!this.showNav()); } diff --git a/libs/blog/shared/ui-icon/src/lib/icon/icon.component.ts b/libs/blog/shared/ui-icon/src/lib/icon/icon.component.ts index 1d26364cc..0ed088f2b 100644 --- a/libs/blog/shared/ui-icon/src/lib/icon/icon.component.ts +++ b/libs/blog/shared/ui-icon/src/lib/icon/icon.component.ts @@ -18,7 +18,9 @@ export type IconType = | 'send' | 'tick' | 'twitter-x' - | 'youtube'; + | 'youtube' + | 'sun' + | 'moon'; @Component({ selector: 'al-icon', diff --git a/libs/blog/shell/feature-shell-web/src/lib/root-shell.component.ts b/libs/blog/shell/feature-shell-web/src/lib/root-shell.component.ts index c3c611004..ba9f0c524 100644 --- a/libs/blog/shell/feature-shell-web/src/lib/root-shell.component.ts +++ b/libs/blog/shell/feature-shell-web/src/lib/root-shell.component.ts @@ -23,6 +23,7 @@ import { AdImageBanner, AlBannerCarouselComponent, } from '@angular-love/blog/shared/ad-banner'; +import { AppThemeStore } from '@angular-love/data-access-app-theme'; @Component({ selector: 'al-root-shell', @@ -32,7 +33,9 @@ import { @@ -86,6 +89,14 @@ export class RootShellComponent { () => this.sliderStore.slider()?.slideDisplayTimeMs, ); readonly translocoService = inject(TranslocoService); +<<<<<<< HEAD +======= + + private readonly _appThemeStore = inject(AppThemeStore); + + protected readonly theme = computed(() => this._appThemeStore.theme()); + +>>>>>>> 31a555a8 (feat: added theme switcher - wip) // todo: temporary solution to keep in mind how banner influence the layout protected readonly adBannerVisible = computed(() => false); readonly language = toSignal( @@ -113,6 +124,10 @@ export class RootShellComponent { ); } + onThemeToggle() { + this._appThemeStore.toggleTheme(); + } + constructor(viewport: ViewportScroller) { // todo: temporary solution to keep in mind how banner influence the layout effect(() => { diff --git a/libs/shared/assets/src/lib/styles/main.scss b/libs/shared/assets/src/lib/styles/main.scss index d011e99d0..55f3e4d6f 100644 --- a/libs/shared/assets/src/lib/styles/main.scss +++ b/libs/shared/assets/src/lib/styles/main.scss @@ -5,7 +5,7 @@ @tailwind utilities; @layer base { - :root { + :root[data-theme='dark'] { --primary: 255 0 106; --foreground: 255 255 255; --primary-foreground: 255 255 255; @@ -23,17 +23,15 @@ --grey: 46 47 59; } - @media (prefers-color-scheme: light) { - :root { - --primary: 213 1 89; - --foreground: 20 21 27; - --primary-foreground: 0 0 0; - --muted: 25 25 25; - --border: 200 200 200; - --card: 255 255 255; - --background: 255 255 255; - --grey: 241 241 241; - } + :root[data-theme='light'] { + --primary: 213 1 89; + --foreground: 20 21 27; + --primary-foreground: 0 0 0; + --muted: 25 25 25; + --border: 200 200 200; + --card: 255 255 255; + --background: 255 255 255; + --grey: 241 241 241; } } From 9329dcd6de5939fabadfb37e46d24f49ed1ea030 Mon Sep 17 00:00:00 2001 From: Marcin Stelmaszyk Date: Thu, 29 May 2025 15:09:34 +0200 Subject: [PATCH 06/11] feat: added theme switch and fixed cookies consent logic --- .../src/app-theme.store.ts | 22 ++++++++++++++----- .../article-content.component.scss | 2 +- .../article-content.component.ts | 1 - .../src/lib/styles/cookies-consent.scss | 2 +- libs/shared/assets/src/lib/styles/main.scss | 9 +++++--- tailwind.preset.js | 20 +---------------- 6 files changed, 26 insertions(+), 30 deletions(-) diff --git a/libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts b/libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts index 010ed5f4c..6a9085f3b 100644 --- a/libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts +++ b/libs/blog/app-theme/data-access-app-theme/src/app-theme.store.ts @@ -10,7 +10,7 @@ interface AppThemeStore { export const AppThemeStore = signalStore( { providedIn: 'root' }, - withState({ theme: 'light' }), + withState({ theme: 'dark' }), withMethods( ( store, @@ -19,15 +19,19 @@ export const AppThemeStore = signalStore( ) => ({ syncWithSystemTheme: () => { if (isPlatformBrowser(platformId)) { - const theme = getSystemTheme(); + const theme = + (localStorage.getItem('theme') as Theme) ?? getSystemTheme(); ccConsumer.setThemeAttribute(theme); patchState(store, { theme: theme }); } }, toggleTheme: () => { - const theme = store.theme() === 'dark' ? 'light' : 'dark'; - ccConsumer.setThemeAttribute(theme); - patchState(store, { theme: theme }); + if (isPlatformBrowser(platformId)) { + const newTheme = store.theme() === 'dark' ? 'light' : 'dark'; + ccConsumer.setThemeAttribute(newTheme); + localStorage.setItem('theme', newTheme); + patchState(store, { theme: newTheme }); + } }, }), ), @@ -44,5 +48,13 @@ function getSystemTheme(): Theme { export class CCAppThemeConsumer { setThemeAttribute(theme: Theme): void { document.documentElement.setAttribute('data-theme', theme); + + const classList = document.documentElement.classList; + + if (theme === 'dark') { + classList.add('cc--darkmode'); + } else { + classList.remove('cc--darkmode'); + } } } diff --git a/libs/blog/articles/ui-article-content/src/lib/article-content/article-content.component.scss b/libs/blog/articles/ui-article-content/src/lib/article-content/article-content.component.scss index e914d095b..4d2429caa 100644 --- a/libs/blog/articles/ui-article-content/src/lib/article-content/article-content.component.scss +++ b/libs/blog/articles/ui-article-content/src/lib/article-content/article-content.component.scss @@ -5,7 +5,7 @@ margin-top: 1.6rem; } -@media (prefers-color-scheme: dark) { +:root[data-theme='dark'] { .shiki, .shiki span { color: var(--shiki-dark) !important; diff --git a/libs/blog/articles/ui-article-content/src/lib/article-content/article-content.component.ts b/libs/blog/articles/ui-article-content/src/lib/article-content/article-content.component.ts index 26a31b44b..f42793556 100644 --- a/libs/blog/articles/ui-article-content/src/lib/article-content/article-content.component.ts +++ b/libs/blog/articles/ui-article-content/src/lib/article-content/article-content.component.ts @@ -12,7 +12,6 @@ import { DomSanitizer } from '@angular/platform-browser'; selector: 'al-article-content', templateUrl: './article-content.component.html', styleUrl: './article-content.component.scss', - imports: [], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, }) diff --git a/libs/shared/assets/src/lib/styles/cookies-consent.scss b/libs/shared/assets/src/lib/styles/cookies-consent.scss index 434be9c22..392d7abda 100644 --- a/libs/shared/assets/src/lib/styles/cookies-consent.scss +++ b/libs/shared/assets/src/lib/styles/cookies-consent.scss @@ -17,7 +17,7 @@ /** Also make toggles the same color as the button **/ --cc-toggle-on-bg: var(--cc-btn-primary-bg); - @media (prefers-color-scheme: light) { + :root[data-theme='light'] { --cc-btn-secondary-color: rgba(44, 47, 49, 1); } } diff --git a/libs/shared/assets/src/lib/styles/main.scss b/libs/shared/assets/src/lib/styles/main.scss index 55f3e4d6f..010c8a925 100644 --- a/libs/shared/assets/src/lib/styles/main.scss +++ b/libs/shared/assets/src/lib/styles/main.scss @@ -4,6 +4,9 @@ @tailwind components; @tailwind utilities; +@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *)); +@custom-variant light (&:where([data-theme="light"], [data-theme="light"] *)); + @layer base { :root[data-theme='dark'] { --primary: 255 0 106; @@ -28,7 +31,7 @@ --foreground: 20 21 27; --primary-foreground: 0 0 0; --muted: 25 25 25; - --border: 200 200 200; + --border: 229 231 235; --card: 255 255 255; --background: 255 255 255; --grey: 241 241 241; @@ -87,8 +90,8 @@ html { } } -@layer components { +@layer base { .al-link { - @apply text-blue-600 hover:underline; + @apply text-red-500 hover:underline dark:text-blue-400; } } diff --git a/tailwind.preset.js b/tailwind.preset.js index abc725a03..dd6e7ee8e 100644 --- a/tailwind.preset.js +++ b/tailwind.preset.js @@ -1,11 +1,6 @@ -const { - themeVariants, - prefersLight, - prefersDark, -} = require('tailwindcss-theme-variants'); - /** @type {import('tailwindcss').Config} */ module.exports = { + darkMode: 'selector', theme: { extend: { translate: { @@ -51,17 +46,4 @@ module.exports = { }, }, }, - plugins: [ - require('@tailwindcss/container-queries'), - themeVariants({ - themes: { - light: { - mediaQuery: prefersLight /* "@media (prefers-color-scheme: light)" */, - }, - dark: { - mediaQuery: prefersDark /* "@media (prefers-color-scheme: dark)" */, - }, - }, - }), - ], }; From 0445dc3ecbe1b84a5860db7e0323e08afc6529ff Mon Sep 17 00:00:00 2001 From: Marcin Stelmaszyk Date: Thu, 29 May 2025 15:19:18 +0200 Subject: [PATCH 07/11] feat: added theme in gh-giscus component --- .../src/lib/giscus-comments/giscus-comments.component.html | 2 +- .../src/lib/giscus-comments/giscus-comments.component.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/blog/articles/feature-comments/src/lib/giscus-comments/giscus-comments.component.html b/libs/blog/articles/feature-comments/src/lib/giscus-comments/giscus-comments.component.html index 40e24724b..206552b03 100644 --- a/libs/blog/articles/feature-comments/src/lib/giscus-comments/giscus-comments.component.html +++ b/libs/blog/articles/feature-comments/src/lib/giscus-comments/giscus-comments.component.html @@ -11,7 +11,7 @@ [attr.strict]="config.strict ? '1' : '0'" [attr.emitmetadata]="config.emitMetadata ? '1' : '0'" [attr.inputposition]="config.inputPosition" - [attr.theme]="config.theme" + [attr.theme]="theme()" src="https://giscus.app/client.js" crossorigin="anonymous" async diff --git a/libs/blog/articles/feature-comments/src/lib/giscus-comments/giscus-comments.component.ts b/libs/blog/articles/feature-comments/src/lib/giscus-comments/giscus-comments.component.ts index 41e7dde05..6ceb99dfc 100644 --- a/libs/blog/articles/feature-comments/src/lib/giscus-comments/giscus-comments.component.ts +++ b/libs/blog/articles/feature-comments/src/lib/giscus-comments/giscus-comments.component.ts @@ -14,10 +14,10 @@ import { GISCUS_CONFIG, provideComments, } from '@angular-love/blog/articles/data-access'; +import { AppThemeStore } from '@angular-love/data-access-app-theme'; @Component({ selector: 'al-giscus-comments', - imports: [], templateUrl: './giscus-comments.component.html', styleUrl: './giscus-comments.component.scss', changeDetection: ChangeDetectionStrategy.OnPush, @@ -30,6 +30,7 @@ import { export class GiscusCommentsComponent { readonly config = inject(GISCUS_CONFIG); readonly translocoService = inject(TranslocoService); + readonly theme = inject(AppThemeStore).theme; readonly lang = toSignal(this.translocoService.langChanges$, { initialValue: this.translocoService.getActiveLang(), From e0a2694a723c5181dd56916ceb698ae9506d0bda Mon Sep 17 00:00:00 2001 From: Marcin Stelmaszyk Date: Wed, 4 Jun 2025 20:52:43 +0200 Subject: [PATCH 08/11] feat: enhance theming support with light/dark variants and gradient options --- .../feature-about-us.component.html | 7 +++++- .../feature-about-us.component.ts | 5 ++++ .../feature-latest-articles.component.html | 2 +- .../author-card-template.component.ts | 25 ++++++++++--------- .../author-card/author-card.component.html | 2 +- .../lib/author-card/author-card.component.ts | 1 + .../footer-social-media-icons.component.ts | 2 +- .../src/lib/button/button.component.ts | 2 +- .../shared/ui-card/src/lib/card.component.ts | 9 ++++--- .../src/lib/social-media-icons.component.html | 2 +- .../src/lib/social-media-icons.component.ts | 20 ++++++++++++++- libs/shared/assets/src/lib/styles/main.scss | 3 --- tailwind.preset.js | 11 ++++++++ 13 files changed, 66 insertions(+), 25 deletions(-) diff --git a/libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.html b/libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.html index 871b50e05..8e5dc2e74 100644 --- a/libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.html +++ b/libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.html @@ -41,7 +41,12 @@

@for (author of authorsCards(); track author.slug) { - + @if ($index === noAuthorsInView() - 2) { @defer (on viewport) { diff --git a/libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.ts b/libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.ts index 7b1377788..e0281fed5 100644 --- a/libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.ts +++ b/libs/blog/about-us/feature-about-us/src/lib/feature-about-us/feature-about-us.component.ts @@ -16,6 +16,7 @@ import { } from '@angular-love/blog/shared/ui-card'; import { InfiniteScrollTriggerDirective } from '@angular-love/blog/shared/ui-pagination'; import { SocialMediaIconsComponent } from '@angular-love/blog/shared/ui-social-media-icons'; +import { AppThemeStore } from '@angular-love/data-access-app-theme'; @Component({ selector: 'al-about-us', @@ -41,6 +42,10 @@ export class FeatureAboutUsComponent implements OnInit { return this.authorsCards()?.length || 0; }); + readonly theme = inject(AppThemeStore).theme; + + readonly hideGradientInAuthorCards = computed(() => this.theme() === 'light'); + private readonly _skip = this._authorListStore.skip; private readonly _total = this._authorListStore.total; private readonly _pageSize = this._authorListStore.pageSize; diff --git a/libs/blog/articles/feature-latest-articles/src/lib/feature-latest-articles/feature-latest-articles.component.html b/libs/blog/articles/feature-latest-articles/src/lib/feature-latest-articles/feature-latest-articles.component.html index 6fadbca06..17802ad09 100644 --- a/libs/blog/articles/feature-latest-articles/src/lib/feature-latest-articles/feature-latest-articles.component.html +++ b/libs/blog/articles/feature-latest-articles/src/lib/feature-latest-articles/feature-latest-articles.component.html @@ -37,7 +37,7 @@
-
diff --git a/libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts b/libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts index c191a4930..99821566d 100644 --- a/libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts +++ b/libs/blog/authors/ui-author-card/src/lib/author-card/author-card-template.component.ts @@ -1,36 +1,35 @@ -import { Component } from '@angular/core'; +import { Component, input } from '@angular/core'; import { CardComponent, CardContentDirective, + GradientCardDirective, } from '@angular-love/blog/shared/ui-card'; @Component({ selector: 'al-author-card-template', - standalone: true, - imports: [CardComponent, CardContentDirective], + imports: [CardComponent, CardContentDirective, GradientCardDirective], host: { class: 'block @container', }, template: ` - +
- -
+
@@ -38,4 +37,6 @@ import { `, }) -export class AuthorCardTemplateComponent {} +export class AuthorCardTemplateComponent { + hideGradient = input(true); +} diff --git a/libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.html b/libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.html index 08807e6b8..0ac69c2d8 100644 --- a/libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.html +++ b/libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.html @@ -1,5 +1,5 @@
- + @if (linkable()) { diff --git a/libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.ts b/libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.ts index 5ea188951..755fc34df 100644 --- a/libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.ts +++ b/libs/blog/authors/ui-author-card/src/lib/author-card/author-card.component.ts @@ -45,6 +45,7 @@ export class AuthorCardComponent { clampText = input(); linkable = input(false); + hideGradient = input(false); descriptionClass = computed( () => 'text-sm' + (this.clampText() ? ' line-clamp-3' : ''), diff --git a/libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-social-media-icons.component.ts b/libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-social-media-icons.component.ts index 5f2975052..dcfa03f32 100644 --- a/libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-social-media-icons.component.ts +++ b/libs/blog/layouts/ui-layouts/src/lib/footer/components/footer-social-media-icons.component.ts @@ -13,7 +13,7 @@ import { SocialMediaIconsComponent } from '@angular-love/blog/shared/ui-social-m > Social media

- +
`, changeDetection: ChangeDetectionStrategy.OnPush, diff --git a/libs/blog/shared/ui-button/src/lib/button/button.component.ts b/libs/blog/shared/ui-button/src/lib/button/button.component.ts index eca33edd9..c391f3abe 100644 --- a/libs/blog/shared/ui-button/src/lib/button/button.component.ts +++ b/libs/blog/shared/ui-button/src/lib/button/button.component.ts @@ -21,7 +21,7 @@ const buttonVariants = cva( { variants: { variant: >{ - Primary: 'bg-al-primary/90 text-white font-bold uppercase', + Primary: 'bg-al-primary/90 text-white uppercase', Secondary: 'bg-al-background border', Outline: 'border border-al-primary/90 bg-white text-al-primary', Ghost: 'bg-transparent', diff --git a/libs/blog/shared/ui-card/src/lib/card.component.ts b/libs/blog/shared/ui-card/src/lib/card.component.ts index 218f08e19..573bfe209 100644 --- a/libs/blog/shared/ui-card/src/lib/card.component.ts +++ b/libs/blog/shared/ui-card/src/lib/card.component.ts @@ -65,12 +65,15 @@ export class CardLinkableDirective { @Directive({ standalone: true, selector: 'al-card[alGradientCard]', + host: { + '[class.bg-al-radial-gradient]': '!hideGradient()', + }, }) export class GradientCardDirective { + hideGradient = input(false); + @HostBinding('class') - get hostClasses() { - return 'bg-al-radial-gradient dark:bg-al-background'; - } + hostClasses = 'dark:bg-al-background'; } @Directive({ diff --git a/libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.html b/libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.html index f4244a0df..b69855a48 100644 --- a/libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.html +++ b/libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.html @@ -2,7 +2,7 @@ @for (social of socials; track $index) {
  • diff --git a/libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.ts b/libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.ts index 7fcd41e9d..fc99d3727 100644 --- a/libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.ts +++ b/libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.ts @@ -1,4 +1,10 @@ -import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + computed, + inject, + input, +} from '@angular/core'; import { TranslocoService } from '@jsverse/transloco'; import { @@ -6,6 +12,8 @@ import { SocialMediaIconItemUi, } from './social-media-icon-item.component'; +export type SocialMediaIconsVariant = 'light' | 'dark' | 'default'; + @Component({ selector: 'al-social-media-icons', templateUrl: './social-media-icons.component.html', @@ -16,6 +24,16 @@ import { export class SocialMediaIconsComponent { private _transloco = inject(TranslocoService); + variant = input('default'); + + readonly iconColorClass = computed(() => { + return this.variant() === 'default' + ? 'ext-al-primary-foreground' + : this.variant() === 'light' + ? 'text-[#fff]' + : 'text-[#000]'; + }); + readonly socials: SocialMediaIconItemUi[] = [ { usernameOrPageId: 'www.angular.love', diff --git a/libs/shared/assets/src/lib/styles/main.scss b/libs/shared/assets/src/lib/styles/main.scss index 010c8a925..97571861a 100644 --- a/libs/shared/assets/src/lib/styles/main.scss +++ b/libs/shared/assets/src/lib/styles/main.scss @@ -4,9 +4,6 @@ @tailwind components; @tailwind utilities; -@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *)); -@custom-variant light (&:where([data-theme="light"], [data-theme="light"] *)); - @layer base { :root[data-theme='dark'] { --primary: 255 0 106; diff --git a/tailwind.preset.js b/tailwind.preset.js index dd6e7ee8e..59e7289ff 100644 --- a/tailwind.preset.js +++ b/tailwind.preset.js @@ -1,3 +1,5 @@ +const { themeVariants } = require('tailwindcss-theme-variants'); + /** @type {import('tailwindcss').Config} */ module.exports = { darkMode: 'selector', @@ -46,4 +48,13 @@ module.exports = { }, }, }, + plugins: [ + function ({ addVariant }) { + addVariant( + 'light', + '&:where([data-theme="light"], [data-theme="light"] *)', + ); + addVariant('dark', '&:where([data-theme="dark"], [data-theme="dark"] *)'); + }, + ], }; From 5fccbda9aa37826fbf5208f615ffead56fbd902c Mon Sep 17 00:00:00 2001 From: Marcin Stelmaszyk Date: Thu, 5 Jun 2025 12:25:44 +0200 Subject: [PATCH 09/11] fix: typo --- .../src/lib/social-media-icons.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.ts b/libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.ts index fc99d3727..c59d4adc8 100644 --- a/libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.ts +++ b/libs/blog/shared/ui-social-media-icons/src/lib/social-media-icons.component.ts @@ -28,7 +28,7 @@ export class SocialMediaIconsComponent { readonly iconColorClass = computed(() => { return this.variant() === 'default' - ? 'ext-al-primary-foreground' + ? 'text-al-primary-foreground' : this.variant() === 'light' ? 'text-[#fff]' : 'text-[#000]'; From e957263eb43e5ed0d23a693f0b423f96a260e35d Mon Sep 17 00:00:00 2001 From: DamianBrzezinskiHoA Date: Tue, 12 Aug 2025 14:09:51 +0200 Subject: [PATCH 10/11] fix(client): fixed issue with author card in article --- .../article-details.component.html | 1 + .../author-card-template.component.ts | 21 +++++++++++++++---- .../author-card/author-card.component.html | 5 ++++- .../lib/author-card/author-card.component.ts | 1 + 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/libs/blog/articles/feature-article/src/lib/article-details/article-details.component.html b/libs/blog/articles/feature-article/src/lib/article-details/article-details.component.html index 6ea00f3ba..60b0596b2 100644 --- a/libs/blog/articles/feature-article/src/lib/article-details/article-details.component.html +++ b/libs/blog/articles/feature-article/src/lib/article-details/article-details.component.html @@ -53,6 +53,7 @@