feat(aio): add helper CSS classes to the `aio-shell` for fine grained styling
Alternative to #16564 Closes #16549
This commit is contained in:
parent
9da63408b0
commit
309ada5df5
|
@ -254,6 +254,24 @@ describe('AppComponent', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('hostClasses', () => {
|
||||||
|
it('should set the css classes of the host container based on the current doc and navigation view', () => {
|
||||||
|
const host = fixture.debugElement;
|
||||||
|
|
||||||
|
locationService.go('guide/pipes');
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(host.properties['className']).toEqual('page-guide-pipes folder-guide view-SideNav');
|
||||||
|
|
||||||
|
locationService.go('features');
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(host.properties['className']).toEqual('page-features folder-features view-TopBar');
|
||||||
|
|
||||||
|
locationService.go('');
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(host.properties['className']).toEqual('page-home folder-home view-');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('currentDocument', () => {
|
describe('currentDocument', () => {
|
||||||
|
|
||||||
it('should display a guide page (guide/pipes)', () => {
|
it('should display a guide page (guide/pipes)', () => {
|
||||||
|
@ -274,22 +292,6 @@ describe('AppComponent', () => {
|
||||||
expect(docViewer.innerText).toMatch(/Features/i);
|
expect(docViewer.innerText).toMatch(/Features/i);
|
||||||
});
|
});
|
||||||
|
|
||||||
const marketingClassName = 'marketing';
|
|
||||||
|
|
||||||
it('should not have marketing CSS class on host element for a guide page (guide/pipes)', () => {
|
|
||||||
locationService.go('guide/pipes');
|
|
||||||
fixture.detectChanges();
|
|
||||||
const classes: string[] = fixture.nativeElement.className;
|
|
||||||
expect(classes).not.toContain(marketingClassName);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have marketing CSS class on host element for a marketing page', () => {
|
|
||||||
locationService.go('features');
|
|
||||||
fixture.detectChanges();
|
|
||||||
const classes: string[] = fixture.nativeElement.className;
|
|
||||||
expect(classes).toContain(marketingClassName);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update the document title', () => {
|
it('should update the document title', () => {
|
||||||
const titleService = TestBed.get(Title);
|
const titleService = TestBed.get(Title);
|
||||||
spyOn(titleService, 'setTitle');
|
spyOn(titleService, 'setTitle');
|
||||||
|
|
|
@ -22,13 +22,33 @@ export class AppComponent implements OnInit {
|
||||||
currentNode: CurrentNode;
|
currentNode: CurrentNode;
|
||||||
currentPath: string;
|
currentPath: string;
|
||||||
dtOn = false;
|
dtOn = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An HTML friendly identifier for the currently displayed page.
|
||||||
|
* This is computed from the `currentDocument.id` by replacing `/` with `-`
|
||||||
|
*/
|
||||||
pageId: string;
|
pageId: string;
|
||||||
|
/**
|
||||||
|
* An HTML friendly identifer for the "folder" of the currently displayed page.
|
||||||
|
* This is computed by taking everything up to the first `/` in the `currentDocument.id`
|
||||||
|
*/
|
||||||
|
folderId: string;
|
||||||
|
/**
|
||||||
|
* These CSS classes are computed from the current state of the application
|
||||||
|
* (e.g. what document is being viewed) to allow for fine grain control over
|
||||||
|
* the styling of individual pages.
|
||||||
|
* You will get three classes:
|
||||||
|
*
|
||||||
|
* * `page-...`: computed from the current document id (e.g. news, guide-security, tutorial-toh-pt2)
|
||||||
|
* * `folder-...`: computed from the top level folder for an id (e.g. guide, tutorial, etc)
|
||||||
|
* * `view-...`: computef from the navigation view (e.g. SideNav, TopBar, etc)
|
||||||
|
*/
|
||||||
|
@HostBinding('class')
|
||||||
|
hostClasses = '';
|
||||||
|
|
||||||
currentDocument: DocumentContents;
|
currentDocument: DocumentContents;
|
||||||
footerNodes: NavigationNode[];
|
footerNodes: NavigationNode[];
|
||||||
|
|
||||||
@HostBinding('class.marketing')
|
|
||||||
isMarketing = false;
|
|
||||||
|
|
||||||
isStarting = true;
|
isStarting = true;
|
||||||
isSideBySide = false;
|
isSideBySide = false;
|
||||||
private isSideNavDoc = false;
|
private isSideNavDoc = false;
|
||||||
|
@ -79,6 +99,8 @@ export class AppComponent implements OnInit {
|
||||||
this.documentService.currentDocument.subscribe(doc => {
|
this.documentService.currentDocument.subscribe(doc => {
|
||||||
this.currentDocument = doc;
|
this.currentDocument = doc;
|
||||||
this.setPageId(doc.id);
|
this.setPageId(doc.id);
|
||||||
|
this.setFolderId(doc.id);
|
||||||
|
this.updateHostClasses();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.locationService.currentPath.subscribe(path => {
|
this.locationService.currentPath.subscribe(path => {
|
||||||
|
@ -93,12 +115,12 @@ export class AppComponent implements OnInit {
|
||||||
|
|
||||||
this.navigationService.currentNode.subscribe(currentNode => {
|
this.navigationService.currentNode.subscribe(currentNode => {
|
||||||
this.currentNode = currentNode;
|
this.currentNode = currentNode;
|
||||||
|
this.updateHostClasses();
|
||||||
|
|
||||||
// Toggle the sidenav if side-by-side and the kind of view changed
|
// Toggle the sidenav if side-by-side and the kind of view changed
|
||||||
if (this.previousNavView === currentNode.view) { return; }
|
if (this.previousNavView === currentNode.view) { return; }
|
||||||
this.previousNavView = currentNode.view;
|
this.previousNavView = currentNode.view;
|
||||||
this.isSideNavDoc = currentNode.view === sideNavView;
|
this.isSideNavDoc = currentNode.view === sideNavView;
|
||||||
this.isMarketing = !this.isSideNavDoc;
|
|
||||||
this.sideNavToggle(this.isSideNavDoc && this.isSideBySide);
|
this.sideNavToggle(this.isSideNavDoc && this.isSideBySide);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -174,4 +196,17 @@ export class AppComponent implements OnInit {
|
||||||
// Special case the home page
|
// Special case the home page
|
||||||
this.pageId = (id === 'index') ? 'home' : id.replace('/', '-');
|
this.pageId = (id === 'index') ? 'home' : id.replace('/', '-');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setFolderId(id: string) {
|
||||||
|
// Special case the home page
|
||||||
|
this.folderId = (id === 'index') ? 'home' : id.split('/', 1)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
updateHostClasses() {
|
||||||
|
const pageClass = `page-${this.pageId}`;
|
||||||
|
const folderClass = `folder-${this.folderId}`;
|
||||||
|
const viewClass = `view-${this.currentNode && this.currentNode.view}`;
|
||||||
|
|
||||||
|
this.hostClasses = `${pageClass} ${folderClass} ${viewClass}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue