Skip to content

Commit 06b07bb

Browse files
MaudeLaflammemtlmatt
authored andcommitted
feat(system-header): add system-header pattern. close VilledeMontreal#55 (VilledeMontreal#171)
Signed-off-by: Maude Laflamme <maude.laflamme@montreal.ca>
1 parent 93eaf0e commit 06b07bb

File tree

12 files changed

+687
-2
lines changed

12 files changed

+687
-2
lines changed

projects/angular-ui/src/lib/bao.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { BaoHyperlinkModule } from './hyperlink';
2323
import { BaoDropdownMenuModule } from './dropdown-menu';
2424
import { BaoFileModule } from './file/module';
2525
import { BaoSnackBarModule } from './snack-bar/module';
26+
import { BaoSystemHeaderModule } from './system-header';
2627

2728
@NgModule({
2829
imports: [
@@ -52,7 +53,8 @@ import { BaoSnackBarModule } from './snack-bar/module';
5253
BaoHyperlinkModule,
5354
BaoDropdownMenuModule,
5455
BaoFileModule,
55-
BaoSnackBarModule
56+
BaoSnackBarModule,
57+
BaoSystemHeaderModule
5658
// TODO: reactivate once component does not depend on global css BaoBadgeModule,
5759
]
5860
})
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* Copyright (c) 2023 Ville de Montreal. All rights reserved.
3+
* Licensed under the MIT license.
4+
* See LICENSE file in the project root for full license information.
5+
*/
6+
export const Breakpoints = {
7+
XSmall: '(max-width: 575.98px)',
8+
Small: '(min-width: 576px) and (max-width: 767.98px)',
9+
Medium: '(min-width: 768px) and (max-width: 991.98px)',
10+
Large: '(min-width: 992px) and (max-width: 1199.98px)',
11+
XLarge: '(min-width: 1200px)'
12+
};

projects/angular-ui/src/lib/core/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
* See LICENSE file in the project root for full license information.
55
*/
66
export * from './colors';
7+
export * from './breakpoints';
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/*
2+
* Copyright (c) 2023 Ville de Montreal. All rights reserved.
3+
* Licensed under the MIT license.
4+
* See LICENSE file in the project root for full license information.
5+
*/
6+
export * from './module';
7+
export * from './system-header.component';
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright (c) 2023 Ville de Montreal. All rights reserved.
3+
* Licensed under the MIT license.
4+
* See LICENSE file in the project root for full license information.
5+
*/
6+
import { CommonModule } from '@angular/common';
7+
import { NgModule } from '@angular/core';
8+
import {
9+
BaoBackNavigationInsert,
10+
BaoSystemHeaderComponent,
11+
BaoBackNavigationComponent
12+
} from './system-header.component';
13+
import { BaoIconModule } from '../icon';
14+
15+
const SYSTEM_HEADER_DIRECTIVES = [
16+
BaoSystemHeaderComponent,
17+
BaoBackNavigationInsert,
18+
BaoBackNavigationComponent
19+
];
20+
21+
@NgModule({
22+
imports: [CommonModule, BaoIconModule],
23+
declarations: [SYSTEM_HEADER_DIRECTIVES],
24+
exports: [SYSTEM_HEADER_DIRECTIVES]
25+
})
26+
export class BaoSystemHeaderModule {}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<div class="left-side-content">
2+
<div class="back-navigation-container">
3+
<ng-content select="a"></ng-content>
4+
<ng-template backNavigationInsert></ng-template>
5+
</div>
6+
<div #textContainer class="text-content">
7+
<ng-content select="bao-breadcrumb"></ng-content>
8+
<ng-content select="h1"></ng-content>
9+
<div class="tag-info-container">
10+
<ng-content select="bao-tag"></ng-content>
11+
<span class="additional-info">
12+
<ng-content select="span"></ng-content>
13+
</span>
14+
</div>
15+
</div>
16+
</div>
17+
<div class="button-container">
18+
<ng-content></ng-content>
19+
</div>
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
@import '../core/colors';
2+
@import '../core/grid';
3+
@import '../core/typography';
4+
5+
.bao-system-header {
6+
display: flex;
7+
justify-content: flex-start;
8+
.left-side-content {
9+
display: inline-flex;
10+
width: 75%;
11+
.back-navigation-container {
12+
a {
13+
margin-right: 1.25rem;
14+
border-bottom: none;
15+
&:hover {
16+
cursor: pointer;
17+
}
18+
}
19+
}
20+
.text-content {
21+
width: 100%;
22+
h1 {
23+
font-weight: 700;
24+
color: $ground-reversed;
25+
font-size: 1.5rem;
26+
line-height: 2rem;
27+
margin-bottom: 0.5rem;
28+
}
29+
.tag-info-container {
30+
width: 100%;
31+
display: block;
32+
> span:nth-child(2) {
33+
&:before {
34+
content: '·';
35+
margin: 0 0.5rem;
36+
}
37+
}
38+
.additional-info > * {
39+
@include typo-interface-small;
40+
}
41+
&.mobile {
42+
.bao-tag {
43+
margin-bottom: 0.25rem;
44+
}
45+
.additional-info {
46+
display: block;
47+
&:before {
48+
content: none;
49+
}
50+
}
51+
}
52+
> .bao-tag {
53+
max-width: 100%;
54+
> span {
55+
width: 100%;
56+
white-space: nowrap;
57+
overflow: hidden;
58+
text-overflow: ellipsis;
59+
}
60+
}
61+
}
62+
}
63+
}
64+
.button-container {
65+
flex-shrink: 0;
66+
margin-left: auto;
67+
.bao-button {
68+
margin-left: 1rem;
69+
}
70+
}
71+
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Copyright (c) 2023 Ville de Montreal. All rights reserved.
3+
* Licensed under the MIT license.
4+
* See LICENSE file in the project root for full license information.
5+
*/
6+
7+
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
8+
import { By } from '@angular/platform-browser';
9+
import {
10+
TestSystemHeaderHostComponent,
11+
TestBackNavigationHostComponent
12+
} from './tests/system-header.hostcomponent.spec';
13+
import {
14+
BaoSystemHeaderComponent,
15+
BaoBackNavigationInsert,
16+
BaoBackNavigationComponent
17+
} from './system-header.component';
18+
import { BaoTagComponent } from '../tag/tag.component';
19+
import { BaoIconComponent } from '../icon/icon.component';
20+
import { BaoBreadcrumbComponent } from '../breadcrumb/breadcrumb.component';
21+
import {
22+
BaoDropdownMenuComponent,
23+
BaoDropdownMenuTrigger,
24+
BaoDropdownMenuItem,
25+
BaoDropdownMenuItemLabel
26+
} from '../dropdown-menu/dropdown-menu.component';
27+
import { DebugElement } from '@angular/core';
28+
29+
declare const viewport;
30+
/* eslint-disable @typescript-eslint/no-unsafe-return */
31+
describe('BaoSystemHeaderComponent', () => {
32+
let testComponent: TestSystemHeaderHostComponent;
33+
let fixture: ComponentFixture<TestSystemHeaderHostComponent>;
34+
beforeEach(
35+
waitForAsync(() => {
36+
TestBed.configureTestingModule({
37+
declarations: [
38+
BaoSystemHeaderComponent,
39+
BaoBackNavigationInsert,
40+
BaoBackNavigationComponent,
41+
BaoIconComponent,
42+
BaoDropdownMenuComponent,
43+
BaoDropdownMenuTrigger,
44+
BaoDropdownMenuItem,
45+
BaoDropdownMenuItemLabel,
46+
BaoTagComponent,
47+
BaoBreadcrumbComponent,
48+
TestSystemHeaderHostComponent,
49+
TestBackNavigationHostComponent
50+
],
51+
imports: [],
52+
providers: []
53+
});
54+
return TestBed.compileComponents();
55+
})
56+
);
57+
describe('Desktop screen', () => {
58+
beforeEach(() => {
59+
viewport.set('xl');
60+
fixture = TestBed.createComponent(TestSystemHeaderHostComponent);
61+
testComponent = fixture.componentInstance;
62+
fixture.detectChanges();
63+
});
64+
it('should create', () => {
65+
expect(testComponent).toBeTruthy();
66+
});
67+
it('should display breadcrumb on desktop screen', () => {
68+
const breadcrumb = fixture.debugElement.query(By.css('bao-breadcrumb'));
69+
expect(breadcrumb).toBeDefined();
70+
});
71+
});
72+
describe('Tablet screen', () => {
73+
beforeEach(() => {
74+
viewport.set('md');
75+
fixture = TestBed.createComponent(TestSystemHeaderHostComponent);
76+
testComponent = fixture.componentInstance;
77+
fixture.detectChanges();
78+
});
79+
it('should display back button on tablet screen', () => {
80+
const backButton = fixture.debugElement.query(
81+
By.css('.bao-system-header-back-button')
82+
);
83+
expect(backButton).toBeDefined();
84+
});
85+
});
86+
describe('Mobile screen', () => {
87+
beforeEach(() => {
88+
viewport.set('sm');
89+
fixture = TestBed.createComponent(TestSystemHeaderHostComponent);
90+
testComponent = fixture.componentInstance;
91+
fixture.detectChanges();
92+
});
93+
it('should display back button on mobile screen', () => {
94+
const backButton = fixture.debugElement.query(
95+
By.css('.bao-system-header-back-button')
96+
);
97+
expect(backButton).toBeDefined();
98+
});
99+
it('should apply mobile css class', () => {
100+
const tagInfoContainer = fixture.debugElement.query(
101+
By.css('.tag-info-container')
102+
);
103+
expect(tagInfoContainer).toBeDefined();
104+
expect(
105+
tagInfoContainer.nativeNode.classList.contains('mobile')
106+
).toBeTrue();
107+
});
108+
});
109+
describe('BaoBackNavigationComponent', () => {
110+
let testComponent: TestBackNavigationHostComponent;
111+
let fixture: ComponentFixture<TestBackNavigationHostComponent>;
112+
let debugElement: DebugElement;
113+
beforeEach(() => {
114+
fixture = TestBed.createComponent(TestBackNavigationHostComponent);
115+
testComponent = fixture.componentInstance;
116+
fixture.detectChanges();
117+
});
118+
it('should create', () => {
119+
expect(testComponent).toBeTruthy();
120+
});
121+
it('should set link input as href attribute', () => {
122+
const parentLink = 'parent-page.ca';
123+
testComponent.link = parentLink;
124+
fixture.detectChanges();
125+
debugElement = fixture.debugElement.query(By.css('a'));
126+
expect(debugElement.nativeNode.attributes['href'].value).toBe(parentLink);
127+
});
128+
});
129+
});

0 commit comments

Comments
 (0)