fix(docs-infra): prevent search-bar from overlapping nav-items by gkalpak · Pull Request #37938 · angular/angular · GitHub
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions aio/src/app/app.component.html
76 changes: 42 additions & 34 deletions aio/src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down Expand Up @@ -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'));
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
});
});

Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -286,64 +294,64 @@ 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'];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This describe block could be:

describe('when changing from narrow to wide view', () => {

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);
});
});

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'];

Expand All @@ -352,7 +360,7 @@ describe('AppComponent', () => {
navigateTo(doc);
expect(sidenav.opened).toBe(true);

resizeTo(sideBySideBreakPoint - 1);
resizeTo(dockSideNavWidth - 1);
expect(sidenav.opened).toBe(false);
});
});
Expand All @@ -362,7 +370,7 @@ describe('AppComponent', () => {
navigateTo(doc);
expect(sidenav.opened).toBe(false);

resizeTo(sideBySideBreakPoint - 1);
resizeTo(dockSideNavWidth - 1);
expect(sidenav.opened).toBe(false);
});
});
Expand All @@ -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;
}
Expand Down
23 changes: 13 additions & 10 deletions aio/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
import { first, map } from 'rxjs/operators';

const sideNavView = 'SideNav';
export const showTopMenuWidth = 1048;
export const dockSideNavWidth = 992;
export const showFloatingTocWidth = 800;

@Component({
selector: 'aio-shell',
Expand Down Expand Up @@ -57,27 +60,26 @@ 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;

versionInfo: VersionInfo;

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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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
Expand Down
13 changes: 8 additions & 5 deletions aio/src/styles/1-layouts/_top-menu.scss