diff --git a/projects/cdk/constants/used-icons.ts b/projects/cdk/constants/used-icons.ts index 3cc8794ce6a3..ecb56346750f 100644 --- a/projects/cdk/constants/used-icons.ts +++ b/projects/cdk/constants/used-icons.ts @@ -46,6 +46,8 @@ export const TUI_USED_ICONS = [ '@tui.file', '@tui.trash', '@tui.phone', + '@tui.heart', + '@tui.heart-filled', '@tui.star', '@tui.calendar', '@tui.rotate-ccw-square', diff --git a/projects/demo-playwright/tests/kit/like/like.spec.ts b/projects/demo-playwright/tests/kit/like/like.spec.ts new file mode 100644 index 000000000000..e78db687c6a8 --- /dev/null +++ b/projects/demo-playwright/tests/kit/like/like.spec.ts @@ -0,0 +1,70 @@ +import {DemoRoute} from '@demo/routes'; +import {TuiDocumentationPagePO, tuiGoto} from '@demo-playwright/utils'; +import {expect, test} from '@playwright/test'; + +test.describe('TuiLike', () => { + test.describe('Examples', () => { + test('Basic like', async ({page}) => { + await tuiGoto(page, DemoRoute.Like); + const example = new TuiDocumentationPagePO(page).getExample('#basic'); + + await example.locator('[tuiLike]').first().click(); + + await expect(example).toHaveScreenshot('01-basic-like.png'); + }); + + test('External icon loads', async ({page}) => { + await tuiGoto(page, DemoRoute.Like); + const example = new TuiDocumentationPagePO(page).getExample( + '#external-icons', + ); + + await example.locator('[tuiLike]').first().click(); + + await expect(example).toHaveScreenshot('02-external-icon-like.png'); + }); + + test('Other appearances hover', async ({page}) => { + await tuiGoto(page, DemoRoute.Like); + const example = new TuiDocumentationPagePO(page).getExample( + '#other-appearances', + ); + + await example.locator('[tuiLike]').nth(1).hover(); + + await expect(example).toHaveScreenshot('03-other-appearances-hover-like.png'); + }); + + test('Other appearances click', async ({page}) => { + await tuiGoto(page, DemoRoute.Like); + const example = new TuiDocumentationPagePO(page).getExample( + '#other-appearances', + ); + + await example.locator('[tuiLike]').nth(1).click(); + + await expect(example).toHaveScreenshot('04-other-appearances-click-like.png'); + }); + + test('With forms click', async ({page}) => { + await tuiGoto(page, DemoRoute.Like); + const example = new TuiDocumentationPagePO(page).getExample('#with-forms'); + + await example.locator('[tuiLike]').nth(0).click(); + + await expect(example).toHaveScreenshot( + '05-with-forms-ngModel-click-like.png', + ); + + await example.locator('[tuiLike]').nth(1).click(); + + await expect(example).toHaveScreenshot( + '06-with-forms-reactive-forms-click-like.png', + ); + + await example.locator('[tuiButton]').click(); + + await expect(example).toHaveScreenshot('07-with-forms-click-toggle.png'); + }); + }); +}); diff --git a/projects/demo/src/modules/app/app.routes.ts b/projects/demo/src/modules/app/app.routes.ts index 592439abb41d..da38a03588ea 100644 --- a/projects/demo/src/modules/app/app.routes.ts +++ b/projects/demo/src/modules/app/app.routes.ts @@ -479,6 +479,11 @@ export const ROUTES: Routes = [ loadComponent: async () => import('../components/line-clamp'), title: 'LineClamp', }), + route({ + path: DemoRoute.Like, + loadComponent: async () => import('../components/like'), + title: 'Like', + }), route({ path: DemoRoute.Link, loadComponent: async () => import('../components/link'), diff --git a/projects/demo/src/modules/app/demo-routes.ts b/projects/demo/src/modules/app/demo-routes.ts index 97d819ed51ea..e2f330554d80 100644 --- a/projects/demo/src/modules/app/demo-routes.ts +++ b/projects/demo/src/modules/app/demo-routes.ts @@ -117,6 +117,7 @@ export const DemoRoute = { Status: '/components/status', Stepper: '/navigation/stepper', Preview: '/components/preview', + Like: '/components/like', AppBar: '/navigation/app-bar', TabBar: '/navigation/tab-bar', Tabs: '/navigation/tabs', diff --git a/projects/demo/src/modules/app/pages.ts b/projects/demo/src/modules/app/pages.ts index 9d38332969bf..bfbcb7df8e91 100644 --- a/projects/demo/src/modules/app/pages.ts +++ b/projects/demo/src/modules/app/pages.ts @@ -601,6 +601,12 @@ export const pages: TuiDocRoutePages = [ keywords: 'лэйбл, метка, форма, label', route: DemoRoute.Label, }, + { + section: 'Components', + title: 'Like', + keywords: 'like, лайк, эмодзи, смайлик, стикер', + route: DemoRoute.Like, + }, { section: 'Components', title: 'LineClamp', diff --git a/projects/demo/src/modules/components/like/examples/1/index.html b/projects/demo/src/modules/components/like/examples/1/index.html new file mode 100644 index 000000000000..e319c40e503a --- /dev/null +++ b/projects/demo/src/modules/components/like/examples/1/index.html @@ -0,0 +1,12 @@ + + + diff --git a/projects/demo/src/modules/components/like/examples/1/index.ts b/projects/demo/src/modules/components/like/examples/1/index.ts new file mode 100644 index 000000000000..bfe0f7ac09bd --- /dev/null +++ b/projects/demo/src/modules/components/like/examples/1/index.ts @@ -0,0 +1,14 @@ +import {Component} from '@angular/core'; +import {changeDetection} from '@demo/emulate/change-detection'; +import {encapsulation} from '@demo/emulate/encapsulation'; +import {TuiLike} from '@taiga-ui/kit'; + +@Component({ + standalone: true, + imports: [TuiLike], + templateUrl: './index.html', + styles: [':host { display: flex; gap: 1rem; align-items: center; }'], + encapsulation, + changeDetection, +}) +export default class Example {} diff --git a/projects/demo/src/modules/components/like/examples/2/index.html b/projects/demo/src/modules/components/like/examples/2/index.html new file mode 100644 index 000000000000..22e42411c38e --- /dev/null +++ b/projects/demo/src/modules/components/like/examples/2/index.html @@ -0,0 +1,4 @@ + diff --git a/projects/demo/src/modules/components/like/examples/2/index.ts b/projects/demo/src/modules/components/like/examples/2/index.ts new file mode 100644 index 000000000000..57a27af142a8 --- /dev/null +++ b/projects/demo/src/modules/components/like/examples/2/index.ts @@ -0,0 +1,19 @@ +import {Component} from '@angular/core'; +import {changeDetection} from '@demo/emulate/change-detection'; +import {encapsulation} from '@demo/emulate/encapsulation'; +import {TuiLike, tuiLikeOptionsProvider} from '@taiga-ui/kit'; + +@Component({ + standalone: true, + imports: [TuiLike], + templateUrl: './index.html', + styles: [':host { display: flex; gap: 1rem; align-items: center; }'], + encapsulation, + changeDetection, + providers: [ + tuiLikeOptionsProvider({ + icons: {unchecked: '@tui.star', checked: '@tui.star-filled'}, + }), + ], +}) +export default class Example {} diff --git a/projects/demo/src/modules/components/like/examples/3/index.html b/projects/demo/src/modules/components/like/examples/3/index.html new file mode 100644 index 000000000000..d5bd4ad8a7a1 --- /dev/null +++ b/projects/demo/src/modules/components/like/examples/3/index.html @@ -0,0 +1,4 @@ + diff --git a/projects/demo/src/modules/components/like/examples/3/index.ts b/projects/demo/src/modules/components/like/examples/3/index.ts new file mode 100644 index 000000000000..1057a41f6acb --- /dev/null +++ b/projects/demo/src/modules/components/like/examples/3/index.ts @@ -0,0 +1,23 @@ +import {Component} from '@angular/core'; +import {changeDetection} from '@demo/emulate/change-detection'; +import {encapsulation} from '@demo/emulate/encapsulation'; +import {TuiLike, tuiLikeOptionsProvider} from '@taiga-ui/kit'; + +@Component({ + standalone: true, + imports: [TuiLike], + templateUrl: './index.html', + styles: [':host { display: flex; gap: 1rem; align-items: center; }'], + encapsulation, + changeDetection, + providers: [ + tuiLikeOptionsProvider({ + icons: { + unchecked: + 'https://raw.githubusercontent.com/MarsiBarsi/readme-icons/main/github.svg', + checked: 'https://cdn-icons-png.flaticon.com/64/12710/12710759.png', + }, + }), + ], +}) +export default class Example {} diff --git a/projects/demo/src/modules/components/like/examples/4/index.html b/projects/demo/src/modules/components/like/examples/4/index.html new file mode 100644 index 000000000000..f9223a0f4ee5 --- /dev/null +++ b/projects/demo/src/modules/components/like/examples/4/index.html @@ -0,0 +1,6 @@ + diff --git a/projects/demo/src/modules/components/like/examples/4/index.ts b/projects/demo/src/modules/components/like/examples/4/index.ts new file mode 100644 index 000000000000..bc1a6a381945 --- /dev/null +++ b/projects/demo/src/modules/components/like/examples/4/index.ts @@ -0,0 +1,17 @@ +import {NgForOf} from '@angular/common'; +import {Component} from '@angular/core'; +import {changeDetection} from '@demo/emulate/change-detection'; +import {encapsulation} from '@demo/emulate/encapsulation'; +import {TuiLike} from '@taiga-ui/kit'; + +@Component({ + standalone: true, + imports: [NgForOf, TuiLike], + templateUrl: './index.html', + styles: [':host { display: flex; gap: 1rem; align-items: center; }'], + encapsulation, + changeDetection, +}) +export default class Example { + protected readonly appearances = ['error', 'success', 'warning', 'flat'] as const; +} diff --git a/projects/demo/src/modules/components/like/examples/5/index.html b/projects/demo/src/modules/components/like/examples/5/index.html new file mode 100644 index 000000000000..dcb5da6c07e3 --- /dev/null +++ b/projects/demo/src/modules/components/like/examples/5/index.html @@ -0,0 +1,35 @@ +
NgModel
+ + + +Liked: {{ liked }}
+Reactive form
+ + + +Liked: {{ likeForm.value.liked }}
+
+ A like component based on native checkbox with icons and custom color for icon when
+ :checked
+ state.
+