Skip to content

Commit 419b04c

Browse files
feat(blog): icon to share article by url (#267)
1 parent 3c3af74 commit 419b04c

File tree

5 files changed

+62
-15
lines changed

5 files changed

+62
-15
lines changed

apps/blog/src/assets/i18n/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@
100100
"title": "Share this post",
101101
"twitterAriaLabel": "Share on Twitter",
102102
"facebookAriaLabel": "Share on Facebook",
103-
"linkedInAriaLabel": "Share on LinkedIn"
103+
"linkedInAriaLabel": "Share on LinkedIn",
104+
"urlAriaLabel": "Copy URL"
104105
},
105106
"dynamicTextClamp": {
106107
"readMore": "Read more",

apps/blog/src/assets/i18n/pl.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@
103103
"title": "Podziel się artykułem",
104104
"twitterAriaLabel": "Udostępnij na Twitterze",
105105
"facebookAriaLabel": "Udostępnij na Facebooku",
106-
"linkedInAriaLabel": "Udostępnij na LinkedIn"
106+
"linkedInAriaLabel": "Udostępnij na LinkedIn",
107+
"urlAriaLabel": "Skopiuj URL"
107108
},
108109
"dynamicTextClamp": {
109110
"readMore": "Czytaj więcej",

apps/blog/src/assets/icons/link.svg

Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
.url-icon-animated {
2+
animation: icon 1s forwards;
3+
animation-iteration-count: 1;
4+
}
5+
6+
@keyframes icon {
7+
0% {
8+
transform: scale(1);
9+
}
10+
50% {
11+
transform: scale(0.8);
12+
}
13+
100% {
14+
transform: scale(1);
15+
}
16+
}

libs/blog/articles/feature-article/src/lib/article-share-icons/article-share-icons.component.ts

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { Component, computed, input } from '@angular/core';
1+
import { CdkCopyToClipboard } from '@angular/cdk/clipboard';
2+
import { Component, computed, input, signal } from '@angular/core';
23
import { TranslocoDirective } from '@jsverse/transloco';
34
import { FastSvgComponent } from '@push-based/ngx-fast-svg';
45

5-
import { IconComponent, IconType } from '@angular-love/blog/shared/ui-icon';
6+
import { IconType } from '@angular-love/blog/shared/ui-icon';
67

78
type ShareItem = {
89
href: string;
@@ -13,16 +14,16 @@ type ShareItem = {
1314
@Component({
1415
standalone: true,
1516
selector: 'al-article-share-icons',
16-
imports: [IconComponent, TranslocoDirective, FastSvgComponent],
17+
imports: [TranslocoDirective, FastSvgComponent, CdkCopyToClipboard],
18+
styleUrls: ['./article-share-icons.component.scss'],
1719
template: `
18-
<div class="flex items-center gap-4">
19-
<span *transloco="let t" class="text-lg font-bold">
20+
<div *transloco="let t" class="flex items-center gap-4">
21+
<span class="text-lg font-bold">
2022
{{ t('articleShareIcons.title') }}
2123
</span>
2224
2325
@for (item of items(); track $index) {
2426
<a
25-
*transloco="let t"
2627
role="button"
2728
[attr.aria-label]="t(item.ariaLabel)"
2829
[href]="item.href"
@@ -31,19 +32,46 @@ type ShareItem = {
3132
<fast-svg class="text-al-foreground" [name]="item.icon" size="28" />
3233
</a>
3334
}
35+
<a
36+
role="button"
37+
[attr.aria-label]="t('articleShareIcons.urlAriaLabel')"
38+
[class.url-icon-animated]="animating()"
39+
[cdkCopyToClipboard]="articleUrl()"
40+
(click)="animating.set(true)"
41+
(animationend)="animating.set(false)"
42+
target="_blank"
43+
>
44+
<fast-svg
45+
name="link"
46+
class="text-al-foreground"
47+
[class.!hidden]="animating()"
48+
size="28"
49+
/>
50+
<fast-svg
51+
name="circle-check"
52+
class="text-al-foreground"
53+
[class.!hidden]="!animating()"
54+
size="28"
55+
/>
56+
</a>
3457
</div>
3558
`,
3659
})
3760
export class ArticleShareIconsComponent {
38-
slug = input.required<string>();
39-
title = input.required<string>();
40-
language = input.required<string>();
61+
readonly slug = input.required<string>();
62+
readonly title = input.required<string>();
63+
readonly language = input.required<string>();
64+
65+
readonly animating = signal(false);
66+
67+
readonly articleUrl = computed(() =>
68+
this.language() === 'pl_PL'
69+
? `https://angular.love/${this.slug()}`
70+
: `https://angular.love/en/${this.slug()}`,
71+
);
4172

4273
readonly items = computed<ShareItem[]>(() => {
43-
const url =
44-
this.language() === 'pl_PL'
45-
? `https://angular.love/${this.slug()}`
46-
: `https://angular.love/en/${this.slug()}`;
74+
const url = this.articleUrl();
4775
const text = encodeURIComponent(this.title());
4876

4977
return [

0 commit comments

Comments
 (0)