diff --git a/apps/docs/src/app/examples/breadcrumbs/basic/basic.component.html b/apps/docs/src/app/examples/breadcrumbs/basic/basic.component.html new file mode 100644 index 00000000..8bbd17d9 --- /dev/null +++ b/apps/docs/src/app/examples/breadcrumbs/basic/basic.component.html @@ -0,0 +1 @@ + diff --git a/apps/docs/src/app/examples/breadcrumbs/basic/basic.component.scss b/apps/docs/src/app/examples/breadcrumbs/basic/basic.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/apps/docs/src/app/examples/breadcrumbs/basic/basic.component.ts b/apps/docs/src/app/examples/breadcrumbs/basic/basic.component.ts new file mode 100644 index 00000000..72f6e0f2 --- /dev/null +++ b/apps/docs/src/app/examples/breadcrumbs/basic/basic.component.ts @@ -0,0 +1,31 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { BreadCrumb } from 'libs/anglify/src/modules/breadcrumbs/breadcrumbs.interface'; + +@Component({ + templateUrl: './basic.component.html', + styleUrls: ['./basic.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class BasicComponent { + public items: BreadCrumb[] = [ + { + text: 'Home', + disabled: false, + href: '#', + routerLink: ['/components/breadcrumbs'], + }, + { + text: 'About', + disabled: false, + href: '#', + routerLink: ['/getting-started/installation'], + }, + { + text: 'Contact', + disabled: true, + href: '#', + routerLink: ['/components/card'], + }, + ]; +} +export default BasicComponent; diff --git a/apps/docs/src/app/examples/breadcrumbs/breadcrumbs-example.module.ts b/apps/docs/src/app/examples/breadcrumbs/breadcrumbs-example.module.ts new file mode 100644 index 00000000..d710710f --- /dev/null +++ b/apps/docs/src/app/examples/breadcrumbs/breadcrumbs-example.module.ts @@ -0,0 +1,11 @@ +import { BreadcrumbsModule, IconModule } from '@anglify/components'; +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { BasicComponent } from './basic/basic.component'; +import { IconComponent } from './icon/icon.component'; + +@NgModule({ + declarations: [BasicComponent, IconComponent], + imports: [CommonModule, BreadcrumbsModule, IconModule], +}) +export class BreadcrumbsExampleModule {} diff --git a/apps/docs/src/app/examples/breadcrumbs/icon/icon.component.html b/apps/docs/src/app/examples/breadcrumbs/icon/icon.component.html new file mode 100644 index 00000000..4952c09e --- /dev/null +++ b/apps/docs/src/app/examples/breadcrumbs/icon/icon.component.html @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/docs/src/app/examples/breadcrumbs/icon/icon.component.scss b/apps/docs/src/app/examples/breadcrumbs/icon/icon.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/apps/docs/src/app/examples/breadcrumbs/icon/icon.component.ts b/apps/docs/src/app/examples/breadcrumbs/icon/icon.component.ts new file mode 100644 index 00000000..adc2ac90 --- /dev/null +++ b/apps/docs/src/app/examples/breadcrumbs/icon/icon.component.ts @@ -0,0 +1,32 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { BreadCrumb } from 'libs/anglify/src/modules/breadcrumbs/breadcrumbs.interface'; + +@Component({ + templateUrl: './icon.component.html', + styleUrls: ['./icon.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class IconComponent { + public items: BreadCrumb[] = [ + { + text: 'Home', + disabled: false, + href: '#', + routerLink: ['/components/breadcrumbs'], + }, + { + text: 'About', + disabled: false, + href: '#', + routerLink: ['/getting-started/installation'], + }, + { + text: 'Contact', + disabled: true, + href: '#', + routerLink: ['/components/card'], + }, + ]; +} + +export default IconComponent; diff --git a/apps/docs/src/app/layouts/default/default.component.ts b/apps/docs/src/app/layouts/default/default.component.ts index 852e9ad6..e769713d 100644 --- a/apps/docs/src/app/layouts/default/default.component.ts +++ b/apps/docs/src/app/layouts/default/default.component.ts @@ -62,6 +62,10 @@ export class DefaultComponent { link: 'components/bottom-navigation', name: 'Bottom Navigation', }, + { + link: 'components/breadcrumbs', + name: 'Breadcrumbs', + }, { link: 'components/button', name: 'Button', diff --git a/apps/docs/src/app/pages/components/breadcrumbs-page/breadcrumbs-page.component.html b/apps/docs/src/app/pages/components/breadcrumbs-page/breadcrumbs-page.component.html new file mode 100644 index 00000000..eb898a05 --- /dev/null +++ b/apps/docs/src/app/pages/components/breadcrumbs-page/breadcrumbs-page.component.html @@ -0,0 +1,22 @@ +

Breadcrumbs

+ +

+ Breadcrumbs consist of a list of links that help a user visualize a page's location within the hierarchical structure of a website, and + allow navigation up to any of its "ancestors". +

+ +

Examples

+ +

Basic

+ + +

With Icon

+ + +

API

+

Styling

+ diff --git a/apps/docs/src/app/pages/components/breadcrumbs-page/breadcrumbs-page.component.scss b/apps/docs/src/app/pages/components/breadcrumbs-page/breadcrumbs-page.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/apps/docs/src/app/pages/components/breadcrumbs-page/breadcrumbs-page.component.ts b/apps/docs/src/app/pages/components/breadcrumbs-page/breadcrumbs-page.component.ts new file mode 100644 index 00000000..50cd98f3 --- /dev/null +++ b/apps/docs/src/app/pages/components/breadcrumbs-page/breadcrumbs-page.component.ts @@ -0,0 +1,9 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'anglify-breadcrumbs-page', + templateUrl: './breadcrumbs-page.component.html', + styleUrls: ['./breadcrumbs-page.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class BreadcrumbsPageComponent {} diff --git a/apps/docs/src/app/pages/components/components-routing.module.ts b/apps/docs/src/app/pages/components/components-routing.module.ts index c3dedfeb..f339dc43 100644 --- a/apps/docs/src/app/pages/components/components-routing.module.ts +++ b/apps/docs/src/app/pages/components/components-routing.module.ts @@ -2,6 +2,7 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { BadgePageComponent } from './badge-page/badge-page.component'; import { BottomNavigationPageComponent } from './bottom-navigation-page/bottom-navigation-page.component'; +import { BreadcrumbsPageComponent } from './breadcrumbs-page/breadcrumbs-page.component'; import { ButtonPageComponent } from './button-page/button-page.component'; import { CardPageComponent } from './card-page/card-page.component'; import { CheckBoxPageComponent } from './checkbox-page/checkbox-page.component'; @@ -112,6 +113,10 @@ const routes: Routes = [ path: 'badge', component: BadgePageComponent, }, + { + path: 'breadcrumbs', + component: BreadcrumbsPageComponent, + }, ]; @NgModule({ diff --git a/apps/docs/src/app/pages/components/components.module.ts b/apps/docs/src/app/pages/components/components.module.ts index dcbe564f..bef56602 100644 --- a/apps/docs/src/app/pages/components/components.module.ts +++ b/apps/docs/src/app/pages/components/components.module.ts @@ -4,6 +4,7 @@ import { NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { BadgePageComponent } from './badge-page/badge-page.component'; import { BottomNavigationPageComponent } from './bottom-navigation-page/bottom-navigation-page.component'; +import { BreadcrumbsPageComponent } from './breadcrumbs-page/breadcrumbs-page.component'; import { ButtonPageComponent } from './button-page/button-page.component'; import { CardPageComponent } from './card-page/card-page.component'; import { CheckBoxPageComponent } from './checkbox-page/checkbox-page.component'; @@ -27,6 +28,7 @@ import { ToolbarPageComponent } from './toolbar-page/toolbar-page.component'; import { TooltipPageComponent } from './tooltip-page/tooltip-page.component'; import { BadgeExampleModule } from '../../examples/badge/badge-example.module'; import { BottomNavigationExampleModule } from '../../examples/bottom-navigation/bottom-navigation-example.module'; +import { BreadcrumbsExampleModule } from '../../examples/breadcrumbs/breadcrumbs-example.module'; import { ButtonExamplesModule } from '../../examples/button/button-examples.module'; import { CardExamplesModule } from '../../examples/card/card-examples.module'; import { CheckBoxExamplesModule } from '../../examples/checkbox/checkbox-examples.module'; @@ -73,6 +75,7 @@ import { SharedModule } from '../../modules/shared/shared.module'; ItemGroupPageComponent, ChipPageComponent, TabPageComponent, + BreadcrumbsPageComponent, ], imports: [ CommonModule, @@ -100,6 +103,7 @@ import { SharedModule } from '../../modules/shared/shared.module'; ProgressCircularExamplesModule, CardExamplesModule, TabExamplesModule, + BreadcrumbsExampleModule, // Imports for Playground IconModule, FormFieldModule, diff --git a/libs/anglify/ng-package.json b/libs/anglify/ng-package.json index 4ca4655e..487d9b1d 100644 --- a/libs/anglify/ng-package.json +++ b/libs/anglify/ng-package.json @@ -9,6 +9,7 @@ "src/modules/badge/*.scss", "src/modules/bottom-navigation/*.scss", "src/modules/button/*.scss", + "src/modules/breadcrumbs/*.scss", "src/modules/card/*.scss", "src/modules/checkbox/*.scss", "src/modules/chip/*.scss", diff --git a/libs/anglify/src/index.ts b/libs/anglify/src/index.ts index e596c254..9663f9be 100644 --- a/libs/anglify/src/index.ts +++ b/libs/anglify/src/index.ts @@ -28,6 +28,11 @@ export * from './modules/bottom-navigation/components/bottom-navigation-item/bot export * from './modules/button/button.component'; export * from './modules/button/button.interface'; export * from './modules/button/button.module'; +// Breadcrumbs +export * from './modules/breadcrumbs/breadcrumbs-settings.token'; +export * from './modules/breadcrumbs/breadcrumbs.component'; +export * from './modules/breadcrumbs/breadcrumbs.interface'; +export * from './modules/breadcrumbs/breadcrumbs.module'; // Card export * from './modules/card/card-settings.token'; export * from './modules/card/card.component'; diff --git a/libs/anglify/src/modules/breadcrumbs/_variables.scss b/libs/anglify/src/modules/breadcrumbs/_variables.scss new file mode 100644 index 00000000..16ebc427 --- /dev/null +++ b/libs/anglify/src/modules/breadcrumbs/_variables.scss @@ -0,0 +1,10 @@ +$breadcrumbs-active-color: var(--anglify-breadcrumbs-active-color, var(--color-primary)) !default; +$breadcrumbs-inactive-color: var(--anglify-breadcrumbs-inactive-color, var(--color-on-surface-medium-emphasis)) !default; +$breadcrumbs-text-font: var(--anglify-breadcrumbs-text-font, var(--font-body-2)) !default; +$breadcrumbs-text-letter-spacing: var(--anglify-breadcrumbs-text-letter-spacing, var(--font-letter-spacing-body-2)) !default; +$breadcrumbs-text-transform: var(--anglify-breadcrumbs-text-transform, var(--font-text-transform-body-2)) !default; +$breadcrumbs-divider-font: var(--anglify-breadcrumbs-divider-font, var(--font-body-2)) !default; +$breadcrumbs-divider-letter-spacing: var(--anglify-breadcrumbs-divider-letter-spacing, var(--font-letter-spacing-body-2)) !default; +$breadcrumbs-divider-transform: var(--anglify-breadcrumbs-divider-transform, var(--font-text-transform-body-2)) !default; +$breadcrumbs-divider-padding: var(--anglify-breadcrumbs-divider-padding, 0 12px) !default; +$breadcrumbs-disabled-color: var(--anglify-breadcrumbs-disabled-color, var(--color-on-surface-low-emphasis)) !default; diff --git a/libs/anglify/src/modules/breadcrumbs/breadcrumbs-settings.token.ts b/libs/anglify/src/modules/breadcrumbs/breadcrumbs-settings.token.ts new file mode 100644 index 00000000..8b4dbc06 --- /dev/null +++ b/libs/anglify/src/modules/breadcrumbs/breadcrumbs-settings.token.ts @@ -0,0 +1,9 @@ +import { InjectionToken } from '@angular/core'; +import { BreadCrumbsSettings, EntireBreadCrumbsSettings } from './breadcrumbs.interface'; + +export const DEFAULT_BREADCRUMBS_SETTINGS: EntireBreadCrumbsSettings = { + items: [], + divider: '/', + matchOptions: { matrixParams: 'exact', queryParams: 'exact', paths: 'exact', fragment: 'exact' }, +}; +export const BREADCRUMBS_SETTINGS = new InjectionToken('Breadcrumbs Settings'); diff --git a/libs/anglify/src/modules/breadcrumbs/breadcrumbs.component.html b/libs/anglify/src/modules/breadcrumbs/breadcrumbs.component.html new file mode 100644 index 00000000..018f5f57 --- /dev/null +++ b/libs/anglify/src/modules/breadcrumbs/breadcrumbs.component.html @@ -0,0 +1,15 @@ + + + {{ item.text }} + + {{ item.text }} +
+ {{ divider }} +
+
diff --git a/libs/anglify/src/modules/breadcrumbs/breadcrumbs.component.scss b/libs/anglify/src/modules/breadcrumbs/breadcrumbs.component.scss new file mode 100644 index 00000000..9dc4fd13 --- /dev/null +++ b/libs/anglify/src/modules/breadcrumbs/breadcrumbs.component.scss @@ -0,0 +1,33 @@ +@use 'variables' as *; + +:host { + display: flex; + align-items: center; + user-select: none; + + a { + color: $breadcrumbs-inactive-color; + font: $breadcrumbs-text-font; + letter-spacing: $breadcrumbs-text-letter-spacing; + text-decoration: none; + text-transform: $breadcrumbs-text-transform; + } + + .active { + color: $breadcrumbs-active-color; + } + + .divider { + padding: $breadcrumbs-divider-padding; + color: $breadcrumbs-inactive-color; + font: $breadcrumbs-divider-font; + letter-spacing: $breadcrumbs-divider-letter-spacing; + text-decoration: none; + text-transform: $breadcrumbs-divider-transform; + } + + .disabled { + color: $breadcrumbs-disabled-color; + cursor: not-allowed; + } +} diff --git a/libs/anglify/src/modules/breadcrumbs/breadcrumbs.component.spec.ts b/libs/anglify/src/modules/breadcrumbs/breadcrumbs.component.spec.ts new file mode 100644 index 00000000..d6e3bd3c --- /dev/null +++ b/libs/anglify/src/modules/breadcrumbs/breadcrumbs.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { BreadcrumbsComponent } from './breadcrumbs.component'; + +describe('BreadcrumbsComponent', () => { + let component: BreadcrumbsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [BreadcrumbsComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(BreadcrumbsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/libs/anglify/src/modules/breadcrumbs/breadcrumbs.component.ts b/libs/anglify/src/modules/breadcrumbs/breadcrumbs.component.ts new file mode 100644 index 00000000..15331c9b --- /dev/null +++ b/libs/anglify/src/modules/breadcrumbs/breadcrumbs.component.ts @@ -0,0 +1,29 @@ +import { ChangeDetectionStrategy, Component, ContentChildren, Inject, Input, QueryList, Self } from '@angular/core'; +import { IsActiveMatchOptions } from '@angular/router'; +import { BREADCRUMBS_SETTINGS, DEFAULT_BREADCRUMBS_SETTINGS } from './breadcrumbs-settings.token'; +import { BreadCrumb, EntireBreadCrumbsSettings } from './breadcrumbs.interface'; +import { createSettingsProvider } from '../../factories/settings.factory'; +import { SlotDirective } from '../common/directives/slot/slot.directive'; + +@Component({ + selector: 'anglify-breadcrumbs', + templateUrl: './breadcrumbs.component.html', + styleUrls: ['./breadcrumbs.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + providers: [ + createSettingsProvider('anglifyBreadcrumbsSettings', DEFAULT_BREADCRUMBS_SETTINGS, BREADCRUMBS_SETTINGS), + ], +}) +export class BreadcrumbsComponent { + @ContentChildren(SlotDirective) public readonly slots?: QueryList; + + @Input() public items: BreadCrumb[] = this.settings.items; + @Input() public divider: string = this.settings.divider; + @Input() public matchOptions: IsActiveMatchOptions = this.settings.matchOptions; + + public constructor(@Self() @Inject('anglifyBreadcrumbsSettings') public settings: EntireBreadCrumbsSettings) {} + + public isLastItem(item: BreadCrumb) { + return item === this.items[this.items.length - 1]; + } +} diff --git a/libs/anglify/src/modules/breadcrumbs/breadcrumbs.interface.ts b/libs/anglify/src/modules/breadcrumbs/breadcrumbs.interface.ts new file mode 100644 index 00000000..14152e65 --- /dev/null +++ b/libs/anglify/src/modules/breadcrumbs/breadcrumbs.interface.ts @@ -0,0 +1,15 @@ +import { IsActiveMatchOptions } from '@angular/router'; +import { RouterLinkCommands } from '../../utils/interfaces'; + +export interface EntireBreadCrumbsSettings { + items: BreadCrumb[]; + divider: string; + matchOptions: IsActiveMatchOptions; +} +export interface BreadCrumb { + text: string; + disabled: boolean; + href: string; + routerLink: RouterLinkCommands; +} +export type BreadCrumbsSettings = Partial; diff --git a/libs/anglify/src/modules/breadcrumbs/breadcrumbs.module.ts b/libs/anglify/src/modules/breadcrumbs/breadcrumbs.module.ts new file mode 100644 index 00000000..125c6f88 --- /dev/null +++ b/libs/anglify/src/modules/breadcrumbs/breadcrumbs.module.ts @@ -0,0 +1,12 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { BreadcrumbsComponent } from './breadcrumbs.component'; +import { AnglifyCommonModule } from '../common/anglify-common.module'; + +@NgModule({ + declarations: [BreadcrumbsComponent], + imports: [CommonModule, AnglifyCommonModule, RouterModule], + exports: [BreadcrumbsComponent, AnglifyCommonModule, RouterModule], +}) +export class BreadcrumbsModule {}