diff --git a/projects/elonkit/src/public-api.ts b/projects/elonkit/src/public-api.ts index 99ebc1a5..a2131391 100644 --- a/projects/elonkit/src/public-api.ts +++ b/projects/elonkit/src/public-api.ts @@ -5,5 +5,5 @@ export * from './ui/inline-form-field'; export * from './ui/paginator'; export * from './ui/timepicker'; export * from './ui/action-heading'; - +export * from './ui/tag'; export * from './ui/locale'; diff --git a/projects/elonkit/src/ui/tag/__specs__/tag.spec.ts b/projects/elonkit/src/ui/tag/__specs__/tag.spec.ts new file mode 100644 index 00000000..599a9e0d --- /dev/null +++ b/projects/elonkit/src/ui/tag/__specs__/tag.spec.ts @@ -0,0 +1,70 @@ +import { render } from '@testing-library/angular'; +import { ESTagModule, ESTagComponent } from '..'; +import { Component } from '@angular/core'; + +@Component({ + template: ` Tag ` +}) +class ESTagWrapperdComponent {} + +describe('Tag', () => { + it('Should show content', async () => { + const component = await render(ESTagWrapperdComponent, { + imports: [ESTagModule] + }); + + expect(component.getByText('Tag')).toBeInTheDocument(); + }); + + it('Should show with default colors', async () => { + const component = await render(ESTagComponent, { + imports: [ESTagModule], + excludeComponentDeclaration: true + }); + + expect(component.fixture.nativeElement.querySelector('.es-tag').style.backgroundColor).toBe( + 'rgb(0, 0, 0)' + ); + expect(component.fixture.nativeElement.querySelector('.es-tag__text').style.color).toBe( + 'rgb(255, 255, 255)' + ); + }); + + it('Should change colors', async () => { + const component = await render(ESTagComponent, { + imports: [ESTagModule], + excludeComponentDeclaration: true, + componentProperties: { + color: 'rgb(255, 255, 1)', + textColor: 'rgb(255, 255, 2)' + } + }); + + expect(component.fixture.nativeElement.querySelector('.es-tag').style.backgroundColor).toBe( + 'rgb(255, 255, 1)' + ); + expect(component.fixture.nativeElement.querySelector('.es-tag__text').style.color).toBe( + 'rgb(255, 255, 2)' + ); + }); + + it('Should show right icon', async () => { + const component = await render(ESTagComponent, { + imports: [ESTagModule], + excludeComponentDeclaration: true, + componentProperties: { + icon: 'info' + } + }); + + expect(component.fixture.componentInstance.currentIcon).toEqual({ icon: 'info' }); + + component.fixture.componentInstance.icon = null; + component.fixture.componentInstance.svgIcon = 'test'; + expect(component.fixture.componentInstance.currentIcon).toEqual({ svgIcon: 'test' }); + + component.fixture.componentInstance.icon = 'info'; + component.fixture.componentInstance.svgIcon = 'test'; + expect(component.fixture.componentInstance.currentIcon).toEqual({ icon: 'info' }); + }); +}); diff --git a/projects/elonkit/src/ui/tag/__stories__/tag-story-basic/index.ts b/projects/elonkit/src/ui/tag/__stories__/tag-story-basic/index.ts new file mode 100644 index 00000000..fbe125e1 --- /dev/null +++ b/projects/elonkit/src/ui/tag/__stories__/tag-story-basic/index.ts @@ -0,0 +1 @@ +export { TAG_STORY_BASIC_SOURCE } from './tag-story-basic.source'; diff --git a/projects/elonkit/src/ui/tag/__stories__/tag-story-basic/tag-story-basic.source.ts b/projects/elonkit/src/ui/tag/__stories__/tag-story-basic/tag-story-basic.source.ts new file mode 100644 index 00000000..3955a6c1 --- /dev/null +++ b/projects/elonkit/src/ui/tag/__stories__/tag-story-basic/tag-story-basic.source.ts @@ -0,0 +1,5 @@ +export const TAG_STORY_BASIC_SOURCE = { + html: ` + {{content}} + ` +}; diff --git a/projects/elonkit/src/ui/tag/__stories__/tag-story-svg-icon/index.ts b/projects/elonkit/src/ui/tag/__stories__/tag-story-svg-icon/index.ts new file mode 100644 index 00000000..e885dfee --- /dev/null +++ b/projects/elonkit/src/ui/tag/__stories__/tag-story-svg-icon/index.ts @@ -0,0 +1,3 @@ +export { TAG_STORY_SVG_ICON_SOURCE } from './tag-story-svg-icon.source'; +export { TagStorySvgIconModule } from './tag-story-svg-icon.module'; +export { TagStorySvgIconComponent } from './tag-story-svg-icon.component'; diff --git a/projects/elonkit/src/ui/tag/__stories__/tag-story-svg-icon/tag-story-svg-icon.component.ts b/projects/elonkit/src/ui/tag/__stories__/tag-story-svg-icon/tag-story-svg-icon.component.ts new file mode 100644 index 00000000..c15bd3a2 --- /dev/null +++ b/projects/elonkit/src/ui/tag/__stories__/tag-story-svg-icon/tag-story-svg-icon.component.ts @@ -0,0 +1,20 @@ +import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; +import { MatIconRegistry } from '@angular/material/icon'; +import { DomSanitizer } from '@angular/platform-browser'; + +@Component({ + selector: 'es-tag-story-svg-icon', + template: `{{ content }}`, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TagStorySvgIconComponent { + @Input() + public content: string; + + constructor(private matIconRegistry: MatIconRegistry, private domSanitizer: DomSanitizer) { + this.matIconRegistry.addSvgIcon( + 'warning', + this.domSanitizer.bypassSecurityTrustResourceUrl('/icons/alert/warning.svg') + ); + } +} diff --git a/projects/elonkit/src/ui/tag/__stories__/tag-story-svg-icon/tag-story-svg-icon.module.ts b/projects/elonkit/src/ui/tag/__stories__/tag-story-svg-icon/tag-story-svg-icon.module.ts new file mode 100644 index 00000000..20c0285e --- /dev/null +++ b/projects/elonkit/src/ui/tag/__stories__/tag-story-svg-icon/tag-story-svg-icon.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { HttpClientModule } from '@angular/common/http'; +import { TagStorySvgIconComponent } from './tag-story-svg-icon.component'; +import { ESTagModule } from '../..'; + +@NgModule({ + declarations: [TagStorySvgIconComponent], + imports: [CommonModule, HttpClientModule, ESTagModule], + exports: [TagStorySvgIconComponent] +}) +export class TagStorySvgIconModule {} diff --git a/projects/elonkit/src/ui/tag/__stories__/tag-story-svg-icon/tag-story-svg-icon.source.ts b/projects/elonkit/src/ui/tag/__stories__/tag-story-svg-icon/tag-story-svg-icon.source.ts new file mode 100644 index 00000000..92b7f89e --- /dev/null +++ b/projects/elonkit/src/ui/tag/__stories__/tag-story-svg-icon/tag-story-svg-icon.source.ts @@ -0,0 +1,5 @@ +export const TAG_STORY_SVG_ICON_SOURCE = { + html: ` + {{content}} + ` +}; diff --git a/projects/elonkit/src/ui/tag/__stories__/tag.stories.mdx b/projects/elonkit/src/ui/tag/__stories__/tag.stories.mdx new file mode 100644 index 00000000..dbba803a --- /dev/null +++ b/projects/elonkit/src/ui/tag/__stories__/tag.stories.mdx @@ -0,0 +1,78 @@ +import { Meta, Story, ArgsTable } from '@storybook/addon-docs/blocks'; +import { Canvas } from '~storybook/components'; + +import { action } from '@storybook/addon-actions'; + +import { ESTagModule, ESTagComponent } from '..'; +import { TAG_STORY_BASIC_SOURCE } from './tag-story-basic'; +import { + TagStorySvgIconModule, + TagStorySvgIconComponent, + TAG_STORY_SVG_ICON_SOURCE +} from './tag-story-svg-icon'; + + + +# Tag + +A tags primary use is to place content in context. + +## Demos + +export const getContent = (args, context) => { + return args.content || (context.globals.locale === 'en' ? 'Message' : 'Сообщение'); +}; + + + + {((args, context) => ({ + template: `{{content}}`, + moduleMetadata: { + imports: [ESTagModule] + }, + props: { + ...args, + content: getContent(args, context) + } + })).bind({})} + + + +We can use individual icons. + + + + {((args, context) => ({ + component: TagStorySvgIconComponent, + moduleMetadata: { + imports: [TagStorySvgIconModule] + }, + props: { + ...args, + content: getContent(args, context) + } + })).bind({})} + + + +## API + + diff --git a/projects/elonkit/src/ui/tag/index.ts b/projects/elonkit/src/ui/tag/index.ts new file mode 100644 index 00000000..7e1a213e --- /dev/null +++ b/projects/elonkit/src/ui/tag/index.ts @@ -0,0 +1 @@ +export * from './public-api'; diff --git a/projects/elonkit/src/ui/tag/ng-package.json b/projects/elonkit/src/ui/tag/ng-package.json new file mode 100644 index 00000000..789c95e4 --- /dev/null +++ b/projects/elonkit/src/ui/tag/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} diff --git a/projects/elonkit/src/ui/tag/public-api.ts b/projects/elonkit/src/ui/tag/public-api.ts new file mode 100644 index 00000000..7562cfc5 --- /dev/null +++ b/projects/elonkit/src/ui/tag/public-api.ts @@ -0,0 +1,2 @@ +export { ESTagComponent } from './tag.component'; +export { ESTagModule } from './tag.module'; diff --git a/projects/elonkit/src/ui/tag/tag.component.html b/projects/elonkit/src/ui/tag/tag.component.html new file mode 100644 index 00000000..836f4020 --- /dev/null +++ b/projects/elonkit/src/ui/tag/tag.component.html @@ -0,0 +1,15 @@ +
+
+ + {{ currentIcon.icon || '' }} + +
+ +
+
+
diff --git a/projects/elonkit/src/ui/tag/tag.component.scss b/projects/elonkit/src/ui/tag/tag.component.scss new file mode 100644 index 00000000..c5f71066 --- /dev/null +++ b/projects/elonkit/src/ui/tag/tag.component.scss @@ -0,0 +1,29 @@ +.es-tag { + border-radius: 4px; + padding: 3px 8px; + width: fit-content; + + &__content { + align-items: center; + display: flex; + } + + &__text { + font-size: 12px; + line-height: 16px; + } + + &__icon { + font-size: 14px; + + &.mat-icon { + height: 14px; + line-height: 14px; + width: 14px; + } + + &_display { + margin-right: 5px; + } + } +} diff --git a/projects/elonkit/src/ui/tag/tag.component.ts b/projects/elonkit/src/ui/tag/tag.component.ts new file mode 100644 index 00000000..dd346062 --- /dev/null +++ b/projects/elonkit/src/ui/tag/tag.component.ts @@ -0,0 +1,48 @@ +import { Component, ChangeDetectionStrategy, Input, ViewEncapsulation } from '@angular/core'; + +@Component({ + selector: 'es-tag', + templateUrl: './tag.component.html', + styleUrls: ['./tag.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + encapsulation: ViewEncapsulation.None +}) +export class ESTagComponent { + /** + * The background color of tag. + */ + @Input() + public color = '#000'; + + /** + * The color of text. + */ + @Input() + public textColor = '#fff'; + + /** + * The icon displayed before the text. + */ + @Input() + public icon?: string; + + /** + * + * The svg icon displayed before the text. + */ + @Input() + public svgIcon?: string; + + /** + * @internal + * @ignore + */ + public get currentIcon() { + if (this.icon) { + return { icon: this.icon }; + } + if (this.svgIcon) { + return { svgIcon: this.svgIcon }; + } + } +} diff --git a/projects/elonkit/src/ui/tag/tag.module.ts b/projects/elonkit/src/ui/tag/tag.module.ts new file mode 100644 index 00000000..08fa9331 --- /dev/null +++ b/projects/elonkit/src/ui/tag/tag.module.ts @@ -0,0 +1,11 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { MatIconModule } from '@angular/material/icon'; +import { ESTagComponent } from './tag.component'; + +@NgModule({ + imports: [CommonModule, MatIconModule], + declarations: [ESTagComponent], + exports: [ESTagComponent] +}) +export class ESTagModule {}