diff --git a/aio/src/app/embedded/embedded.module.ts b/aio/src/app/embedded/embedded.module.ts index 5839a2d0ef..aa502d8445 100644 --- a/aio/src/app/embedded/embedded.module.ts +++ b/aio/src/app/embedded/embedded.module.ts @@ -9,7 +9,7 @@ import { PrettyPrinter } from './code/pretty-printer.service'; // It is not enough just to import them inside the AppModule // Reusable components (used inside embedded components) -import { MdTabsModule } from '@angular/material'; +import { MdIconModule, MdTabsModule } from '@angular/material'; import { CodeComponent } from './code/code.component'; // Embedded Components @@ -38,7 +38,11 @@ export class EmbeddedComponents { } @NgModule({ - imports: [ CommonModule, MdTabsModule ], + imports: [ + CommonModule, + MdIconModule, + MdTabsModule + ], declarations: [ embeddedComponents, CodeComponent, diff --git a/aio/src/app/embedded/toc/toc.component.html b/aio/src/app/embedded/toc/toc.component.html index 079952d615..d30070d473 100644 --- a/aio/src/app/embedded/toc/toc.component.html +++ b/aio/src/app/embedded/toc/toc.component.html @@ -1,11 +1,17 @@ -
-
Contents
-
-

Table of Contents

-
+
+ + +
Contents
+ +
diff --git a/aio/src/app/embedded/toc/toc.component.spec.ts b/aio/src/app/embedded/toc/toc.component.spec.ts index 227202e5b6..370394aabd 100644 --- a/aio/src/app/embedded/toc/toc.component.spec.ts +++ b/aio/src/app/embedded/toc/toc.component.spec.ts @@ -1,4 +1,4 @@ -import { Component, DebugElement } from '@angular/core'; +import { Component, CUSTOM_ELEMENTS_SCHEMA, DebugElement } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { By, DOCUMENT } from '@angular/platform-browser'; import { BehaviorSubject } from 'rxjs/BehaviorSubject'; @@ -15,7 +15,8 @@ describe('TocComponent', () => { let page: { listItems: DebugElement[]; tocHeading: DebugElement; - tocHeadingButton: DebugElement; + tocHeadingButtonEmbedded: DebugElement; + tocHeadingButtonSide: DebugElement; tocMoreButton: DebugElement; }; @@ -23,7 +24,8 @@ describe('TocComponent', () => { return { listItems: tocComponentDe.queryAll(By.css('ul.toc-list>li')), tocHeading: tocComponentDe.query(By.css('.toc-heading')), - tocHeadingButton: tocComponentDe.query(By.css('.toc-heading button')), + tocHeadingButtonEmbedded: tocComponentDe.query(By.css('button.toc-heading.embedded')), + tocHeadingButtonSide: tocComponentDe.query(By.css('button.toc-heading:not(.embedded)')), tocMoreButton: tocComponentDe.query(By.css('button.toc-more-items')), }; } @@ -34,7 +36,8 @@ describe('TocComponent', () => { providers: [ { provide: ScrollService, useClass: TestScrollService }, { provide: TocService, useClass: TestTocService } - ] + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA] }); }); @@ -106,18 +109,18 @@ describe('TocComponent', () => { }); it('should not display expando buttons', () => { - expect(page.tocHeadingButton).toBeFalsy('top expand/collapse button'); + expect(page.tocHeadingButtonEmbedded).toBeFalsy('top expand/collapse button'); expect(page.tocMoreButton).toBeFalsy('bottom more button'); }); }); describe('when many TocItems', () => { - let scrollSpy: jasmine.Spy; + let scrollToTopSpy: jasmine.Spy; beforeEach(() => { fixture.detectChanges(); page = setPage(); - scrollSpy = TestBed.get(ScrollService).scrollToTop; + scrollToTopSpy = TestBed.get(ScrollService).scrollToTop; }); it('should have more than 4 displayed items', () => { @@ -128,16 +131,16 @@ describe('TocComponent', () => { expect(page.listItems.length).toEqual(tocList.length); }); - it('should be in "closed" (not expanded) state at the start', () => { - expect(tocComponent.isClosed).toBeTruthy(); + it('should be in "collapsed" (not expanded) state at the start', () => { + expect(tocComponent.isCollapsed).toBeTruthy(); }); - it('should have "closed" class at the start', () => { - expect(tocComponentDe.children[0].classes.closed).toEqual(true); + it('should have "collapsed" class at the start', () => { + expect(tocComponentDe.children[0].classes.collapsed).toEqual(true); }); it('should display expando buttons', () => { - expect(page.tocHeadingButton).toBeTruthy('top expand/collapse button'); + expect(page.tocHeadingButtonEmbedded).toBeTruthy('top expand/collapse button'); expect(page.tocMoreButton).toBeTruthy('bottom more button'); }); @@ -145,7 +148,7 @@ describe('TocComponent', () => { expect(tocComponent.hasSecondary).toEqual(true, 'hasSecondary flag'); }); - // CSS should hide items with the secondary class when closed + // CSS should hide items with the secondary class when collapsed it('should have secondary item with a secondary class', () => { const aSecondary = page.listItems.find(item => item.classes.secondary); expect(aSecondary).toBeTruthy('should find a secondary'); @@ -155,32 +158,32 @@ describe('TocComponent', () => { describe('after click tocHeading button', () => { beforeEach(() => { - page.tocHeadingButton.nativeElement.click(); + page.tocHeadingButtonEmbedded.nativeElement.click(); fixture.detectChanges(); }); - it('should not be "closed"', () => { - expect(tocComponent.isClosed).toEqual(false); + it('should not be "collapsed"', () => { + expect(tocComponent.isCollapsed).toEqual(false); }); - it('should not have "closed" class', () => { - expect(tocComponentDe.children[0].classes.closed).toBeFalsy(); + it('should not have "collapsed" class', () => { + expect(tocComponentDe.children[0].classes.collapsed).toBeFalsy(); }); it('should not scroll', () => { - expect(scrollSpy).not.toHaveBeenCalled(); + expect(scrollToTopSpy).not.toHaveBeenCalled(); }); - it('should be "closed" after clicking again', () => { - page.tocHeadingButton.nativeElement.click(); + it('should be "collapsed" after clicking again', () => { + page.tocHeadingButtonEmbedded.nativeElement.click(); fixture.detectChanges(); - expect(tocComponent.isClosed).toEqual(true); + expect(tocComponent.isCollapsed).toEqual(true); }); it('should not scroll after clicking again', () => { - page.tocHeadingButton.nativeElement.click(); + page.tocHeadingButtonEmbedded.nativeElement.click(); fixture.detectChanges(); - expect(scrollSpy).not.toHaveBeenCalled(); + expect(scrollToTopSpy).not.toHaveBeenCalled(); }); }); @@ -191,34 +194,34 @@ describe('TocComponent', () => { fixture.detectChanges(); }); - it('should not be "closed"', () => { - expect(tocComponent.isClosed).toEqual(false); + it('should not be "collapsed"', () => { + expect(tocComponent.isCollapsed).toEqual(false); }); - it('should not have "closed" class', () => { - expect(tocComponentDe.children[0].classes.closed).toBeFalsy(); + it('should not have "collapsed" class', () => { + expect(tocComponentDe.children[0].classes.collapsed).toBeFalsy(); }); it('should not scroll', () => { - expect(scrollSpy).not.toHaveBeenCalled(); + expect(scrollToTopSpy).not.toHaveBeenCalled(); }); - it('should be "closed" after clicking again', () => { + it('should be "collapsed" after clicking again', () => { page.tocMoreButton.nativeElement.click(); fixture.detectChanges(); - expect(tocComponent.isClosed).toEqual(true); + expect(tocComponent.isCollapsed).toEqual(true); }); - it('should be "closed" after clicking tocHeadingButton', () => { + it('should be "collapsed" after clicking tocHeadingButton', () => { page.tocMoreButton.nativeElement.click(); fixture.detectChanges(); - expect(tocComponent.isClosed).toEqual(true); + expect(tocComponent.isCollapsed).toEqual(true); }); it('should scroll after clicking again', () => { page.tocMoreButton.nativeElement.click(); fixture.detectChanges(); - expect(scrollSpy).toHaveBeenCalled(); + expect(scrollToTopSpy).toHaveBeenCalled(); }); }); }); @@ -226,9 +229,12 @@ describe('TocComponent', () => { describe('when in side panel (not embedded))', () => { let fixture: ComponentFixture; + let scrollToTopSpy: jasmine.Spy; beforeEach(() => { fixture = TestBed.createComponent(HostNotEmbeddedTocComponent); + + scrollToTopSpy = TestBed.get(ScrollService).scrollToTop; tocComponentDe = fixture.debugElement.children[0]; tocComponent = tocComponentDe.componentInstance; tocService = TestBed.get(TocService); @@ -255,9 +261,19 @@ describe('TocComponent', () => { }); it('should not display expando buttons', () => { - expect(page.tocHeadingButton).toBeFalsy('top expand/collapse button'); + expect(page.tocHeadingButtonEmbedded).toBeFalsy('top expand/collapse button'); expect(page.tocMoreButton).toBeFalsy('bottom more button'); }); + + it('should display "Contents" button', () => { + expect(page.tocHeadingButtonSide).toBeTruthy(); + }); + + it('should scroll to top when "Contents" button clicked', () => { + page.tocHeadingButtonSide.nativeElement.click(); + fixture.detectChanges(); + expect(scrollToTopSpy).toHaveBeenCalled(); + }); }); }); diff --git a/aio/src/app/embedded/toc/toc.component.ts b/aio/src/app/embedded/toc/toc.component.ts index 700facc4b7..6e261e9aa4 100644 --- a/aio/src/app/embedded/toc/toc.component.ts +++ b/aio/src/app/embedded/toc/toc.component.ts @@ -15,7 +15,7 @@ export class TocComponent implements OnInit, OnDestroy { hasSecondary = false; hasToc = false; hostElement: HTMLElement; - isClosed = true; + isCollapsed = true; isEmbedded = false; private onDestroy = new Subject(); private primaryMax = 4; @@ -52,7 +52,11 @@ export class TocComponent implements OnInit, OnDestroy { } toggle(canScroll = true) { - this.isClosed = !this.isClosed; - if (canScroll && this.isClosed) { this.scrollService.scrollToTop(); } + this.isCollapsed = !this.isCollapsed; + if (canScroll && this.isCollapsed) { this.toTop(); } + } + + toTop() { + this.scrollService.scrollToTop(); } } diff --git a/aio/src/app/layout/nav-item/nav-item.component.html b/aio/src/app/layout/nav-item/nav-item.component.html index d1be279aff..e319889f9b 100644 --- a/aio/src/app/layout/nav-item/nav-item.component.html +++ b/aio/src/app/layout/nav-item/nav-item.component.html @@ -13,7 +13,8 @@ diff --git a/aio/src/styles/2-modules/_toc.scss b/aio/src/styles/2-modules/_toc.scss index 9d49fcf5f5..ecbafd8d13 100644 --- a/aio/src/styles/2-modules/_toc.scss +++ b/aio/src/styles/2-modules/_toc.scss @@ -50,51 +50,70 @@ aio-toc > div { } } - button.toc-show-all, + button.toc-heading, button.toc-more-items { + cursor: pointer; display: inline-block; background: 0; background-color: transparent; border: none; box-shadow: none; - color: $mediumgray; padding: 0; + &:focus.embedded { + outline: none; + background: $lightgray; + } + } + + button.toc-heading, + div.toc-heading { + font-size: 115%; + } + + button.toc-heading { + md-icon.rotating-icon { + height: 18px; + width: 18px; + position: relative; + left: -4px; + top: 5px; + } + + &:hover:not(.embedded) { + color: $accentblue; + } + } + + + button.toc-more-items { + color: $mediumgray; + top: 10px; + position: relative; + &:hover { color: $accentblue; } - &:focus { - outline: none; - } - } - - button.toc-show-all { - min-width: 34px; - position: absolute; - top: 0; - } - - button.toc-show-all::after { - content: 'expand_less'; - } - - button.toc-show-all.closed::after { - content: 'expand_more'; - } - - button.toc-more-items { - top: 10px; - position: relative; } button.toc-more-items::after { content: 'expand_less'; } - button.toc-more-items.closed::after { + button.toc-more-items.collapsed::after { content: 'more_horiz'; } + + .mat-icon.collapsed { + @include rotate(0deg); + } + + .mat-icon:not(.collapsed) { + @include rotate(90deg); + // margin: 4px; + } + ul.toc-list { list-style-type: none; margin: 0; @@ -131,6 +150,6 @@ aio-toc > div { } } -aio-toc.embedded > div.closed li.secondary { +aio-toc.embedded > div.collapsed li.secondary { display: none; }