projects/tl-elements/src/lib/tl-mega-menu/tl-mega-menu.component.ts
changeDetection | ChangeDetectionStrategy.Default |
selector | tl-mega-menu-component |
styleUrls | ./tl-mega-menu.component.scss |
templateUrl | ./tl-mega-menu.component.html |
Properties |
|
Methods |
Inputs |
HostBindings |
HostListeners |
Accessors |
constructor(injector: Injector)
|
||||||
Parameters :
|
menuTitle | |
Type : string
|
|
Default value : 'Mega Menu'
|
|
The default text value to be displayed for tl-mega menu title. |
openDelay | |
Type : number
|
|
Default value : 50
|
|
This property determines the delay in milliseconds the dropdown takes prior to display on mouse hover. |
outOfHeader | |
Type : boolean
|
|
Default value : false
|
|
The boolean variable enables proper header display on window resize. |
viewAllButtonText | |
Type : string
|
|
This variable allows customizing the text value of View All button in the mega menu. |
viewAllHref | |
Type : any
|
|
This allows to provide href value for tl mega menu section href. |
inheritFontStyle | |
Type : "true" | "false"
|
|
Inherited from
TamuAbstractBaseComponent
|
|
Defined in
TamuAbstractBaseComponent:14
|
style.--tl-mobile-display-max-height |
Type : string
|
Default value : '0px'
|
Allows for the override of the --tl-mobile-display-max-height variable. |
style.--tl-font-family-sans-serif |
Type : string
|
Default value : 'var(--tl-default-font-family-sans-serif)'
|
Inherited from
TamuAbstractBaseComponent
|
Defined in
TamuAbstractBaseComponent:12
|
Allows for the override of the --tl-font-family-sans-serif css variable. |
style.--tl-font-size |
Type : string
|
Default value : 'var(--tl-default-font-size)'
|
Inherited from
TamuAbstractBaseComponent
|
Defined in
TamuAbstractBaseComponent:9
|
Allows for the override of the --tl-default-font-size css variable. |
window:resize |
window:resize()
|
This event listener on window resize event helps the header for proper display. |
addSection | ||||||
addSection(section: TlMegaMenuSectionComponent)
|
||||||
Parameters :
Returns :
void
|
calculateMenuXOffset |
calculateMenuXOffset()
|
Decorators :
@HostListener('window:resize')
|
This event listener on window resize event helps the header for proper display.
Returns :
void
|
ngAfterContentInit |
ngAfterContentInit()
|
This adjusts the dropdown menu x offset on page load.
Returns :
void
|
toggleMobileMenuOpen |
toggleMobileMenuOpen()
|
This toggles the display of mobile menu on click event.
Returns :
void
|
active |
Default value : false
|
menuXOffset |
Type : number
|
Default value : 0
|
This property determines the mega menu dropdown x-offset. |
mobileDisplayMaxHeight |
Type : string
|
Default value : '0px'
|
Decorators :
@HostBinding('style.--tl-mobile-display-max-height')
|
Allows for the override of the --tl-mobile-display-max-height variable. |
Private Readonly sections |
Type : Array<TlMegaMenuSectionComponent>
|
Private sectionTitleHeight |
Type : number
|
Default value : 0
|
variantTypes |
Type : []
|
Default value : ['button']
|
_fontFamily |
Type : string
|
Default value : 'var(--tl-default-font-family-sans-serif)'
|
Decorators :
@HostBinding('style.--tl-font-family-sans-serif')
|
Inherited from
TamuAbstractBaseComponent
|
Defined in
TamuAbstractBaseComponent:12
|
Allows for the override of the --tl-font-family-sans-serif css variable. |
_fontSize |
Type : string
|
Default value : 'var(--tl-default-font-size)'
|
Decorators :
@HostBinding('style.--tl-font-size')
|
Inherited from
TamuAbstractBaseComponent
|
Defined in
TamuAbstractBaseComponent:9
|
Allows for the override of the --tl-default-font-size css variable. |
viewAllButtonDisplayText |
getviewAllButtonDisplayText()
|
This returns customized text or the default value to be displayed on the mega menu View All button.
Returns :
string
|
import { AfterContentInit, ChangeDetectionStrategy, Component, HostBinding, HostListener, Injector, Input } from '@angular/core';
import { debounce, wvrTimeout } from '@wvr/elements';
import { TamuAbstractBaseComponent } from '../shared/tl-abstract-base.component';
import { TlMegaMenuSectionComponent } from './tl-mega-menu-section/tl-mega-menu-section.component';
@Component({
selector: 'tl-mega-menu-component',
templateUrl: './tl-mega-menu.component.html',
styleUrls: ['./tl-mega-menu.component.scss'],
changeDetection: ChangeDetectionStrategy.Default
})
export class TlMegaMenuComponent extends TamuAbstractBaseComponent implements AfterContentInit {
/** The default text value to be displayed for tl-mega menu title. */
@Input() menuTitle = 'Mega Menu';
/** This allows to provide href value for tl mega menu section href. */
@Input() viewAllHref;
/** The boolean variable enables proper header display on window resize. */
@Input() outOfHeader = false;
/** This property determines the mega menu dropdown x-offset. */
menuXOffset = 0;
/** This variable allows customizing the text value of View All button in the mega menu. */
@Input() viewAllButtonText: string;
active = false;
/** This property determines the delay in milliseconds the dropdown takes prior to display on mouse hover. */
@Input() openDelay = 50;
/** This returns customized text or the default value to be displayed on the mega menu View All button. */
get viewAllButtonDisplayText(): string {
return this.viewAllButtonText ? this.viewAllButtonText : `View All ${this.menuTitle}`;
}
/** Allows for the override of the --tl-mobile-display-max-height variable. */
@HostBinding('style.--tl-mobile-display-max-height') mobileDisplayMaxHeight = '0px';
private readonly sections: Array<TlMegaMenuSectionComponent>;
private sectionTitleHeight = 0;
variantTypes = ['button'];
// tslint:disable-next-line:unnecessary-constructor
constructor(injector: Injector) {
super(injector);
this.sections = new Array<TlMegaMenuSectionComponent>();
}
/** This adjusts the dropdown menu x offset on page load. */
ngAfterContentInit(): void {
super.ngAfterContentInit();
wvrTimeout(() => {
this.calculateMenuXOffset();
});
}
addSection(section: TlMegaMenuSectionComponent): void {
this.sections.push(section);
this.sectionTitleHeight = section.getElementHeight() > this.sectionTitleHeight
? section.getElementHeight()
: this.sectionTitleHeight;
}
/** This toggles the display of mobile menu on click event. */
toggleMobileMenuOpen(): void {
this.mobileDisplayMaxHeight = `${this.sections.length * this.sectionTitleHeight}px`;
if (this.active) {
this.sections.forEach(s => {
s.close();
});
this.active = false;
} else {
this.active = true;
}
}
/** This event listener on window resize event helps the header for proper display. */
@HostListener('window:resize') @debounce() calculateMenuXOffset(): void {
if (!this.outOfHeader) {
const nativeElem = this.eRef.nativeElement as HTMLElement;
const header = document.querySelector('tl-header');
if (!header) { return; }
const bottomNav = header.shadowRoot.querySelector('div[bottom-navigation]');
if (bottomNav) {
let wvrBtn;
const frameReq = requestAnimationFrame(() => {
wvrBtn = nativeElem.querySelector('wvr-button-component');
if (wvrBtn && bottomNav.children.length >= 2) {
this.menuXOffset = (bottomNav.children[1] as HTMLElement).offsetLeft - nativeElem.parentElement.offsetLeft;
cancelAnimationFrame(frameReq);
}
});
}
}
}
}
<wvr-dropdown-component
[themeVariant]="'link'"
[toggleOn]="'mouseover'"
menuXOffset="{{menuXOffset}}px"
[menuYOffset]="'-2px'"
[menuWidth]="'928px'"
[btnTextDecoration]="'none'"
[btnColor]="'var(--tl-black)'"
[btnFontWeight]="'bolder'"
[btnColorHover]="'var(--tl-black)'"
[btnTextDecorationHover]="'none'"
[btnFontFamily]="'var(--tl-font-family-sans-serif)'"
[ngClass]="{active: active}"
[openDelay]="openDelay"
ngbDropdownAnchor>
<template dropdown-button>
<span (click)="toggleMobileMenuOpen()">
{{menuTitle}}
<tl-icon-component
class="x-icon"
[hiddenInMobile]="true"
[set]="'bootstrap'"
[name]="'caret-right-fill'"
[size]="'11px'">
</tl-icon-component>
<tl-icon-component
class="plus-icon"
[set]="'bootstrap'"
[name]="'plus'"
[size]="'24px'">
</tl-icon-component>
</span>
</template>
<template dropdown-menu>
<div class="tl-mega-menu-custom-top" *ngIf="!isMobileLayout">
<div class="flex-fill align-self-stretch">
<ng-content select="tl-mega-menu-custom[top-content]"></ng-content>
</div>
</div>
<div class="mega-menu-sections d-flex justify-content-between flex-wrap" *ngIf="!isMobileLayout">
<ng-container *ngTemplateOutlet="sections"></ng-container>
</div>
<div class="tl-mega-menu-custom-bottom" *ngIf="!isMobileLayout">
<div class="flex-fill align-self-stretch">
<ng-content select="tl-mega-menu-custom[bottom-content]"></ng-content>
</div>
</div>
<div class="mega-menu-view-all container pt-2" *ngIf="viewAllHref">
<tl-button-component [href]="viewAllHref" [themeVariant]="'primary'">
<template button-content>
<wvr-text-component [value]="viewAllButtonDisplayText"></wvr-text-component>
</template>
</tl-button-component>
</div>
</template>
</wvr-dropdown-component>
<div *ngIf="isMobileLayout" class="mobile-display" [ngClass]="{active: active}">
<ng-container *ngTemplateOutlet="sections"></ng-container>
<tl-mega-menu-section [sectionTitle]="viewAllButtonDisplayText" [viewAllHref]="viewAllHref"></tl-mega-menu-section>
</div>
<ng-template #sections>
<ng-content select="tl-mega-menu-section"></ng-content>
</ng-template>
./tl-mega-menu.component.scss
@import "../shared/styles/tl-variables.scss";
:host {
font-family: var(--tl-font-family-sans-serif);
--tl-mobile-display-max-height: 1500px;
.mega-menu-sections {
margin: 0px 20px;
}
.mega-menu-view-all {
display: flex;
justify-content: flex-end;
}
wvr-dropdown-component {
::ng-deep {
@import "~@wvr/elements/styles/variables";
@import "~bootstrap/scss/bootstrap";
@import "~@wvr/elements/styles/mixins";
@import "~@wvr/elements/styles/overrides";
.wvr-dropdown .dropdown {
.btn.btn-link.dropdown-toggle,
.btn.btn-link:not(:disabled):not(.disabled).active,
.btn.btn-link:not(:disabled):not(.disabled):active {
text-decoration: none !important;
color: var(--tl-black) !important;
}
.btn {
width: 100%;
tl-icon-component.x-icon svg {
transition: transform 0.25s ease-in-out;
transform: rotate(0deg);
}
tl-icon-component.plus-icon svg {
transition: transform 0.25s ease-in-out;
transform: rotate(0deg);
}
}
}
}
}
wvr-dropdown-component:focus-within,
wvr-dropdown-component:hover {
::ng-deep {
.wvr-dropdown .dropdown {
.btn {
tl-icon-component.x-icon svg {
transition: transform 0.25s ease-in-out;
transform: rotate(90deg);
}
}
}
}
}
wvr-dropdown-component.active {
::ng-deep {
.wvr-dropdown .dropdown {
.btn {
tl-icon-component.plus-icon svg {
transition: transform 0.25s ease-in-out;
transform: rotate(45deg);
}
}
}
}
}
.mobile-display {
max-height: 0px;
overflow: hidden;
transition: max-height 1s ease-in-out;
background: var(--tl-grey);
::ng-deep {
tl-mega-menu-section-component,
tl-mega-menu-section {
display: flex;
flex-direction: column;
width: 100%;
padding: 0px;
a {
margin: 0px 15px 0px 0px;
padding: 20px 0px 0px 60px;
text-align: start;
color: var(--tl-black);
font-size: 17px;
font-family: var(--tl-font-family-sans-serif);
font-weight: 300;
wvre-text {
font-weight: 400;
padding: 0px;
margin: 0px;
border-bottom: 0.5px solid #e4e4e4;
display: flex;
height: 40px;
width: 97%;
}
}
a:focus-within,
a:hover {
border-bottom: none;
wvre-text {
border-bottom: none;
}
}
.section-title {
cursor: pointer;
margin: 0px 15px 0px 30px;
padding: 20px 0px;
text-align: start;
color: var(--tl-black);
font-size: 17px;
font-family: var(--tl-font-family-sans-serif);
font-weight: 300;
border-bottom: 0.5px solid #e4e4e4;
text-decoration: none;
}
a.mega-menu-view-all {
cursor: pointer;
margin: 0px 15px 0px 30px;
padding: 20px 0px;
text-align: start;
color: var(--tl-black);
font-size: 17px;
font-family: var(--tl-font-family-sans-serif);
font-weight: 300;
border-bottom: 0.5px solid #e4e4e4;
}
}
}
}
.mobile-display.active {
max-height: var(--tl-mobile-display-max-height);
transition: max-height 0.5s ease-in-out;
}
::ng-deep {
tl-button-component {
--tl-btn-border-radius: 0px;
}
.wvr-dropdown .dropdown {
wvr-button-component {
width: 100%;
tl-icon-component.plus-icon {
display: none;
float: right;
}
tl-icon-component.x-icon {
display: inline-block;
}
}
[ngbDropdownMenu] {
padding: 20px 0px;
border: 1px solid var(--tl-grey);
border-radius: 3px;
border-bottom: 12px solid var(--tl-deep-yellow);
box-shadow: 0px 2px 3px 1px var(--tl-grey);
}
}
}
@media (max-width: 992px) {
wvr-dropdown-component {
::ng-deep {
.wvr-dropdown .dropdown {
.btn {
text-align: start !important;
}
}
}
}
::ng-deep {
div[template="dropdown-menu"] {
display: none;
}
.wvr-dropdown .dropdown {
wvr-button-component {
tl-icon-component.plus-icon {
display: inline-block;
}
tl-icon-component.x-icon {
display: none;
}
}
}
}
}
}