Skip to content

Commit

Permalink
feat(agora): migrate Header component and utils (AG-1549) (Sage-Bione…
Browse files Browse the repository at this point in the history
  • Loading branch information
sagely1 authored Sep 27, 2024
1 parent c3184a7 commit 303d4b7
Show file tree
Hide file tree
Showing 11 changed files with 420 additions and 14 deletions.
2 changes: 1 addition & 1 deletion apps/agora/app/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<!-- <agora-header></agora-header> -->
<agora-header></agora-header>
<router-outlet></router-outlet>
<agora-footer></agora-footer>
4 changes: 2 additions & 2 deletions apps/agora/app/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Component, inject, OnInit } from '@angular/core';
import { Meta, Title } from '@angular/platform-browser';
import { ActivatedRoute, NavigationEnd, Router, RouterModule } from '@angular/router';
import { FooterComponent } from '@sagebionetworks/agora/ui';
import { FooterComponent, HeaderComponent } from '@sagebionetworks/agora/ui';
import { filter } from 'rxjs';

@Component({
standalone: true,
imports: [RouterModule, FooterComponent],
imports: [RouterModule, HeaderComponent, FooterComponent],
selector: 'app-root',
templateUrl: './app.component.html',
styleUrl: './app.component.scss',
Expand Down
2 changes: 1 addition & 1 deletion libs/agora/ui/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// export * from './lib/components/header/header.component';
export * from './lib/components/header/header.component';
export * from './lib/components/footer/footer.component';
export * from './lib/components/loading-icon/loading-icon.component';
// export * from './lib/components/modal-link/modal-link.component';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<img [src]="footerLogoPath" alt="footer logo" />
</a>
</li>
@for (item of navItems; track item.url) {
@for (item of navItems; track item.label) {
<li>
@if (item.routerLink) {
<a [routerLink]="item.routerLink" routerLinkActive="active"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { HttpClientModule } from '@angular/common/http';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { FooterComponent } from './footer.component';
import { provideHttpClient } from '@angular/common/http';
import { provideRouter } from '@angular/router';

describe('FooterComponent', () => {
let component: FooterComponent;
let fixture: ComponentFixture<FooterComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [HttpClientModule, RouterTestingModule],
imports: [],
providers: [provideRouter([]), provideHttpClient()],
}).compileComponents();
});

Expand Down
12 changes: 6 additions & 6 deletions libs/agora/ui/src/lib/components/footer/footer.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { Component, inject, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { Dataversion, DataversionService } from '@sagebionetworks/agora/api-client-angular';
Expand All @@ -16,6 +16,10 @@ import { NavigationLink } from '../../models/navigation-link';
styleUrls: ['./footer.component.scss'],
})
export class FooterComponent implements OnInit {
configService = inject(ConfigService);
dataVersionService = inject(DataversionService);
sanitizer = inject(PathSanitizer);

footerLogoPath!: SafeUrl;
dataVersion$!: Observable<Dataversion>;

Expand All @@ -36,11 +40,7 @@ export class FooterComponent implements OnInit {
},
];

constructor(
private readonly configService: ConfigService,
private dataVersionService: DataversionService,
private sanitizer: PathSanitizer,
) {
constructor() {
this.footerLogoPath = this.sanitizer.sanitize('/agora-assets/images/footer-logo.svg');
}

Expand Down
53 changes: 53 additions & 0 deletions libs/agora/ui/src/lib/components/header/header.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<header>
<div id="header" [ngClass]="{ 'is-mobile': isMobile }" (window:resize)="onResize()">
<div class="header-inner">
<div class="header-logo">
<a routerLink="/">
<img [src]="headerLogoPath" alt="header logo" />
</a>
</div>
@if (navItems.length > 0) {
<div class="header-nav" [ngClass]="{ show: isShown }">
<button class="header-nav-toggle" (click)="toggleNav()">
<span></span>
<span></span>
<span></span>
</button>
<div class="header-nav-inner">
<ul>
@for (item of navItems; track item.label) {
<li>
@if (item.routerLink) {
<a
[routerLink]="item.routerLink"
routerLinkActive="active"
[routerLinkActiveOptions]="item.activeOptions || { exact: false }"
(click)="toggleNav()"
>
<span>{{ item.label }}</span>
</a>
} @else if (item.url) {
<a
*ngIf="item.url"
[attr.href]="item.url"
[attr.target]="item.target"
(click)="toggleNav()"
>
<span>{{ item.label }}</span>
</a>
} @else {
<span>{{ item.label }}</span>
}
</li>
}
</ul>

<div class="separator"></div>

<!-- <gene-search class="header-search" (searchNavigated)="toggleNav()"></gene-search> -->
</div>
</div>
}
</div>
</div>
</header>
230 changes: 230 additions & 0 deletions libs/agora/ui/src/lib/components/header/header.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
/* stylelint-disable plugin/no-unsupported-browser-features */

@import 'libs/agora/styles/src/lib/constants';
@import 'libs/agora/styles/src/lib/mixins';

#header {
// Uncomment for sticky header
// position: fixed;
// top: 0;
// left: 0;
// right: 0;
// border-bottom: 1px solid var(--color-gray-200);
position: relative;
background-color: #fff;
z-index: 999;

.header-inner {
@include container('lg');

padding: 0 var(--spacing-xl);
display: flex;
height: calc(var(--header-height) - 1px);
}
}

.header-logo {
display: flex;
align-items: center;
}

.header-nav {
display: flex;
flex-grow: 1;
justify-content: flex-end;
align-items: center;

.header-nav-toggle {
@include reset-button;

position: relative;
width: 20px;
height: 20px;
cursor: pointer;

span {
display: block;
position: absolute;
left: 0;
right: 0;
background-color: var(--color-primary);
height: 4px;
transition: var(--transition-duration);

&:nth-child(1) {
top: 0;
}

&:nth-child(2) {
top: 50%;
margin-top: -2px;
}

&:nth-child(3) {
bottom: 0;
}
}

&:hover {
opacity: 0.8;
}
}

ul {
list-style: none;
padding: 0;
margin: 0;
}

a {
font-size: var(--font-size-lg);
color: var(--color-text);
text-decoration: none;
}

.separator {
border-left: 2px solid var(--color-separator);
height: var(--spacing-lg);
box-sizing: border-box;
}

.header-search {
height: fit-content;
}
}

#header:not(.is-mobile) {
.header-nav-toggle {
display: none;
}

.header-nav {
.header-nav-inner {
display: flex;
justify-content: flex-end;
align-items: center;
gap: var(--spacing-lg);
}

ul {
display: flex;
height: 100%;
gap: var(--spacing-md);
}

li {
padding: 0 20px;
}

a {
position: relative;
display: flex;
font-weight: 700;
padding: 8px 0;
color: var(--color-text-secondary);
transition: var(--transition-duration);
align-items: center;

&:hover {
color: var(--color-action-primary);
}

&::after {
content: ' ';
position: absolute;
display: block;
bottom: 0;
left: 0;
right: 0;
height: 4px;
background-color: var(--color-action-primary);
border-radius: 2px;
opacity: 0;
visibility: hidden;
transition: var(--transition-duration);
}

&.active {
color: var(--color-action-primary);

&::after {
opacity: 1;
visibility: visible;
}
}
}
}
}

#header.is-mobile {
.header-nav {
.header-nav-inner {
position: absolute;
top: 100%;
left: 0;
right: 0;
padding: 30px;
background-color: #fff;
border-top: 1px solid var(--color-gray-300);
border-bottom: 1px solid var(--color-gray-300);
opacity: 0;
visibility: hidden;
}

ul {
li {
padding: 10px 0;
}
}

a {
&.active {
position: relative;
color: var(--color-action-primary);

&::after {
content: ' ';
position: absolute;
display: block;
bottom: -4px;
left: 0;
right: 0;
height: 4px;
background-color: var(--color-action-primary);
border-radius: 2px;
transition: var(--transition-duration);
}
}
}

&.show {
.header-nav-toggle {
span {
&:nth-child(1) {
right: -5px;
transform: rotate(45deg) translate(5px, 6px);
}

&:nth-child(2) {
opacity: 0;
}

&:nth-child(3) {
right: -5px;
transform: rotate(-45deg) translate(5px, -6px);
}
}
}

.header-nav-inner {
opacity: 1;
visibility: visible;
}
}
}

.separator {
opacity: 0;
height: 15px;
}
}
26 changes: 26 additions & 0 deletions libs/agora/ui/src/lib/components/header/header.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HeaderComponent } from './header.component';
import { provideHttpClient } from '@angular/common/http';
import { provideRouter } from '@angular/router';

describe('HeaderComponent', () => {
let component: HeaderComponent;
let fixture: ComponentFixture<HeaderComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [],
providers: [provideRouter([]), provideHttpClient()],
}).compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(HeaderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Loading

0 comments on commit 303d4b7

Please sign in to comment.