diff --git a/aio/src/app/app.component.spec.ts b/aio/src/app/app.component.spec.ts
index ce1c4d75c3..a872868931 100644
--- a/aio/src/app/app.component.spec.ts
+++ b/aio/src/app/app.component.spec.ts
@@ -25,11 +25,9 @@ import { first, mapTo } from 'rxjs/operators';
import { MockLocationService } from 'testing/location.service';
import { MockLogger } from 'testing/logger.service';
import { MockSearchService } from 'testing/search.service';
-import { AppComponent } from './app.component';
+import { AppComponent, dockSideNavWidth, showFloatingTocWidth, showTopMenuWidth } from './app.component';
import { AppModule } from './app.module';
-const sideBySideBreakPoint = 992;
-const hideToCBreakPoint = 800;
const startedDelay = 100;
describe('AppComponent', () => {
@@ -58,7 +56,7 @@ describe('AppComponent', () => {
component = fixture.componentInstance;
fixture.detectChanges();
- component.onResize(sideBySideBreakPoint + 1); // wide by default
+ component.onResize(showTopMenuWidth + 1); // wide by default
const de = fixture.debugElement;
const docViewerDe = de.query(By.css('aio-doc-viewer'));
@@ -99,7 +97,7 @@ describe('AppComponent', () => {
});
it('should be false on narrow screens', () => {
- component.onResize(hideToCBreakPoint - 1);
+ component.onResize(showFloatingTocWidth - 1);
tocService.tocList.next([{}, {}, {}] as TocItem[]);
expect(component.hasFloatingToc).toBe(false);
@@ -112,7 +110,7 @@ describe('AppComponent', () => {
});
it('should be true on wide screens unless the toc is empty', () => {
- component.onResize(hideToCBreakPoint + 1);
+ component.onResize(showFloatingTocWidth + 1);
tocService.tocList.next([{}, {}, {}] as TocItem[]);
expect(component.hasFloatingToc).toBe(true);
@@ -127,37 +125,47 @@ describe('AppComponent', () => {
it('should be false when toc is empty', () => {
tocService.tocList.next([]);
- component.onResize(hideToCBreakPoint + 1);
+ component.onResize(showFloatingTocWidth + 1);
expect(component.hasFloatingToc).toBe(false);
- component.onResize(hideToCBreakPoint - 1);
+ component.onResize(showFloatingTocWidth - 1);
expect(component.hasFloatingToc).toBe(false);
- component.onResize(hideToCBreakPoint + 1);
+ component.onResize(showFloatingTocWidth + 1);
expect(component.hasFloatingToc).toBe(false);
});
it('should be true when toc is not empty unless the screen is narrow', () => {
tocService.tocList.next([{}, {}, {}] as TocItem[]);
- component.onResize(hideToCBreakPoint + 1);
+ component.onResize(showFloatingTocWidth + 1);
expect(component.hasFloatingToc).toBe(true);
- component.onResize(hideToCBreakPoint - 1);
+ component.onResize(showFloatingTocWidth - 1);
expect(component.hasFloatingToc).toBe(false);
- component.onResize(hideToCBreakPoint + 1);
+ component.onResize(showFloatingTocWidth + 1);
expect(component.hasFloatingToc).toBe(true);
});
});
- describe('isSideBySide', () => {
+ describe('showTopMenu', () => {
it('should be updated on resize', () => {
- component.onResize(sideBySideBreakPoint - 1);
- expect(component.isSideBySide).toBe(false);
+ component.onResize(showTopMenuWidth - 1);
+ expect(component.showTopMenu).toBe(false);
- component.onResize(sideBySideBreakPoint + 1);
- expect(component.isSideBySide).toBe(true);
+ component.onResize(showTopMenuWidth + 1);
+ expect(component.showTopMenu).toBe(true);
+ });
+ });
+
+ describe('dockSideNav', () => {
+ it('should be updated on resize', () => {
+ component.onResize(dockSideNavWidth - 1);
+ expect(component.dockSideNav).toBe(false);
+
+ component.onResize(dockSideNavWidth + 1);
+ expect(component.dockSideNav).toBe(true);
});
});
@@ -185,8 +193,8 @@ describe('AppComponent', () => {
fixture.detectChanges();
};
- describe('when side-by-side (wide)', () => {
- beforeEach(() => resizeTo(sideBySideBreakPoint + 1)); // side-by-side
+ describe('when view is wide', () => {
+ beforeEach(() => resizeTo(dockSideNavWidth + 1)); // wide view
it('should open when navigating to a guide page (guide/pipes)', () => {
navigateTo('guide/pipes');
@@ -232,8 +240,8 @@ describe('AppComponent', () => {
});
});
- describe('when NOT side-by-side (narrow)', () => {
- beforeEach(() => resizeTo(sideBySideBreakPoint - 1)); // NOT side-by-side
+ describe('when view is narrow', () => {
+ beforeEach(() => resizeTo(dockSideNavWidth - 1)); // narrow view
it('should be closed when navigating to a guide page (guide/pipes)', () => {
navigateTo('guide/pipes');
@@ -286,30 +294,30 @@ describe('AppComponent', () => {
});
});
- describe('when changing side-by-side (narrow --> wide)', () => {
+ describe('when changing from narrow to wide view', () => {
const sidenavDocs = ['api/a/b/c/d', 'guide/pipes'];
const nonSidenavDocs = ['features', 'about'];
sidenavDocs.forEach(doc => {
it(`should open when on a sidenav doc (${doc})`, () => {
- resizeTo(sideBySideBreakPoint - 1);
+ resizeTo(dockSideNavWidth - 1);
navigateTo(doc);
expect(sidenav.opened).toBe(false);
- resizeTo(sideBySideBreakPoint + 1);
+ resizeTo(dockSideNavWidth + 1);
expect(sidenav.opened).toBe(true);
});
});
nonSidenavDocs.forEach(doc => {
it(`should remain closed when on a non-sidenav doc (${doc})`, () => {
- resizeTo(sideBySideBreakPoint - 1);
+ resizeTo(dockSideNavWidth - 1);
navigateTo(doc);
expect(sidenav.opened).toBe(false);
- resizeTo(sideBySideBreakPoint + 1);
+ resizeTo(dockSideNavWidth + 1);
expect(sidenav.opened).toBe(false);
});
});
@@ -317,33 +325,33 @@ describe('AppComponent', () => {
describe('when manually opened', () => {
sidenavDocs.forEach(doc => {
it(`should remain opened when on a sidenav doc (${doc})`, () => {
- resizeTo(sideBySideBreakPoint - 1);
+ resizeTo(dockSideNavWidth - 1);
navigateTo(doc);
toggleSidenav();
expect(sidenav.opened).toBe(true);
- resizeTo(sideBySideBreakPoint + 1);
+ resizeTo(dockSideNavWidth + 1);
expect(sidenav.opened).toBe(true);
});
});
nonSidenavDocs.forEach(doc => {
it(`should close when on a non-sidenav doc (${doc})`, () => {
- resizeTo(sideBySideBreakPoint - 1);
+ resizeTo(dockSideNavWidth - 1);
navigateTo(doc);
toggleSidenav();
expect(sidenav.opened).toBe(true);
- resizeTo(sideBySideBreakPoint + 1);
+ resizeTo(showTopMenuWidth + 1);
expect(sidenav.opened).toBe(false);
});
});
});
});
- describe('when changing side-by-side (wide --> narrow)', () => {
+ describe('when changing from wide to narrow view', () => {
const sidenavDocs = ['api/a/b/c/d', 'guide/pipes'];
const nonSidenavDocs = ['features', 'about'];
@@ -352,7 +360,7 @@ describe('AppComponent', () => {
navigateTo(doc);
expect(sidenav.opened).toBe(true);
- resizeTo(sideBySideBreakPoint - 1);
+ resizeTo(dockSideNavWidth - 1);
expect(sidenav.opened).toBe(false);
});
});
@@ -362,7 +370,7 @@ describe('AppComponent', () => {
navigateTo(doc);
expect(sidenav.opened).toBe(false);
- resizeTo(sideBySideBreakPoint - 1);
+ resizeTo(dockSideNavWidth - 1);
expect(sidenav.opened).toBe(false);
});
});
@@ -376,7 +384,7 @@ describe('AppComponent', () => {
async function setupSelectorForTesting(mode?: string) {
createTestingModule('a/b', mode);
await initializeTest();
- component.onResize(sideBySideBreakPoint + 1); // side-by-side
+ component.onResize(dockSideNavWidth + 1); // wide view
selectElement = fixture.debugElement.query(By.directive(SelectComponent));
selectComponent = selectElement.componentInstance;
}
diff --git a/aio/src/app/app.component.ts b/aio/src/app/app.component.ts
index bedd804613..822f4b2e5e 100644
--- a/aio/src/app/app.component.ts
+++ b/aio/src/app/app.component.ts
@@ -14,6 +14,9 @@ import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
import { first, map } from 'rxjs/operators';
const sideNavView = 'SideNav';
+export const showTopMenuWidth = 992;
+export const dockSideNavWidth = 992;
+export const showFloatingTocWidth = 800;
@Component({
selector: 'aio-shell',
@@ -57,18 +60,17 @@ export class AppComponent implements OnInit {
isStarting = true;
isTransitioning = true;
isFetching = false;
- isSideBySide = false;
+ showTopMenu = false;
+ dockSideNav = false;
private isFetchingTimeout: any;
private isSideNavDoc = false;
- private sideBySideWidth = 992;
sideNavNodes: NavigationNode[];
topMenuNodes: NavigationNode[];
topMenuNarrowNodes: NavigationNode[];
hasFloatingToc = false;
private showFloatingToc = new BehaviorSubject(false);
- private showFloatingTocWidth = 800;
tocMaxHeight: string;
private tocMaxHeightOffset = 0;
@@ -76,8 +78,8 @@ export class AppComponent implements OnInit {
private currentUrl: string;
- get isOpened() { return this.isSideBySide && this.isSideNavDoc; }
- get mode() { return this.isSideBySide ? 'side' : 'over'; }
+ get isOpened() { return this.dockSideNav && this.isSideNavDoc; }
+ get mode() { return this.dockSideNav && (this.isSideNavDoc || this.showTopMenu) ? 'side' : 'over'; }
// Search related properties
showSearchResults = false;
@@ -239,13 +241,14 @@ export class AppComponent implements OnInit {
@HostListener('window:resize', ['$event.target.innerWidth'])
onResize(width: number) {
- this.isSideBySide = width >= this.sideBySideWidth;
- this.showFloatingToc.next(width > this.showFloatingTocWidth);
+ this.showTopMenu = width >= showTopMenuWidth;
+ this.dockSideNav = width >= dockSideNavWidth;
+ this.showFloatingToc.next(width > showFloatingTocWidth);
- if (this.isSideBySide && !this.isSideNavDoc) {
+ if (this.showTopMenu && !this.isSideNavDoc) {
// If this is a non-sidenav doc and the screen is wide enough so that we can display menu
// items in the top-bar, ensure the sidenav is closed.
- // (This condition can only be met when the resize event changes the value of `isSideBySide`
+ // (This condition can only be met when the resize event changes the value of `showTopMenu`
// from `false` to `true` while on a non-sidenav doc.)
this.sidenav.toggle(false);
}
@@ -338,7 +341,7 @@ export class AppComponent implements OnInit {
}
// May be open or closed when wide; always closed when narrow.
- this.sidenav.toggle(this.isSideBySide && openSideNav);
+ this.sidenav.toggle(this.dockSideNav && openSideNav);
}
// Dynamically change height of table of contents container
diff --git a/aio/src/styles/1-layouts/_top-menu.scss b/aio/src/styles/1-layouts/_top-menu.scss
index 5894ca066c..da915c8b62 100644
--- a/aio/src/styles/1-layouts/_top-menu.scss
+++ b/aio/src/styles/1-layouts/_top-menu.scss
@@ -1,6 +1,6 @@
// VARIABLES
-$hamburgerShownMaxWidth: 991px;
-$hamburgerHiddenMinWidth: $hamburgerShownMaxWidth + 1;
+$showTopMenuWidth: 992px;
+$hideTopMenuWidth: $showTopMenuWidth - 1;
$hamburgerShownMargin: 0 8px 0 0;
$hamburgerHiddenMargin: 0 16px 0 -64px;
@@ -54,7 +54,7 @@ aio-shell.folder-docs mat-toolbar.mat-toolbar,
aio-shell.folder-guide mat-toolbar.mat-toolbar,
aio-shell.folder-start mat-toolbar.mat-toolbar,
aio-shell.folder-tutorial mat-toolbar.mat-toolbar {
- @media (min-width: $hamburgerHiddenMinWidth) {
+ @media (min-width: $showTopMenuWidth) {
.hamburger.mat-button {
// Hamburger shown on non-marketing pages even on large screens.
margin: $hamburgerShownMargin;
@@ -68,7 +68,7 @@ aio-shell.folder-tutorial mat-toolbar.mat-toolbar {
margin: $hamburgerShownMargin;
padding: 0;
- @media (min-width: $hamburgerHiddenMinWidth) {
+ @media (min-width: $showTopMenuWidth) {
// Hamburger hidden by default on large screens.
// (Will be shown per doc.)
margin: $hamburgerHiddenMargin;
@@ -106,7 +106,7 @@ aio-shell.folder-tutorial mat-toolbar.mat-toolbar {
outline-offset: 4px;
}
- @media screen and (max-width: $hamburgerShownMaxWidth) {
+ @media screen and (max-width: $hideTopMenuWidth) {
padding: 4px 0;
}
@@ -120,7 +120,7 @@ aio-shell.folder-tutorial mat-toolbar.mat-toolbar {
top: 12px;
height: 40px;
- @media (max-width: $hamburgerShownMaxWidth) {
+ @media (max-width: $hideTopMenuWidth) {
&:hover {
transform: scale(1.1);
}