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', () => {
|
||||
|
||||
it('should display a guide page (guide/pipes)', () => {
|
||||
|
@ -274,22 +292,6 @@ describe('AppComponent', () => {
|
|||
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', () => {
|
||||
const titleService = TestBed.get(Title);
|
||||
spyOn(titleService, 'setTitle');
|
||||
|
|
|
@ -22,13 +22,33 @@ export class AppComponent implements OnInit {
|
|||
currentNode: CurrentNode;
|
||||
currentPath: string;
|
||||
dtOn = false;
|
||||
|
||||
/**
|
||||
* An HTML friendly identifier for the currently displayed page.
|
||||
* This is computed from the `currentDocument.id` by replacing `/` with `-`
|
||||
*/
|
||||
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;
|
||||
footerNodes: NavigationNode[];
|
||||
|
||||
@HostBinding('class.marketing')
|
||||
isMarketing = false;
|
||||
|
||||
isStarting = true;
|
||||
isSideBySide = false;
|
||||
private isSideNavDoc = false;
|
||||
|
@ -79,6 +99,8 @@ export class AppComponent implements OnInit {
|
|||
this.documentService.currentDocument.subscribe(doc => {
|
||||
this.currentDocument = doc;
|
||||
this.setPageId(doc.id);
|
||||
this.setFolderId(doc.id);
|
||||
this.updateHostClasses();
|
||||
});
|
||||
|
||||
this.locationService.currentPath.subscribe(path => {
|
||||
|
@ -93,12 +115,12 @@ export class AppComponent implements OnInit {
|
|||
|
||||
this.navigationService.currentNode.subscribe(currentNode => {
|
||||
this.currentNode = currentNode;
|
||||
this.updateHostClasses();
|
||||
|
||||
// Toggle the sidenav if side-by-side and the kind of view changed
|
||||
if (this.previousNavView === currentNode.view) { return; }
|
||||
this.previousNavView = currentNode.view;
|
||||
this.isSideNavDoc = currentNode.view === sideNavView;
|
||||
this.isMarketing = !this.isSideNavDoc;
|
||||
this.sideNavToggle(this.isSideNavDoc && this.isSideBySide);
|
||||
});
|
||||
|
||||
|
@ -174,4 +196,17 @@ export class AppComponent implements OnInit {
|
|||
// Special case the home page
|
||||
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