diff --git a/apps/docs/src/app/app-routing.module.ts b/apps/docs/src/app/app-routing.module.ts
index 1c9f05e5..62afc495 100644
--- a/apps/docs/src/app/app-routing.module.ts
+++ b/apps/docs/src/app/app-routing.module.ts
@@ -4,6 +4,7 @@ import { BottomNavigationPageComponent } from './pages/component-pages/bottom-na
import { ButtonPageComponent } from './pages/component-pages/button-page/button-page.component';
import { CardPageComponent } from './pages/component-pages/card-page/card-page.component';
import { CheckBoxPageComponent } from './pages/component-pages/checkbox-page/checkbox-page.component';
+import { ChipPageComponent } from './pages/component-pages/chip-page/chip-page.component';
import { DialogPageComponent } from './pages/component-pages/dialog-page/dialog-page.component';
import { FormFieldPageComponent } from './pages/component-pages/form-field-page/form-field-page.component';
import { IconPageComponent } from './pages/component-pages/icon-page/icon-page.component';
@@ -38,6 +39,10 @@ const routes: Routes = [
path: 'components/checkbox',
component: CheckBoxPageComponent,
},
+ {
+ path: 'components/chip',
+ component: ChipPageComponent,
+ },
{
path: 'components/dialog',
component: DialogPageComponent,
diff --git a/apps/docs/src/app/app.component.ts b/apps/docs/src/app/app.component.ts
index 20b76026..426038fc 100644
--- a/apps/docs/src/app/app.component.ts
+++ b/apps/docs/src/app/app.component.ts
@@ -60,6 +60,10 @@ export class AppComponent {
link: 'components/checkbox',
name: 'Checkbox',
},
+ {
+ link: 'components/chip',
+ name: 'Chip',
+ },
{
link: 'components/dialog',
name: 'Dialog',
diff --git a/apps/docs/src/app/app.module.ts b/apps/docs/src/app/app.module.ts
index 909f40a9..eb01637f 100644
--- a/apps/docs/src/app/app.module.ts
+++ b/apps/docs/src/app/app.module.ts
@@ -3,6 +3,7 @@ import {
ButtonModule,
CardModule,
CheckboxModule,
+ ChipModule,
FormFieldModule,
IconModule,
ListModule,
@@ -30,6 +31,7 @@ import { BottomNavigationExampleModule } from './examples/bottom-navigation/bott
import { ButtonExamplesModule } from './examples/button/button-examples.module';
import { CardExamplesModule } from './examples/card/card-examples.module';
import { CheckBoxExamplesModule } from './examples/checkbox/checkbox-examples.module';
+import { ChipExamplesModule } from './examples/chip/chip-examples.module';
import { FormFieldExamplesModule } from './examples/form-field/form-field-examples.module';
import { IconExamplesModule } from './examples/icon/icon-examples.module';
import { ItemGroupExamplesModule } from './examples/item-group/item-group-examples.module';
@@ -48,6 +50,7 @@ import { BottomNavigationPageComponent } from './pages/component-pages/bottom-na
import { ButtonPageComponent } from './pages/component-pages/button-page/button-page.component';
import { CardPageComponent } from './pages/component-pages/card-page/card-page.component';
import { CheckBoxPageComponent } from './pages/component-pages/checkbox-page/checkbox-page.component';
+import { ChipPageComponent } from './pages/component-pages/chip-page/chip-page.component';
import { DialogPageComponent } from './pages/component-pages/dialog-page/dialog-page.component';
import { FormFieldPageComponent } from './pages/component-pages/form-field-page/form-field-page.component';
import { IconPageComponent } from './pages/component-pages/icon-page/icon-page.component';
@@ -88,6 +91,7 @@ import { TooltipPageComponent } from './pages/component-pages/tooltip-page/toolt
BottomNavigationPageComponent,
SnackbarPageComponent,
ItemGroupPageComponent,
+ ChipPageComponent,
],
imports: [
BrowserModule,
@@ -131,6 +135,8 @@ import { TooltipPageComponent } from './pages/component-pages/tooltip-page/toolt
SnackbarModule,
SnackbarExamplesModule,
ItemGroupExamplesModule,
+ ChipModule,
+ ChipExamplesModule,
],
providers: [
{
diff --git a/apps/docs/src/app/examples/chip/appearances/appearances.component.html b/apps/docs/src/app/examples/chip/appearances/appearances.component.html
new file mode 100644
index 00000000..69de85b4
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/appearances/appearances.component.html
@@ -0,0 +1,2 @@
+Filled
+Outlined
diff --git a/apps/docs/src/app/examples/chip/appearances/appearances.component.scss b/apps/docs/src/app/examples/chip/appearances/appearances.component.scss
new file mode 100644
index 00000000..e8b88706
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/appearances/appearances.component.scss
@@ -0,0 +1,5 @@
+:host {
+ display: grid;
+ grid-template-columns: repeat(2, auto);
+ gap: 1rem;
+}
diff --git a/apps/docs/src/app/examples/chip/appearances/appearances.component.ts b/apps/docs/src/app/examples/chip/appearances/appearances.component.ts
new file mode 100644
index 00000000..97f33bc0
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/appearances/appearances.component.ts
@@ -0,0 +1,10 @@
+import { ChangeDetectionStrategy, Component } from '@angular/core';
+
+@Component({
+ templateUrl: './appearances.component.html',
+ styleUrls: ['./appearances.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class AppearancesComponent {}
+
+export default AppearancesComponent;
diff --git a/apps/docs/src/app/examples/chip/chip-examples.module.ts b/apps/docs/src/app/examples/chip/chip-examples.module.ts
new file mode 100644
index 00000000..8e4c64ee
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/chip-examples.module.ts
@@ -0,0 +1,24 @@
+import { ChipModule, IconModule, ItemGroupModule } from '@anglify/components';
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { AppearancesComponent } from './appearances/appearances.component';
+import { FilterComponent } from './filter/filter.component';
+import { GroupsComponent } from './groups/groups.component';
+import { MandatoryComponent } from './mandatory/mandatory.component';
+import { MultipleMandatoryComponent } from './multiple-mandatory/multiple-mandatory.component';
+import { MultipleComponent } from './multiple/multiple.component';
+import { SlotsComponent } from './slots/slots.component';
+
+@NgModule({
+ declarations: [
+ AppearancesComponent,
+ SlotsComponent,
+ GroupsComponent,
+ MandatoryComponent,
+ MultipleComponent,
+ FilterComponent,
+ MultipleMandatoryComponent,
+ ],
+ imports: [CommonModule, ChipModule, IconModule, ItemGroupModule],
+})
+export class ChipExamplesModule {}
diff --git a/apps/docs/src/app/examples/chip/filter/filter.component.html b/apps/docs/src/app/examples/chip/filter/filter.component.html
new file mode 100644
index 00000000..ed82417e
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/filter/filter.component.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ Filled
+
+
+
+ Filled
+
+
+
+
+
+
+
+
+
+ Outlined
+
+
+
diff --git a/apps/docs/src/app/examples/chip/filter/filter.component.scss b/apps/docs/src/app/examples/chip/filter/filter.component.scss
new file mode 100644
index 00000000..027b2f94
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/filter/filter.component.scss
@@ -0,0 +1,6 @@
+:host {
+ anglify-item-group {
+ display: flex;
+ gap: 1rem;
+ }
+}
diff --git a/apps/docs/src/app/examples/chip/filter/filter.component.ts b/apps/docs/src/app/examples/chip/filter/filter.component.ts
new file mode 100644
index 00000000..15de259b
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/filter/filter.component.ts
@@ -0,0 +1,10 @@
+import { Component, ChangeDetectionStrategy } from '@angular/core';
+
+@Component({
+ templateUrl: './filter.component.html',
+ styleUrls: ['./filter.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class FilterComponent {}
+
+export default FilterComponent;
diff --git a/apps/docs/src/app/examples/chip/groups/groups.component.html b/apps/docs/src/app/examples/chip/groups/groups.component.html
new file mode 100644
index 00000000..3d4739de
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/groups/groups.component.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+ Chip 1
+
+
+
+ Chip 2
+
+
+ Chip 3
+
+
+ Chip 4
+
+
diff --git a/apps/docs/src/app/examples/chip/groups/groups.component.scss b/apps/docs/src/app/examples/chip/groups/groups.component.scss
new file mode 100644
index 00000000..027b2f94
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/groups/groups.component.scss
@@ -0,0 +1,6 @@
+:host {
+ anglify-item-group {
+ display: flex;
+ gap: 1rem;
+ }
+}
diff --git a/apps/docs/src/app/examples/chip/groups/groups.component.ts b/apps/docs/src/app/examples/chip/groups/groups.component.ts
new file mode 100644
index 00000000..fab96026
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/groups/groups.component.ts
@@ -0,0 +1,10 @@
+import { Component, ChangeDetectionStrategy } from '@angular/core';
+
+@Component({
+ templateUrl: './groups.component.html',
+ styleUrls: ['./groups.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class GroupsComponent {}
+
+export default GroupsComponent;
diff --git a/apps/docs/src/app/examples/chip/mandatory/mandatory.component.html b/apps/docs/src/app/examples/chip/mandatory/mandatory.component.html
new file mode 100644
index 00000000..03eba37b
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/mandatory/mandatory.component.html
@@ -0,0 +1,14 @@
+
+
+ Chip 1
+
+
+ Chip 2
+
+
+ Chip 3
+
+
+ Chip 4
+
+
diff --git a/apps/docs/src/app/examples/chip/mandatory/mandatory.component.scss b/apps/docs/src/app/examples/chip/mandatory/mandatory.component.scss
new file mode 100644
index 00000000..027b2f94
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/mandatory/mandatory.component.scss
@@ -0,0 +1,6 @@
+:host {
+ anglify-item-group {
+ display: flex;
+ gap: 1rem;
+ }
+}
diff --git a/apps/docs/src/app/examples/chip/mandatory/mandatory.component.ts b/apps/docs/src/app/examples/chip/mandatory/mandatory.component.ts
new file mode 100644
index 00000000..aa808ae7
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/mandatory/mandatory.component.ts
@@ -0,0 +1,10 @@
+import { Component, ChangeDetectionStrategy } from '@angular/core';
+
+@Component({
+ templateUrl: './mandatory.component.html',
+ styleUrls: ['./mandatory.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class MandatoryComponent {}
+
+export default MandatoryComponent;
diff --git a/apps/docs/src/app/examples/chip/multiple-mandatory/multiple-mandatory.component.html b/apps/docs/src/app/examples/chip/multiple-mandatory/multiple-mandatory.component.html
new file mode 100644
index 00000000..2f1e9489
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/multiple-mandatory/multiple-mandatory.component.html
@@ -0,0 +1,14 @@
+
+
+ Chip 1
+
+
+ Chip 2
+
+
+ Chip 3
+
+
+ Chip 4
+
+
diff --git a/apps/docs/src/app/examples/chip/multiple-mandatory/multiple-mandatory.component.scss b/apps/docs/src/app/examples/chip/multiple-mandatory/multiple-mandatory.component.scss
new file mode 100644
index 00000000..027b2f94
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/multiple-mandatory/multiple-mandatory.component.scss
@@ -0,0 +1,6 @@
+:host {
+ anglify-item-group {
+ display: flex;
+ gap: 1rem;
+ }
+}
diff --git a/apps/docs/src/app/examples/chip/multiple-mandatory/multiple-mandatory.component.ts b/apps/docs/src/app/examples/chip/multiple-mandatory/multiple-mandatory.component.ts
new file mode 100644
index 00000000..63b4b56c
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/multiple-mandatory/multiple-mandatory.component.ts
@@ -0,0 +1,10 @@
+import { Component, ChangeDetectionStrategy } from '@angular/core';
+
+@Component({
+ templateUrl: './multiple-mandatory.component.html',
+ styleUrls: ['./multiple-mandatory.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class MultipleMandatoryComponent {}
+
+export default MultipleMandatoryComponent;
diff --git a/apps/docs/src/app/examples/chip/multiple/multiple.component.html b/apps/docs/src/app/examples/chip/multiple/multiple.component.html
new file mode 100644
index 00000000..68eac70e
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/multiple/multiple.component.html
@@ -0,0 +1,14 @@
+
+
+ Chip 1
+
+
+ Chip 2
+
+
+ Chip 3
+
+
+ Chip 4
+
+
diff --git a/apps/docs/src/app/examples/chip/multiple/multiple.component.scss b/apps/docs/src/app/examples/chip/multiple/multiple.component.scss
new file mode 100644
index 00000000..027b2f94
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/multiple/multiple.component.scss
@@ -0,0 +1,6 @@
+:host {
+ anglify-item-group {
+ display: flex;
+ gap: 1rem;
+ }
+}
diff --git a/apps/docs/src/app/examples/chip/multiple/multiple.component.ts b/apps/docs/src/app/examples/chip/multiple/multiple.component.ts
new file mode 100644
index 00000000..bdaf69b1
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/multiple/multiple.component.ts
@@ -0,0 +1,10 @@
+import { Component, ChangeDetectionStrategy } from '@angular/core';
+
+@Component({
+ templateUrl: './multiple.component.html',
+ styleUrls: ['./multiple.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class MultipleComponent {}
+
+export default MultipleComponent;
diff --git a/apps/docs/src/app/examples/chip/slots/slots.component.html b/apps/docs/src/app/examples/chip/slots/slots.component.html
new file mode 100644
index 00000000..d685b6ec
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/slots/slots.component.html
@@ -0,0 +1,27 @@
+
+
+
+
+ Icon left
+
+
+
+
+
+
+ Icon right
+
+
+
+
+
+
+ Icon left
+
+
+
+
+
+
+ Icon right
+
diff --git a/apps/docs/src/app/examples/chip/slots/slots.component.scss b/apps/docs/src/app/examples/chip/slots/slots.component.scss
new file mode 100644
index 00000000..19841ba7
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/slots/slots.component.scss
@@ -0,0 +1,5 @@
+:host {
+ display: grid;
+ grid-template-columns: repeat(4, auto);
+ gap: 1rem;
+}
diff --git a/apps/docs/src/app/examples/chip/slots/slots.component.ts b/apps/docs/src/app/examples/chip/slots/slots.component.ts
new file mode 100644
index 00000000..8c33af97
--- /dev/null
+++ b/apps/docs/src/app/examples/chip/slots/slots.component.ts
@@ -0,0 +1,11 @@
+import { ChangeDetectionStrategy, Component } from '@angular/core';
+
+@Component({
+ selector: 'anglify-slots',
+ templateUrl: './slots.component.html',
+ styleUrls: ['./slots.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class SlotsComponent {}
+
+export default SlotsComponent;
diff --git a/apps/docs/src/app/pages/component-pages/chip-page/chip-page.component.html b/apps/docs/src/app/pages/component-pages/chip-page/chip-page.component.html
new file mode 100644
index 00000000..fee9cc4f
--- /dev/null
+++ b/apps/docs/src/app/pages/component-pages/chip-page/chip-page.component.html
@@ -0,0 +1,28 @@
+
Chip
+
+Examples
+
+Appearances
+
+
+Slots
+
+
+Standard Group
+
+
+Mandatory Chip
+
+
+Multiple Selectable Chips
+
+
+Multiple Mandatory Selectable Chips
+
+
+Filter
+
+
+API
+Styling
+
diff --git a/apps/docs/src/app/pages/component-pages/chip-page/chip-page.component.scss b/apps/docs/src/app/pages/component-pages/chip-page/chip-page.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/apps/docs/src/app/pages/component-pages/chip-page/chip-page.component.ts b/apps/docs/src/app/pages/component-pages/chip-page/chip-page.component.ts
new file mode 100644
index 00000000..e1cc5c15
--- /dev/null
+++ b/apps/docs/src/app/pages/component-pages/chip-page/chip-page.component.ts
@@ -0,0 +1,8 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'anglify-chip-page',
+ templateUrl: './chip-page.component.html',
+ styleUrls: ['./chip-page.component.scss'],
+})
+export class ChipPageComponent {}
diff --git a/libs/anglify/src/index.ts b/libs/anglify/src/index.ts
index 10453fb0..e70efefe 100644
--- a/libs/anglify/src/index.ts
+++ b/libs/anglify/src/index.ts
@@ -15,6 +15,11 @@ export * from './modules/checkbox/tokens/checkbox.token';
export * from './modules/checkbox/checkbox.component';
export * from './modules/checkbox/functions/register-icons.function';
export * from './modules/checkbox/checkbox.module';
+// Chip
+export * from './modules/chip/chip-settings.token';
+export * from './modules/chip/chip.interface';
+export * from './modules/chip/chip.component';
+export * from './modules/chip/chip.module';
// Common
export * from './modules/common/directives/slot/slot.directive';
export * from './modules/common/directives/slot-outlet/slot-outlet.directive';
diff --git a/libs/anglify/src/modules/chip/_variables.scss b/libs/anglify/src/modules/chip/_variables.scss
new file mode 100644
index 00000000..0bd820c5
--- /dev/null
+++ b/libs/anglify/src/modules/chip/_variables.scss
@@ -0,0 +1,14 @@
+$chip-border-radius: var(--anglify-chip-border-radius, 16px);
+$chip-height: var(--anglify-chip-height, 20px);
+$chip-padding: var(--anglify-chip-padding, 6px 12px);
+$chip-background-color: var(--anglify-chip-background-color, var(--color-surface-overlay));
+$chip-text-decoration: var(--anglify-chip-text-decoration, none);
+$chip-cursor: var(--anglify-chip-cursor, default);
+$chip-inline-padding-start-dense: var(--anglify-chip-inline-padding-start-dense, 5px);
+$chip-inline-padding-end-dense: var(--anglify-chip-inline-padding-end-dense, 5px);
+$chip-outlined-border: var(--anglify-chip-outlined-border, 1px solid var(--border-color-on-surface-low-emphasis));
+$chip-group-gap: var(--anglify-chip-group-gap, 16px);
+$chip-filter-prepend-width: var(--anglify-chip-filter-prepend-width, 30px);
+$chip-filter-transition-speed: var(--anglify-chip-filter-transition-speed, all 250ms);
+$chip-hover-state-color: var(--anglify-hover-state-color, var(--color-primary-state-hover)) !default;
+$chip-focus-state-color: var(--anglify-focus-state-color, var(--color-primary-state-focus)) !default;
diff --git a/libs/anglify/src/modules/chip/chip-settings.token.ts b/libs/anglify/src/modules/chip/chip-settings.token.ts
new file mode 100644
index 00000000..4db613c2
--- /dev/null
+++ b/libs/anglify/src/modules/chip/chip-settings.token.ts
@@ -0,0 +1,10 @@
+import { InjectionToken } from '@angular/core';
+import type { ChipSettings } from './chip.interface';
+
+export const DEFAULT_CHIP_SETTINGS: Required = {
+ appearance: 'filled',
+ filter: false,
+ ripple: false,
+};
+
+export const CHIP_SETTINGS = new InjectionToken>('Chip Settings');
diff --git a/libs/anglify/src/modules/chip/chip.component.html b/libs/anglify/src/modules/chip/chip.component.html
new file mode 100644
index 00000000..e3294af1
--- /dev/null
+++ b/libs/anglify/src/modules/chip/chip.component.html
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/libs/anglify/src/modules/chip/chip.component.scss b/libs/anglify/src/modules/chip/chip.component.scss
new file mode 100644
index 00000000..f9f09c69
--- /dev/null
+++ b/libs/anglify/src/modules/chip/chip.component.scss
@@ -0,0 +1,62 @@
+@use 'variables' as *;
+
+:host {
+ display: inline-flex;
+ align-items: center;
+ text-decoration: $chip-text-decoration;
+ border-radius: $chip-border-radius;
+ padding: $chip-padding;
+ min-height: $chip-height;
+ height: 1px;
+ cursor: $chip-cursor;
+
+ &:hover {
+ --state-container-color: #{$chip-hover-state-color};
+ }
+
+ &:focus-visible {
+ --state-container-color: #{$chip-focus-state-color};
+ }
+
+ .prepend,
+ .append {
+ --state-container-color: transparent;
+ }
+
+ &.filter {
+ .prepend {
+ opacity: 0;
+ width: 0;
+ transform: translate(calc(-1 * $chip-filter-prepend-width), 0);
+ transition: $chip-filter-transition-speed;
+ }
+
+ &.active {
+ .prepend {
+ opacity: 1;
+ width: $chip-filter-prepend-width;
+ transform: translate(0, 0);
+ }
+ }
+ }
+
+ &.active {
+ --state-container-color: var(--color-primary-state-focus);
+ }
+
+ &.filled {
+ background-color: $chip-background-color;
+ }
+
+ &.outlined {
+ border: $chip-outlined-border;
+ }
+
+ &.has-left-icon {
+ padding-inline-start: $chip-inline-padding-start-dense;
+ }
+
+ &.has-right-icon {
+ padding-inline-end: $chip-inline-padding-end-dense;
+ }
+}
diff --git a/libs/anglify/src/modules/chip/chip.component.spec.ts b/libs/anglify/src/modules/chip/chip.component.spec.ts
new file mode 100644
index 00000000..26af70cc
--- /dev/null
+++ b/libs/anglify/src/modules/chip/chip.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ChipComponent } from './chip.component';
+import { AnglifyCommonModule } from '../common/anglify-common.module';
+
+describe('ChipComponent', () => {
+ let component: ChipComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ChipComponent],
+ imports: [AnglifyCommonModule],
+ }).compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ChipComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/libs/anglify/src/modules/chip/chip.component.ts b/libs/anglify/src/modules/chip/chip.component.ts
new file mode 100644
index 00000000..61b679d0
--- /dev/null
+++ b/libs/anglify/src/modules/chip/chip.component.ts
@@ -0,0 +1,118 @@
+import {
+ ChangeDetectionStrategy,
+ Component,
+ ContentChildren,
+ ElementRef,
+ EventEmitter,
+ HostBinding,
+ HostListener,
+ Inject,
+ Input,
+ OnInit,
+ Output,
+ QueryList,
+ Self,
+} from '@angular/core';
+import { UntilDestroy } from '@ngneat/until-destroy';
+import { BehaviorSubject } from 'rxjs';
+import { CHIP_SETTINGS, DEFAULT_CHIP_SETTINGS } from './chip-settings.token';
+import { ChipAppearance, ChipSettings } from './chip.interface';
+import { RIPPLE } from '../../composables/ripple/ripple.provider';
+import { RippleService } from '../../composables/ripple/ripple.service';
+import { createSettingsProvider } from '../../factories/settings.factory';
+import { bindClassToNativeElement, toBoolean } from '../../utils/functions';
+import { BooleanLike } from '../../utils/interfaces';
+import { SlotDirective } from '../common/directives/slot/slot.directive';
+
+@UntilDestroy()
+@Component({
+ selector: 'anglify-chip',
+ templateUrl: './chip.component.html',
+ styleUrls: ['./chip.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ providers: [createSettingsProvider('anglifyChipSettings', DEFAULT_CHIP_SETTINGS, CHIP_SETTINGS), RIPPLE],
+})
+export class ChipComponent implements OnInit {
+ @ContentChildren(SlotDirective) public readonly slots?: QueryList;
+
+ @Input()
+ public set active(value: BooleanLike) {
+ this.active$.next(toBoolean(value));
+ }
+
+ public get active() {
+ return this.active$.value;
+ }
+
+ @Input('filter') public filter: BooleanLike = this.settings.filter;
+
+ @Input() public appearance: ChipAppearance = this.settings.appearance;
+
+ @Input()
+ public set ripple(value: BooleanLike) {
+ this.rippleService.active = toBoolean(value);
+ }
+
+ public get ripple(): boolean {
+ return this.rippleService.active;
+ }
+
+ @Output() public readonly onClick = new EventEmitter();
+
+ public readonly active$ = new BehaviorSubject(false);
+
+ public constructor(
+ private readonly elementRef: ElementRef,
+ @Self() @Inject('anglifyChipSettings') public settings: Required,
+ private readonly rippleService: RippleService
+ ) {
+ bindClassToNativeElement(this, this.active$, this.elementRef.nativeElement, 'active');
+ }
+
+ public ngOnInit(): void {
+ const children = Array.from(this.elementRef.nativeElement.children);
+ const hasLeftIcon = children.some(child => {
+ if (child.tagName === 'ANGLIFY-ICON') {
+ const right = Array.from(child.attributes).some(attribute => attribute.name === 'left');
+ return Boolean(right);
+ }
+ return false;
+ });
+
+ const hasRightIcon = children.some(child => {
+ if (child.tagName === 'ANGLIFY-ICON') {
+ const right = Array.from(child.attributes).some(attribute => attribute.name === 'right');
+ return Boolean(right);
+ }
+ return false;
+ });
+
+ if (hasLeftIcon) {
+ this.elementRef.nativeElement.classList.add('has-left-icon');
+ }
+ if (hasRightIcon) {
+ this.elementRef.nativeElement.classList.add('has-right-icon');
+ }
+ }
+
+ @HostBinding('class')
+ protected get classList() {
+ const classNames: string[] = [this.appearance];
+
+ if (toBoolean(this.filter)) {
+ classNames.push('filter');
+ }
+
+ return classNames.join(' ');
+ }
+
+ @HostBinding('tabindex')
+ // @ts-expect-error
+ private readonly tabindex = 0;
+
+ @HostListener('click')
+ // @ts-expect-error
+ private click() {
+ this.onClick.next();
+ }
+}
diff --git a/libs/anglify/src/modules/chip/chip.interface.ts b/libs/anglify/src/modules/chip/chip.interface.ts
new file mode 100644
index 00000000..c957c38a
--- /dev/null
+++ b/libs/anglify/src/modules/chip/chip.interface.ts
@@ -0,0 +1,7 @@
+export type ChipAppearance = 'filled' | 'outlined';
+
+export interface ChipSettings {
+ appearance?: ChipAppearance;
+ filter?: boolean;
+ ripple?: boolean;
+}
diff --git a/libs/anglify/src/modules/chip/chip.module.ts b/libs/anglify/src/modules/chip/chip.module.ts
new file mode 100644
index 00000000..eb3e8d14
--- /dev/null
+++ b/libs/anglify/src/modules/chip/chip.module.ts
@@ -0,0 +1,12 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { ChipComponent } from './chip.component';
+import { AnglifyCommonModule } from '../common/anglify-common.module';
+import { IconModule } from '../icon/icon.module';
+
+@NgModule({
+ declarations: [ChipComponent],
+ imports: [AnglifyCommonModule, CommonModule, IconModule],
+ exports: [AnglifyCommonModule, ChipComponent],
+})
+export class ChipModule {}