Moves menu component into app component. Uses new scrollSpy directive to move selected section indicator.
This commit is contained in:
parent
e812fbb4ff
commit
5756615159
|
@ -1,12 +1,29 @@
|
||||||
<div class="main mat-typography">
|
<div
|
||||||
<app-menu id="menu"></app-menu>
|
class="main mat-typography"
|
||||||
<app-header id="header"></app-header>
|
scrollSpy (sectionChange)="onSectionChange($event)"
|
||||||
<app-welcome id="welcome"></app-welcome>
|
>
|
||||||
<app-about-us id="about_us"></app-about-us>
|
<div
|
||||||
<app-logo-values id="logo_values"></app-logo-values>
|
id="menu"
|
||||||
<app-team id="team"></app-team>
|
fxLayout="column"
|
||||||
<app-case-studies id="case_studies"></app-case-studies>
|
fxLayoutGap="20px"
|
||||||
<app-contact-us id="contact_us"></app-contact-us>
|
fxLayoutAlign="center end"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
*ngFor="let link of menuLinks"
|
||||||
|
mat-button
|
||||||
|
pageScroll
|
||||||
|
href="#{{ link.id }}"
|
||||||
|
(click)="onMenuClick(link.id)"
|
||||||
|
[ngClass]="{'active': currentSection === link.id}"
|
||||||
|
id="{{link.id}}_menu_link"
|
||||||
|
>{{ link.label }}</a
|
||||||
|
>
|
||||||
|
<div id="selected_indicator" [ngStyle]="{'top.px': activeLinkTop, 'opacity': showIndicator ? 1 : 0}"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngFor="let link of menuLinks" class="scroll-spy-section" id="{{link.id}}">
|
||||||
|
<ng-container *ngComponentOutlet="link.component"></ng-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
<app-footer id="footer"></app-footer>
|
<app-footer id="footer"></app-footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
@import "../config";
|
||||||
|
|
||||||
|
#menu {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 100;
|
||||||
|
height: 100vh;
|
||||||
|
width: 300px;
|
||||||
|
background-color: rgba(255, 255, 255, 0.8);
|
||||||
|
padding: 80px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
transition: all 1s ease-in-out 0.5s;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
font-weight: 500;
|
||||||
|
border-right: 2px solid $brand-primary;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#selected_indicator {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 80px;
|
||||||
|
width: 2px;
|
||||||
|
height: 36px;
|
||||||
|
background-color: $brand-primary;
|
||||||
|
transition: all 1s ease-in-out;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
|
@ -1,10 +1,65 @@
|
||||||
import { Component } from '@angular/core';
|
import {AfterViewInit, ChangeDetectionStrategy, Component, QueryList, ViewChildren} from '@angular/core';
|
||||||
|
import {HeaderComponent} from './header/header.component';
|
||||||
|
import {WelcomeComponent} from './welcome/welcome.component';
|
||||||
|
import {AboutUsComponent} from './about-us/about-us.component';
|
||||||
|
import {LogoValuesComponent} from './logo-values/logo-values.component';
|
||||||
|
import {TeamComponent} from './team/team.component';
|
||||||
|
import {CaseStudiesComponent} from './case-studies/case-studies.component';
|
||||||
|
import {ContactUsComponent} from './contact-us/contact-us.component';
|
||||||
|
|
||||||
|
interface MenuLink {
|
||||||
|
id: string;
|
||||||
|
label: string;
|
||||||
|
component: any;
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrls: ['./app.component.scss']
|
styleUrls: ['./app.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent implements AfterViewInit {
|
||||||
|
menuLinks: MenuLink[] = [
|
||||||
|
{id: 'header', label: 'Home', component: HeaderComponent},
|
||||||
|
{id: 'welcome', label: 'Intro', component: WelcomeComponent},
|
||||||
|
{id: 'about_us', label: 'About Us', component: AboutUsComponent},
|
||||||
|
{id: 'logo_values', label: 'Our Values', component: LogoValuesComponent},
|
||||||
|
{id: 'team', label: 'Our Team', component: TeamComponent},
|
||||||
|
{id: 'case_studies', label: 'Projects', component: CaseStudiesComponent},
|
||||||
|
{id: 'contact_us', label: 'Contact', component: ContactUsComponent},
|
||||||
|
];
|
||||||
|
|
||||||
|
@ViewChildren('scrollSpySection') scrollSpySections: QueryList<any>;
|
||||||
title = 'Sartography';
|
title = 'Sartography';
|
||||||
|
currentSection = 'header';
|
||||||
|
activeLinkTop: number;
|
||||||
|
showIndicator = false;
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
ngAfterViewInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
moveSelectedIndicator(linkId: string) {
|
||||||
|
this.currentSection = linkId;
|
||||||
|
const activeLinkEl = document.getElementById(`${this.currentSection}_menu_link`);
|
||||||
|
this.activeLinkTop = activeLinkEl.offsetTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMenuClick(linkId: string) {
|
||||||
|
this.showIndicator = true;
|
||||||
|
this.onSectionChange(linkId);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSectionChange(sectionId: string) {
|
||||||
|
this.currentSection = sectionId;
|
||||||
|
this.moveSelectedIndicator(this.currentSection);
|
||||||
|
console.log('section change to:', sectionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollTo(section) {
|
||||||
|
document.querySelector('#' + section)
|
||||||
|
.scrollIntoView();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,24 @@
|
||||||
import { HttpClientModule } from "@angular/common/http";
|
import {HttpClientModule} from '@angular/common/http';
|
||||||
import { NgModule } from "@angular/core";
|
import {NgModule} from '@angular/core';
|
||||||
import { FlexLayoutModule } from "@angular/flex-layout";
|
import {FlexLayoutModule} from '@angular/flex-layout';
|
||||||
import {
|
import {MatButtonModule, MatCardModule, MatIconModule, MatMenuModule, MatTabsModule, MatToolbarModule} from '@angular/material';
|
||||||
MatButtonModule,
|
import {BrowserModule} from '@angular/platform-browser';
|
||||||
MatCardModule,
|
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
||||||
MatIconModule,
|
import {InlineSVGModule} from 'ng-inline-svg';
|
||||||
MatMenuModule,
|
import {NgxPageScrollModule} from 'ngx-page-scroll';
|
||||||
MatTabsModule,
|
import {AboutUsComponent} from './about-us/about-us.component';
|
||||||
MatToolbarModule
|
import {ApiService} from './api.service';
|
||||||
} from "@angular/material";
|
import {AppComponent} from './app.component';
|
||||||
import { BrowserModule } from "@angular/platform-browser";
|
import {CaseStudiesComponent} from './case-studies/case-studies.component';
|
||||||
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
import {ContactUsComponent} from './contact-us/contact-us.component';
|
||||||
import { InlineSVGModule } from "ng-inline-svg";
|
import {FooterComponent} from './footer/footer.component';
|
||||||
import { NgxPageScrollModule } from "ngx-page-scroll";
|
import {HeaderComponent} from './header/header.component';
|
||||||
import { AboutUsComponent } from "./about-us/about-us.component";
|
import {TeamComponent} from './team/team.component';
|
||||||
import { ApiService } from "./api.service";
|
import {WelcomeComponent} from './welcome/welcome.component';
|
||||||
import { AppComponent } from "./app.component";
|
import {NgxPageScrollCoreModule} from 'ngx-page-scroll-core';
|
||||||
import { CaseStudiesComponent } from "./case-studies/case-studies.component";
|
import {easingFn} from './animation';
|
||||||
import { ContactUsComponent } from "./contact-us/contact-us.component";
|
import {LogoValuesComponent} from './logo-values/logo-values.component';
|
||||||
import { FooterComponent } from "./footer/footer.component";
|
import {ScrollSpyDirective} from './scroll-spy.directive';
|
||||||
import { HeaderComponent } from "./header/header.component";
|
|
||||||
import { MenuComponent } from "./menu/menu.component";
|
|
||||||
import { TeamComponent } from "./team/team.component";
|
|
||||||
import { WelcomeComponent } from "./welcome/welcome.component";
|
|
||||||
import { NgxPageScrollCoreModule } from 'ngx-page-scroll-core';
|
|
||||||
import { easingFn } from './animation';
|
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -35,9 +28,10 @@ import { easingFn } from './animation';
|
||||||
ContactUsComponent,
|
ContactUsComponent,
|
||||||
FooterComponent,
|
FooterComponent,
|
||||||
HeaderComponent,
|
HeaderComponent,
|
||||||
MenuComponent,
|
LogoValuesComponent,
|
||||||
|
ScrollSpyDirective,
|
||||||
TeamComponent,
|
TeamComponent,
|
||||||
WelcomeComponent
|
WelcomeComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
|
@ -55,6 +49,16 @@ import { easingFn } from './animation';
|
||||||
NgxPageScrollCoreModule.forRoot({easingLogic: easingFn})
|
NgxPageScrollCoreModule.forRoot({easingLogic: easingFn})
|
||||||
],
|
],
|
||||||
providers: [ApiService],
|
providers: [ApiService],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent],
|
||||||
|
entryComponents: [
|
||||||
|
AboutUsComponent,
|
||||||
|
CaseStudiesComponent,
|
||||||
|
ContactUsComponent,
|
||||||
|
HeaderComponent,
|
||||||
|
LogoValuesComponent,
|
||||||
|
TeamComponent,
|
||||||
|
WelcomeComponent,
|
||||||
|
]
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
<div
|
|
||||||
class="menu"
|
|
||||||
fxLayout="column"
|
|
||||||
fxLayoutGap="20px"
|
|
||||||
fxLayoutAlign="center end"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
*ngFor="let link of menuLinks"
|
|
||||||
mat-button
|
|
||||||
pageScroll
|
|
||||||
href="#{{ link.id }}"
|
|
||||||
>{{ link.label }}</a
|
|
||||||
>
|
|
||||||
</div>
|
|
|
@ -1,10 +0,0 @@
|
||||||
.menu {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 100;
|
|
||||||
height: 100vh;
|
|
||||||
width: 300px;
|
|
||||||
background-color: rgba(255, 255, 255, 0.8);
|
|
||||||
padding: 80px;
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { MenuComponent } from './menu.component';
|
|
||||||
|
|
||||||
describe('MenuComponent', () => {
|
|
||||||
let component: MenuComponent;
|
|
||||||
let fixture: ComponentFixture<MenuComponent>;
|
|
||||||
|
|
||||||
beforeEach(async(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [ MenuComponent ]
|
|
||||||
})
|
|
||||||
.compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(MenuComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,29 +0,0 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
import { ViewportScroller } from '@angular/common';
|
|
||||||
|
|
||||||
interface MenuLink {
|
|
||||||
id: string;
|
|
||||||
label: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-menu',
|
|
||||||
templateUrl: './menu.component.html',
|
|
||||||
styleUrls: ['./menu.component.scss']
|
|
||||||
})
|
|
||||||
export class MenuComponent implements OnInit {
|
|
||||||
activeLink = 'header';
|
|
||||||
menuLinks: MenuLink[] = [
|
|
||||||
{ id: 'header', label: 'Home' },
|
|
||||||
{ id: 'welcome', label: 'Intro' },
|
|
||||||
{ id: 'about_us', label: 'About Us' },
|
|
||||||
{ id: 'logo_values', label: 'Our Values' },
|
|
||||||
{ id: 'team', label: 'Our Team' },
|
|
||||||
{ id: 'case_studies', label: 'Projects' },
|
|
||||||
{ id: 'contact_us', label: 'Contact' }
|
|
||||||
];
|
|
||||||
|
|
||||||
constructor(private viewportScroller: ViewportScroller) {}
|
|
||||||
|
|
||||||
ngOnInit() {}
|
|
||||||
}
|
|
Loading…
Reference in New Issue