Skip to content
This repository was archived by the owner on Dec 18, 2024. It is now read-only.

feat(nav): new sidenav #300

Merged
merged 8 commits into from
Oct 30, 2017
Merged
Show file tree
Hide file tree
Changes from 3 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
49 changes: 31 additions & 18 deletions src/app/pages/component-sidenav/_component-sidenav-theme.scss
Original file line number Diff line number Diff line change
@@ -1,36 +1,49 @@
@import '../../../../node_modules/@angular/material/theming';
@import '../../../styles/constants';

@mixin component-viewer-sidenav-theme($theme) {
$primary: map-get($theme, primary);
$accent: map-get($theme, accent);
$warn: map-get($theme, warn);
$background: map-get($theme, background);
$foreground: map-get($theme, foreground);
$sidenav: '.docs-component-viewer-sidenav';
$is-dark-theme: map-get($theme, is-dark);
$nav-background-opacity: if($is-dark-theme, 0.2, 0.03);

.docs-component-viewer-nav-inner {
Copy link
Member

Choose a reason for hiding this comment

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

Is there a more descriptive name than inner, or a comment you could add to explain what the element is?

background: rgba(0, 0, 0, $nav-background-opacity);

.docs-component-viewer-sidenav {
&::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, .26);
}

// Section divider
h3 {
background: rgba(mat-color($foreground, secondary-text), .32);
color: mat-color($primary, default-contrast);
color: rgba(mat-color($foreground, text), .5);
}

// Sidenav navigation items
li {
border-color: rgba(mat-color($foreground, secondary-text), .06);
color: mat-color($foreground, secondary-text);
hr {
border: none;
border-top: solid 1px rgba(mat-color($foreground, secondary-text), .1)
}

> a {
a {
color: mat-color($foreground, secondary-text);

&.is-selected,
&:hover,
&:focus {
background: mat-color($background, background);
color: mat-color($primary);
}
&.docs-component-viewer-sidenav-item-selected,
&:hover {
color: mat-color($primary);
}
}
}

@media (max-width: $small-breakpoint-width) {
.docs-component-viewer-sidenav {
.docs-component-viewer-nav-inner {
background: none;
}
}

.mat-drawer {
&::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, .26);
}
}
}
Expand Down
20 changes: 20 additions & 0 deletions src/app/pages/component-sidenav/component-nav.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<div class="docs-component-viewer-nav">
<div class="docs-component-viewer-nav-inner">
<nav *ngFor="let category of docItems.getCategories((params | async)?.section); let last = last;">
<h3 (click)="toggleExpand(category.id)">
Copy link
Member

Choose a reason for hiding this comment

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

For a11y, each of these sections needs to act like an expansion panel. This means that the thing you interact with should be a <button> (with the same aria attrs that expansion panel uses). We shouldn't need to use a real heading element here since it's not part of the document content (table of contents).

{{category.name}}
<mat-icon *ngIf="!getExpanded(category.id)">keyboard_arrow_down</mat-icon>
<mat-icon *ngIf="getExpanded(category.id)">keyboard_arrow_up</mat-icon>
</h3>
<ul [@bodyExpansion]="_getExpandedState(category.id)">
<li *ngFor="let component of category.items">
<a [routerLink]="'/' + (params | async)?.section+ '/' + component.id"
routerLinkActive="docs-component-viewer-sidenav-item-selected">
{{component.name}}
</a>
</li>
</ul>
<hr *ngIf="!last" />
</nav>
</div>
</div>
30 changes: 15 additions & 15 deletions src/app/pages/component-sidenav/component-sidenav.html
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
<mat-sidenav-container class="docs-component-viewer-sidenav-container">
<mat-sidenav #sidenav class="docs-component-viewer-sidenav"
*ngIf="isScreenSmall()"
[opened]="!isScreenSmall()"
[mode]="isScreenSmall() ? 'over' : 'side'">
<nav *ngFor="let category of docItems.getCategories((params | async)?.section)">
<h3>{{category.name}}</h3>
<ul>
<li *ngFor="let component of category.items">
<a [routerLink]="'/' + (params | async)?.section+ '/' + component.id"
routerLinkActive="docs-component-viewer-sidenav-item-selected">
{{component.name}}
</a>
</li>
</ul>
</nav>
<app-component-nav
[params]="params">
</app-component-nav>
Copy link
Member

Choose a reason for hiding this comment

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

This looks like it could fit on one line

</mat-sidenav>

<div class="docs-component-sidenav-content">
<component-page-header (toggleSidenav)="sidenav.toggle()"></component-page-header>
<router-outlet></router-outlet>
<app-footer></app-footer>
<div class="docs-component-sidenav-inner-content">
<div class="docs-component-sidenav-body-content">
<app-component-nav
Copy link
Member

Choose a reason for hiding this comment

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

Add a comment explaining the different structure based on screen size?

*ngIf="!isScreenSmall()"
[params]="params">
</app-component-nav>
<router-outlet></router-outlet>
</div>
<app-footer></app-footer>
</div>
</div>
</mat-sidenav-container>
</mat-sidenav-container>
161 changes: 103 additions & 58 deletions src/app/pages/component-sidenav/component-sidenav.scss
Original file line number Diff line number Diff line change
@@ -1,88 +1,133 @@
$sidenav-spacing-unit: 8px;
$sidenav-width: 240px;
@import '../../../styles/constants';

app-component-sidenav {
display: flex;
}
$sidenav-width: 240px;

.docs-component-viewer-sidenav-container {
width: 100%;

.mat-drawer-content {
position: absolute;
right: 0;
left: 0;
}
box-sizing: border-box;
}

.docs-component-viewer-sidenav {
box-shadow: 3px 0 6px rgba(0, 0, 0, .24);
padding-bottom: 72px;
width: $sidenav-width;
bottom: 0;
overflow: auto;
height: 100%;
}

&.mat-sidenav-opened {
box-shadow: 3px 0 6px rgba(0, 0, 0, .24);
}
.docs-component-sidenav-inner-content {
display: flex;
flex-direction: row;

// Section divider
h3 {
border: none;
font-size: 10px;
letter-spacing: 1px;
line-height: $sidenav-spacing-unit * 3;
text-transform: uppercase;
font-weight: 400;
margin: 0;
padding: 0 ($sidenav-spacing-unit * 2);
// The rule will match the element following the router-outlet which will be the routed component.
router-outlet + * {
flex-grow: 1;
}
}

ul {
list-style-type: none;
margin: 0;
padding: 0;
.mat-drawer {
&::-webkit-scrollbar {
height: 4px;
width: 4px;
}
}

// Sidenav navigation item
li {
border-bottom-width: 1px;
border-bottom-style: solid;
margin: 0;
padding: 0;
.docs-component-viewer-nav {
position: sticky;
top: 25px;

.docs-component-viewer-nav-inner {
margin: 25px;
width: $sidenav-width;
max-height: 75vh;
overflow: auto;

// Hide the border on the last item
&:last-child {
border-color: transparent;
&::-webkit-scrollbar {
height: 4px;
width: 4px;
}

> a {
box-sizing: border-box;
display: block;
font-size: 14px;
font-weight: 400;
line-height: ($sidenav-spacing-unit * 6) - 1;
text-decoration: none;
transition: all .3s;
padding: 0 ($sidenav-spacing-unit * 2);
h3 {
padding: 10px 15px;
font-weight: 700;
line-height: 16px;
margin: 0;
font-size: 13px;
cursor: pointer;
position: relative;

&.docs-component-viewer-sidenav-item-selected {
font-weight: 600;
.mat-icon {
position: absolute;
right: 5px;
font-size: 18px;
}
}

hr {
padding: 0;
margin: 0;
}

ul {
list-style-type: none;
margin: -5px 0 5px 0;
padding: 0;
overflow: hidden;
}

li {
font-size: 13px;
line-height: 16px;
margin: 0;
padding: 5px 15px 5px 20px;
}

a {
text-decoration: none;
}
}
}

.docs-component-sidenav-content {
min-height: 100%;
display: flex;
flex-direction: column;
}

// The rule will match the element following the router-outlet which will be the routed component.
router-outlet + * {
flex-grow: 1;
// Add specific rule to prevent default rule conflict
.docs-component-viewer-sidenav-container.mat-drawer-container{
display: block;
overflow: hidden;
position: absolute;
top: 50px;
Copy link
Member

Choose a reason for hiding this comment

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

Comment for 50px?

bottom: 0;
left: 0;
right: 0;
}

.docs-component-sidenav-inner-content {
display: flex;
flex-direction: column;
}

.docs-component-sidenav-body-content {
display: flex;
min-height: calc(100vh - 264px);
Copy link
Contributor

Choose a reason for hiding this comment

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

What is 264? It looks based on $sidenav-width somehow.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

264 is the footer + header nav height.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh yeah lol of course the min-height doesn't have anything to do with sidenav width. Maybe add it as a variable with a comment?

Copy link
Member

Choose a reason for hiding this comment

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

Comment for sure at the least

}

@media (max-width: $small-breakpoint-width) {
// Add specific rule to prevent default rule conflict
.docs-component-viewer-sidenav-container .docs-component-viewer-sidenav {
top: 42px;
Copy link
Member

Choose a reason for hiding this comment

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

Comment for 42px?

}

.mat-sidenav-content {
margin-top: 42px;
}

.docs-component-viewer-nav {
position: relative;
top: 0;

.docs-component-viewer-nav-inner {
box-sizing: border-box;
margin: 0;
max-height: initial;
box-sizing: border-box;
}
}
}
Loading