fix(aio): expand the main content width when there is no ToC

Previously, the main content would always leave a 18% margin on the right to be
occupied by the ToC (even if there was no ToC).
This commit lets the main content expand to the right to occupy all the
available space when there is no ToC.

Fixes #17205
Fixes #17270
This commit is contained in:
Georgios Kalpakas 2017-06-07 16:51:21 +03:00 committed by Pete Bacon Darwin
parent 8524187869
commit e894f5c399
4 changed files with 113 additions and 30 deletions

View File

@ -15,7 +15,7 @@
</md-toolbar>
<aio-search-results #searchResults *ngIf="showSearchResults" (resultSelected)="hideSearchResults()"></aio-search-results>
<md-sidenav-container class="sidenav-container" [class.starting]="isStarting" role="main">
<md-sidenav-container class="sidenav-container" [class.starting]="isStarting" [class.has-floating-toc]="hasFloatingToc" role="main">
<md-sidenav [ngClass]="{'collapsed': !isSideBySide }" #sidenav class="sidenav" [opened]="isOpened" [mode]="mode" (open)="updateHostClasses()" (close)="updateHostClasses()">
<aio-nav-menu *ngIf="!isSideBySide" [nodes]="topMenuNarrowNodes" [currentNode]="currentNodes?.TopBarNarrow"></aio-nav-menu>
@ -33,7 +33,7 @@
</md-sidenav-container>
<div *ngIf="showFloatingToc" class="toc-container" [style.max-height.px]="tocMaxHeight" (mousewheel)="restrainScrolling($event)">
<div *ngIf="hasFloatingToc" class="toc-container" [style.max-height.px]="tocMaxHeight" (mousewheel)="restrainScrolling($event)">
<aio-toc></aio-toc>
</div>

View File

@ -3,7 +3,7 @@ import { async, inject, ComponentFixture, TestBed, fakeAsync, tick } from '@angu
import { Title } from '@angular/platform-browser';
import { APP_BASE_HREF } from '@angular/common';
import { Http } from '@angular/http';
import { MdProgressBar } from '@angular/material';
import { MdProgressBar, MdSidenav } from '@angular/material';
import { By } from '@angular/platform-browser';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@ -27,7 +27,7 @@ import { SearchService } from 'app/search/search.service';
import { SelectComponent, Option } from 'app/shared/select/select.component';
import { SwUpdateNotificationsService } from 'app/sw-updates/sw-update-notifications.service';
import { TocComponent } from 'app/embedded/toc/toc.component';
import { MdSidenav } from '@angular/material';
import { TocItem, TocService } from 'app/shared/toc.service';
const sideBySideBreakPoint = 992;
const hideToCBreakPoint = 800;
@ -40,6 +40,7 @@ describe('AppComponent', () => {
let hamburger: HTMLButtonElement;
let locationService: MockLocationService;
let sidenav: HTMLElement;
let tocService: TocService;
const initializeTest = () => {
fixture = TestBed.createComponent(AppComponent);
@ -48,10 +49,12 @@ describe('AppComponent', () => {
fixture.detectChanges();
component.onResize(sideBySideBreakPoint + 1); // wide by default
docViewer = fixture.debugElement.query(By.css('aio-doc-viewer')).nativeElement;
hamburger = fixture.debugElement.query(By.css('.hamburger')).nativeElement;
locationService = fixture.debugElement.injector.get(LocationService) as any;
sidenav = fixture.debugElement.query(By.css('md-sidenav')).nativeElement;
const de = fixture.debugElement;
docViewer = de.query(By.css('aio-doc-viewer')).nativeElement;
hamburger = de.query(By.css('.hamburger')).nativeElement;
locationService = de.injector.get(LocationService) as any as MockLocationService;
sidenav = de.query(By.css('md-sidenav')).nativeElement;
tocService = de.injector.get(TocService);
};
describe('with proper DocViewer', () => {
@ -72,19 +75,74 @@ describe('AppComponent', () => {
});
});
describe('onResize', () => {
it('should update `isSideBySide` accordingly', () => {
component.onResize(sideBySideBreakPoint + 1);
expect(component.isSideBySide).toBe(true);
component.onResize(sideBySideBreakPoint - 1);
expect(component.isSideBySide).toBe(false);
describe('hasFloatingToc', () => {
it('should initially be true', () => {
const fixture2 = TestBed.createComponent(AppComponent);
const component2 = fixture2.componentInstance;
expect(component2.hasFloatingToc).toBe(true);
});
it('should update `showFloatingToc` accordingly', () => {
component.onResize(hideToCBreakPoint + 1);
expect(component.showFloatingToc).toBe(true);
it('should be false on narrow screens', () => {
component.onResize(hideToCBreakPoint - 1);
expect(component.showFloatingToc).toBe(false);
tocService.tocList.next([{}, {}, {}] as TocItem[]);
expect(component.hasFloatingToc).toBe(false);
tocService.tocList.next([]);
expect(component.hasFloatingToc).toBe(false);
tocService.tocList.next([{}, {}, {}] as TocItem[]);
expect(component.hasFloatingToc).toBe(false);
});
it('should be true on wide screens unless the toc is empty', () => {
component.onResize(hideToCBreakPoint + 1);
tocService.tocList.next([{}, {}, {}] as TocItem[]);
expect(component.hasFloatingToc).toBe(true);
tocService.tocList.next([]);
expect(component.hasFloatingToc).toBe(false);
tocService.tocList.next([{}, {}, {}] as TocItem[]);
expect(component.hasFloatingToc).toBe(true);
});
it('should be false when toc is empty', () => {
tocService.tocList.next([]);
component.onResize(hideToCBreakPoint + 1);
expect(component.hasFloatingToc).toBe(false);
component.onResize(hideToCBreakPoint - 1);
expect(component.hasFloatingToc).toBe(false);
component.onResize(hideToCBreakPoint + 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);
expect(component.hasFloatingToc).toBe(true);
component.onResize(hideToCBreakPoint - 1);
expect(component.hasFloatingToc).toBe(false);
component.onResize(hideToCBreakPoint + 1);
expect(component.hasFloatingToc).toBe(true);
});
});
describe('isSideBySide', () => {
it('should be updated on resize', () => {
component.onResize(sideBySideBreakPoint - 1);
expect(component.isSideBySide).toBe(false);
component.onResize(sideBySideBreakPoint + 1);
expect(component.isSideBySide).toBe(true);
});
});
@ -523,14 +581,31 @@ describe('AppComponent', () => {
let tocDebugElement: DebugElement;
let tocContainer: DebugElement;
beforeEach(() => {
const setHasFloatingToc = hasFloatingToc => {
component.hasFloatingToc = hasFloatingToc;
fixture.detectChanges();
tocDebugElement = fixture.debugElement.query(By.directive(TocComponent));
tocContainer = tocDebugElement.parent;
tocContainer = tocDebugElement && tocDebugElement.parent;
};
beforeEach(() => setHasFloatingToc(true));
it('should show/hide `<aio-toc>` based on `hasFloatingToc`', () => {
expect(tocDebugElement).toBeTruthy();
expect(tocContainer).toBeTruthy();
setHasFloatingToc(false);
expect(tocDebugElement).toBeFalsy();
expect(tocContainer).toBeFalsy();
setHasFloatingToc(true);
expect(tocDebugElement).toBeTruthy();
expect(tocContainer).toBeTruthy();
});
it('should have a non-embedded `<aio-toc>` element', () => {
expect(tocDebugElement).toBeDefined();
expect(tocDebugElement.classes['embedded']).toBeFalsy();
});

View File

@ -12,7 +12,9 @@ import { SearchResultsComponent } from 'app/search/search-results/search-results
import { SearchBoxComponent } from 'app/search/search-box/search-box.component';
import { SearchService } from 'app/search/search.service';
import { SwUpdateNotificationsService } from 'app/sw-updates/sw-update-notifications.service';
import { TocService } from 'app/shared/toc.service';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { combineLatest } from 'rxjs/observable/combineLatest';
const sideNavView = 'SideNav';
@ -65,8 +67,9 @@ export class AppComponent implements OnInit {
topMenuNodes: NavigationNode[];
topMenuNarrowNodes: NavigationNode[];
showFloatingToc = false;
showFloatingTocWidth = 800;
hasFloatingToc = true;
private showFloatingToc = new BehaviorSubject(false);
private showFloatingTocWidth = 800;
tocMaxHeight: string;
private tocMaxHeightOffset = 0;
@ -103,7 +106,8 @@ export class AppComponent implements OnInit {
private navigationService: NavigationService,
private scrollService: ScrollService,
private searchService: SearchService,
private swUpdateNotifications: SwUpdateNotificationsService
private swUpdateNotifications: SwUpdateNotificationsService,
private tocService: TocService
) { }
ngOnInit() {
@ -174,6 +178,10 @@ export class AppComponent implements OnInit {
this.navigationService.versionInfo.subscribe( vi => this.versionInfo = vi );
this.swUpdateNotifications.enable();
const hasNonEmptyToc = this.tocService.tocList.map(tocList => tocList.length > 0);
combineLatest(hasNonEmptyToc, this.showFloatingToc)
.subscribe(([hasToc, showFloatingToc]) => this.hasFloatingToc = hasToc && showFloatingToc);
}
// Scroll to the anchor in the hash fragment or top of doc.
@ -207,7 +215,7 @@ export class AppComponent implements OnInit {
@HostListener('window:resize', ['$event.target.innerWidth'])
onResize(width) {
this.isSideBySide = width > this.sideBySideWidth;
this.showFloatingToc = width > this.showFloatingTocWidth;
this.showFloatingToc.next(width > this.showFloatingTocWidth);
}
@HostListener('click', ['$event.target', '$event.button', '$event.ctrlKey', '$event.metaKey', '$event.altKey'])

View File

@ -42,12 +42,12 @@ md-sidenav.mat-sidenav.sidenav {
md-sidenav-container.sidenav-container {
min-height: 100%;
height: auto !important;
max-width: 82%;
max-width: 100%;
margin: 0;
transform: none;
@media (max-width: 800px) {
max-width: 100%;
&.has-floating-toc {
max-width: 82%;
}
}