Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added apps/blog/src/assets/HOA_logo_blue.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/blog/src/assets/HOA_logo_white.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 14 additions & 3 deletions apps/blog/src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@
"recommended": "Recommended Articles",
"angularNews": "Angular News",
"guides": "Guides",
"partners": "Community partners",
"mainPartner": "Main partner",
"angularInDepth": "Angular In Depth",
"articleTypes": "Article types",
"categories": {
"all": "Latest",
"news": "News",
Expand All @@ -24,16 +23,27 @@
"home": "Home Page",
"about": "About us",
"meetups": "Angular Meetups",
"guides": "Angular Guides",
"news": "Angular News",
"in_depth": "In-Depth articles",
"partnership": "Let's discuss partnership",
"become_author": "Become an author",
"newsletter": "Angular.letter",
"navLinks": "Navigation links",
"roadmap": "Roadmap",
"toggle_theme": "Toggle theme",
"open_search_dialog": "Open search dialog",
"languagePicker": {
"pl": "Polish",
"en": "English"
"en": "English",
"select_lang": "Select language"
}
},
"footer": {
"mainPartner": "Main partner",
"partners": "Community partners",
"al-description": "This is the place where you can learn Angular, discover best practices, and stay updated with the latest news and trends"
},
"authorPage": {
"posted_by": "Posted by {{name}}"
},
Expand Down Expand Up @@ -219,6 +229,7 @@
"changeLangToEnglish": "Change language to English"
},
"socialLinks": {
"title": "Social media",
"facebook": "Like our Facebook page",
"twitter-x": "Follow us on X (formerly Twitter)",
"linkedIn": "Follow us on LinkedIn",
Expand Down
17 changes: 14 additions & 3 deletions apps/blog/src/assets/i18n/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@
"recommended": "Polecane Artykuły",
"angularNews": "Wiadomości ze świata Angulara",
"guides": "Poradniki",
"partners": "Community partnerzy",
"mainPartner": "Główny partner",
"angularInDepth": "Angular In Depth",
"articleTypes": "Typy artykułów",
"categories": {
"all": "Najnowsze",
"news": "Nowości",
Expand All @@ -24,16 +23,27 @@
"home": "Strona Główna",
"about": "O nas",
"meetups": "Angular Meetups",
"guides": "Angular Guides",
"news": "Angular News",
"in_depth": "Artykuły In-Depth",
"partnership": "Porozmawiajmy o partnerstwie",
"become_author": "Zostań autorem",
"newsletter": "Angular.letter",
"navLinks": "Menu",
"roadmap": "Roadmap",
"toggle_theme": "Przełącz motyw",
"open_search_dialog": "Otwórz okno wyszukiwania",
"languagePicker": {
"pl": "Polski",
"en": "Angielski"
"en": "Angielski",
"select_lang": "Wybierz język"
}
},
"footer": {
"partners": "Community partnerzy",
"mainPartner": "Główny partner",
"al-description": "To jest miejsce, w którym możesz nauczyć się Angulara, odkrywać najlepsze praktyki i być na bieżąco z najnowszymi wiadomościami i trendami"
},
"home": {
"latest": "Latest articles"
},
Expand Down Expand Up @@ -222,6 +232,7 @@
"changeLangToEnglish": "Zmień język na angielski"
},
"socialLinks": {
"title": "Media społecznościowe",
"facebook": "Polub nas na Facebooku",
"twitter-x": "Obserwuj nas na X (dawniej Twitter)",
"linkedIn": "Obserwuj nas na LinkedInie",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
/>

<div class="flex items-center gap-1">
<fast-svg name="clock" size="16" />
<fast-svg name="clock" aria-hidden="true" size="16" />
{{ articleDetails().readingTime }} min
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,15 @@ type ShareItem = {
[href]="item.href"
target="_blank"
>
<fast-svg class="text-al-foreground" [name]="item.icon" size="28" />
<fast-svg
aria-hidden="true"
class="text-al-foreground"
[name]="item.icon"
size="28"
/>
</a>
}
<a
role="button"
<button
[attr.aria-label]="t('articleShareIcons.urlAriaLabel')"
[class.url-icon-animated]="animating()"
[cdkCopyToClipboard]="articleUrl()"
Expand All @@ -43,17 +47,19 @@ type ShareItem = {
>
<fast-svg
name="link"
aria-hidden="true"
class="text-al-foreground"
[class.!hidden]="animating()"
size="28"
/>
<fast-svg
name="circle-check"
aria-hidden="true"
class="text-al-foreground"
[class.!hidden]="!animating()"
size="28"
/>
</a>
</button>
</div>
`,
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
<ng-container *transloco="let t; read: 'homePage'">
<section class="flex justify-center gap-3">
<div
role="tablist"
class="flex justify-center gap-3"
[attr.aria-label]="t('articleTypes')"
>
@for (category of categories(); track $index) {
<button
alPill
alFocusableItem
[tabindex]="selected().name === category.name ? 0 : -1"
role="tab"
[variant]="category.name === selected().name ? 'flat' : 'outline'"
(click)="selected.set(category)"
(keydown)="onPillKeydown($event)"
>
{{ t(category.translationPath) }}
</button>
}
</section>
</div>

<section
class="mb-6 mt-6 grid grid-cols-1 gap-x-4 gap-y-4 md:grid-cols-2 md:gap-x-8 lg:grid-cols-3 lg:gap-y-8"
Expand All @@ -24,21 +32,28 @@
[imagePriority]="i < 2 ? 1 : null"
cardType="regular"
/>
@if (i === 1) {
<ng-container *ngTemplateOutlet="newsletterCard" />
}
}
} @else {
<al-article-regular-card-skeleton *alRepeat="take" />
<ng-container *ngTemplateOutlet="newsletterCard" />
}
<al-card
alGradientCard
class="md:max-lg:col-span-2 lg:col-start-3 lg:row-start-1"
>
<al-newsletter alCardContent />
</al-card>
</section>

<div class="flex justify-center gap-3">
<button al-button role="link" [routerLink]="selected().link" size="medium">
{{ t('categories.showAll', { category: t(selected().translationPath) }) }}
</button>
</div>

<ng-template #newsletterCard>
<al-card
alGradientCard
class="md:max-lg:col-span-2 lg:col-start-3 lg:row-start-1"
>
<al-newsletter alCardContent />
</al-card>
</ng-template>
</ng-container>
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { NgClass } from '@angular/common';
import { FocusKeyManager } from '@angular/cdk/a11y';
import { NgClass, NgTemplateOutlet } from '@angular/common';
import {
AfterViewInit,
ChangeDetectionStrategy,
Component,
computed,
inject,
linkedSignal,
QueryList,
ViewChildren,
} from '@angular/core';
import { RouterLink } from '@angular/router';
import { TranslocoDirective } from '@jsverse/transloco';
Expand All @@ -22,6 +26,7 @@ import {
} from '@angular-love/blog/shared/ui-card';
import { PillDirective } from '@angular-love/blog/shared/ui-pill';
import { ArticleCategory } from '@angular-love/contracts/articles';
import { FocusableItemDirective } from '@angular-love/ui-focusable';
import { RepeatDirective } from '@angular-love/utils';

import { CategoryListItem, injectCategories } from './categories.const';
Expand All @@ -36,19 +41,21 @@ import { CategoryListItem, injectCategories } from './categories.const';
CardComponent,
GradientCardDirective,
NgClass,
NgTemplateOutlet,
TranslocoDirective,
ArticleRegularCardSkeletonComponent,
RepeatDirective,
RouterLink,
ButtonComponent,
PillDirective,
FocusableItemDirective,
],
host: {
'data-testid': 'latest-articles-container',
},
providers: [ArticleListStore],
})
export class FeatureLatestArticlesComponent {
export class FeatureLatestArticlesComponent implements AfterViewInit {
readonly selectedCategorySlug = computed<ArticleCategory | null>(
() => this.selected().slug,
);
Expand All @@ -57,6 +64,11 @@ export class FeatureLatestArticlesComponent {
() => this.categories()[0],
);

@ViewChildren(FocusableItemDirective)
private readonly _focusableItems!: QueryList<FocusableItemDirective>;

private _keyManager!: FocusKeyManager<FocusableItemDirective>;

readonly take = 8;

private readonly _articleListStore = inject(ArticleListStore);
Expand All @@ -80,4 +92,17 @@ export class FeatureLatestArticlesComponent {

this._articleListStore.fetchArticleList(query);
}

ngAfterViewInit(): void {
this._keyManager = new FocusKeyManager(this._focusableItems)
.withWrap()
.withHorizontalOrientation('ltr');

// Set initial active item
this._keyManager.setActiveItem(0);
}

onPillKeydown(event: KeyboardEvent) {
this._keyManager.onKeydown(event);
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
<a [routerLink]="['/', article().slug] | alLocalize">
<article
class="relative h-full overflow-hidden rounded-lg bg-black bg-cover bg-no-repeat transition-transform hover:scale-105 motion-reduce:transition-none motion-reduce:hover:scale-100"
[attr.aria-labelledby]="article().slug"
>
<img
alt=""
class="absolute h-auto w-full bg-contain opacity-20"
[ngSrc]="article().featuredImageUrl || 'assets/article-placeholder.webp'"
[priority]="imagePriority()"
width="1215"
height="750"
/>
<div class="relative flex h-full flex-col justify-between text-[#fff]">
<article
class="h-full rounded-lg bg-cover bg-no-repeat transition-transform hover:scale-105 motion-reduce:transition-none motion-reduce:hover:scale-100"
[style.background-image]="
'url(' +
(article().featuredImageUrl || 'assets/article-placeholder.webp') +
')'
"
[attr.aria-labelledby]="article().slug"
>
<a [routerLink]="['/', article().slug] | alLocalize">
<div
class="bg-al-background relative flex h-full flex-col justify-between opacity-85"
>
<div
class="hover:bg-al-bottom-radial-gradient absolute h-full w-full"
></div>
Expand Down Expand Up @@ -48,5 +47,5 @@ <h3 class="line-clamp-2 text-2xl font-bold" [id]="article().slug">
</p>
</div>
</div>
</article>
</a>
</a>
</article>
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
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';
Expand All @@ -10,13 +9,7 @@ import { AvatarComponent } from '@angular-love/blog/shared/ui-avatar';
@Component({
selector: 'al-article-compact-card',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [
AvatarComponent,
RouterLink,
AlLocalizePipe,
FastSvgComponent,
NgOptimizedImage,
],
imports: [AvatarComponent, RouterLink, AlLocalizePipe, FastSvgComponent],
templateUrl: './article-compact-card.component.html',
})
export class ArticleCompactCardComponent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
</span>
<al-difficulty [difficulty]="article().difficulty" />
<span class="flex w-full flex-row items-center justify-end gap-2">
<fast-svg name="clock" size="16" />
<fast-svg name="clock" aria-hidden="true" size="16" />
<time
class="text-sm/[14px]"
[attr.datetime]="'PT' + article().readingTime + 'M'"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
<a [routerLink]="['/', article().slug] | alLocalize">
<a
[attr.aria-label]="article().title"
[routerLink]="['/', article().slug] | alLocalize"
>
<article
class="light:border group relative flex h-full w-full flex-row rounded-lg shadow-none"
[attr.aria-labelledby]="article().slug"
>
<img
alt="Post featured image"
alt=""
class="hidden h-auto w-auto rounded-l-lg bg-contain lg:block"
[ngSrc]="article().featuredImageUrl || 'assets/article-placeholder.webp'"
[priority]="imagePriority()"
Expand All @@ -27,7 +30,7 @@
<span class="hidden text-sm/[14px] lg:block">
{{ article().publishDate | date: 'dd MMM yyyy' }}
</span>
<fast-svg name="clock" size="16" />
<fast-svg name="clock" aria-hidden="true" size="16" />
<time
class="text-sm/[14px]"
[attr.datetime]="'PT' + article().readingTime + 'M'"
Expand Down
Loading