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

Commit e9165c1

Browse files
committed
feat(nav): new sidenav UX (#300)
1 parent 1981417 commit e9165c1

File tree

9 files changed

+279
-106
lines changed

9 files changed

+279
-106
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"angular-cli": {},
66
"scripts": {
77
"start": "npm run build-themes && ng serve --aot --sourcemaps=false",
8+
"start-jit": "npm run build-themes && ng serve --sourcemaps=false",
89
"lint": "tslint \"src/**/*.ts\"",
910
"test": "ng test",
1011
"pree2e": "webdriver-manager update",

src/app/pages/component-sidenav/_component-sidenav-theme.scss

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,49 @@
11
@import '../../../../node_modules/@angular/material/theming';
2+
@import '../../../styles/constants';
23

34
@mixin component-viewer-sidenav-theme($theme) {
45
$primary: map-get($theme, primary);
5-
$accent: map-get($theme, accent);
6-
$warn: map-get($theme, warn);
76
$background: map-get($theme, background);
87
$foreground: map-get($theme, foreground);
9-
$sidenav: '.docs-component-viewer-sidenav';
8+
$is-dark-theme: map-get($theme, is-dark);
9+
$nav-background-opacity: if($is-dark-theme, 0.2, 0.03);
1010

11+
.docs-component-viewer-nav-content {
12+
background: rgba(0, 0, 0, $nav-background-opacity);
1113

12-
.docs-component-viewer-sidenav {
14+
&::-webkit-scrollbar-thumb {
15+
background: rgba(0, 0, 0, .26);
16+
}
1317

14-
// Section divider
15-
h3 {
16-
background: rgba(mat-color($foreground, secondary-text), .32);
17-
color: mat-color($primary, default-contrast);
18+
button {
19+
color: rgba(mat-color($foreground, text), .5);
1820
}
1921

20-
// Sidenav navigation items
21-
li {
22-
border-color: rgba(mat-color($foreground, secondary-text), .06);
23-
color: mat-color($foreground, secondary-text);
22+
hr {
23+
border: none;
24+
border-top: solid 1px rgba(mat-color($foreground, secondary-text), .1)
25+
}
2426

25-
> a {
27+
a {
2628
color: mat-color($foreground, secondary-text);
2729

28-
&.is-selected,
29-
&:hover,
30-
&:focus {
31-
background: mat-color($background, background);
32-
color: mat-color($primary);
33-
}
30+
&.docs-component-viewer-sidenav-item-selected,
31+
&:hover {
32+
color: mat-color($primary);
33+
}
34+
}
35+
}
36+
37+
@media (max-width: $small-breakpoint-width) {
38+
.docs-component-viewer-sidenav {
39+
.docs-component-viewer-nav-content {
40+
background: none;
41+
}
42+
}
43+
44+
.mat-drawer {
45+
&::-webkit-scrollbar-thumb {
46+
background: rgba(0, 0, 0, .26);
3447
}
3548
}
3649
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<div class="docs-component-viewer-nav">
2+
<div class="docs-component-viewer-nav-content">
3+
<nav *ngFor="let category of docItems.getCategories((params | async)?.section); let last = last;">
4+
<button (click)="toggleExpand(category.id)"
5+
[attr.aria-label]="category.name + ', section toggle'"
6+
[attr.aria-controls]="'panel-' + category.id"
7+
[attr.aria-expanded]="getExpanded(category.id)">
8+
{{category.name}}
9+
<mat-icon *ngIf="!getExpanded(category.id)">keyboard_arrow_down</mat-icon>
10+
<mat-icon *ngIf="getExpanded(category.id)">keyboard_arrow_up</mat-icon>
11+
</button>
12+
<ul [@bodyExpansion]="_getExpandedState(category.id)" id="panel-{{category.id}}">
13+
<li *ngFor="let component of category.items">
14+
<a [routerLink]="'/' + (params | async)?.section+ '/' + component.id"
15+
routerLinkActive="docs-component-viewer-sidenav-item-selected">
16+
{{component.name}}
17+
</a>
18+
</li>
19+
</ul>
20+
<hr *ngIf="!last" />
21+
</nav>
22+
</div>
23+
</div>
Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
<mat-sidenav-container class="docs-component-viewer-sidenav-container">
2+
<!-- If on small screen, menu resides in drawer -->
23
<mat-sidenav #sidenav class="docs-component-viewer-sidenav"
4+
*ngIf="isScreenSmall()"
35
[opened]="!isScreenSmall()"
46
[mode]="isScreenSmall() ? 'over' : 'side'">
5-
<nav *ngFor="let category of docItems.getCategories((params | async)?.section)">
6-
<h3>{{category.name}}</h3>
7-
<ul>
8-
<li *ngFor="let component of category.items">
9-
<a [routerLink]="'/' + (params | async)?.section+ '/' + component.id"
10-
routerLinkActive="docs-component-viewer-sidenav-item-selected">
11-
{{component.name}}
12-
</a>
13-
</li>
14-
</ul>
15-
</nav>
7+
<app-component-nav [params]="params"></app-component-nav>
168
</mat-sidenav>
17-
189
<div class="docs-component-sidenav-content">
1910
<component-page-header (toggleSidenav)="sidenav.toggle()"></component-page-header>
20-
<router-outlet></router-outlet>
21-
<app-footer></app-footer>
11+
<div class="docs-component-sidenav-inner-content">
12+
<div class="docs-component-sidenav-body-content">
13+
<!-- If on large screen, menu resides to left of content -->
14+
<app-component-nav
15+
*ngIf="!isScreenSmall()"
16+
[params]="params">
17+
</app-component-nav>
18+
<router-outlet></router-outlet>
19+
</div>
20+
<app-footer></app-footer>
21+
</div>
2222
</div>
23-
</mat-sidenav-container>
23+
</mat-sidenav-container>
Lines changed: 119 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,149 @@
1-
$sidenav-spacing-unit: 8px;
2-
$sidenav-width: 240px;
1+
@import '../../../styles/constants';
32

4-
app-component-sidenav {
5-
display: flex;
6-
}
3+
$sidenav-width: 240px;
74

85
.docs-component-viewer-sidenav-container {
9-
width: 100%;
10-
11-
.mat-drawer-content {
12-
position: absolute;
13-
right: 0;
14-
left: 0;
15-
}
6+
box-sizing: border-box;
167
}
178

189
.docs-component-viewer-sidenav {
19-
box-shadow: 3px 0 6px rgba(0, 0, 0, .24);
20-
padding-bottom: 72px;
21-
width: $sidenav-width;
22-
bottom: 0;
2310
overflow: auto;
24-
height: 100%;
11+
}
2512

26-
&.mat-sidenav-opened {
27-
box-shadow: 3px 0 6px rgba(0, 0, 0, .24);
28-
}
13+
.docs-component-sidenav-inner-content {
14+
display: flex;
15+
flex-direction: row;
2916

30-
// Section divider
31-
h3 {
32-
border: none;
33-
font-size: 10px;
34-
letter-spacing: 1px;
35-
line-height: $sidenav-spacing-unit * 3;
36-
text-transform: uppercase;
37-
font-weight: 400;
38-
margin: 0;
39-
padding: 0 ($sidenav-spacing-unit * 2);
17+
// The rule will match the element following the router-outlet which will be the routed component.
18+
router-outlet + * {
19+
flex-grow: 1;
4020
}
21+
}
4122

42-
ul {
43-
list-style-type: none;
44-
margin: 0;
45-
padding: 0;
23+
.mat-drawer {
24+
&::-webkit-scrollbar {
25+
height: 4px;
26+
width: 4px;
4627
}
28+
}
4729

48-
// Sidenav navigation item
49-
li {
50-
border-bottom-width: 1px;
51-
border-bottom-style: solid;
52-
margin: 0;
53-
padding: 0;
30+
.docs-component-viewer-nav {
31+
position: sticky;
32+
top: 25px;
5433

34+
.docs-component-viewer-nav-content {
35+
margin: 25px;
36+
width: $sidenav-width;
37+
max-height: 75vh;
38+
overflow: auto;
5539

56-
// Hide the border on the last item
57-
&:last-child {
58-
border-color: transparent;
40+
&::-webkit-scrollbar {
41+
height: 4px;
42+
width: 4px;
5943
}
6044

61-
> a {
62-
box-sizing: border-box;
63-
display: block;
64-
font-size: 14px;
65-
font-weight: 400;
66-
line-height: ($sidenav-spacing-unit * 6) - 1;
67-
text-decoration: none;
68-
transition: all .3s;
69-
padding: 0 ($sidenav-spacing-unit * 2);
45+
button {
46+
padding: 10px 15px;
47+
font-weight: 700;
48+
line-height: 16px;
49+
margin: 0;
50+
font-size: 13px;
51+
cursor: pointer;
7052
position: relative;
53+
display: block;
54+
width: 100%;
55+
text-align: left;
56+
background: none;
57+
border: none;
7158

72-
&.docs-component-viewer-sidenav-item-selected {
73-
font-weight: 600;
59+
&:focus {
60+
outline: none;
7461
}
62+
63+
.mat-icon {
64+
position: absolute;
65+
right: 5px;
66+
font-size: 18px;
67+
}
68+
}
69+
70+
hr {
71+
padding: 0;
72+
margin: 0;
73+
}
74+
75+
ul {
76+
list-style-type: none;
77+
margin: -5px 0 5px 0;
78+
padding: 0;
79+
overflow: hidden;
80+
}
81+
82+
li {
83+
font-size: 13px;
84+
line-height: 16px;
85+
margin: 0;
86+
padding: 5px 15px 5px 20px;
87+
}
88+
89+
a {
90+
display: block;
91+
text-decoration: none;
7592
}
7693
}
7794
}
7895

7996
.docs-component-sidenav-content {
80-
min-height: 100%;
8197
display: flex;
8298
flex-direction: column;
99+
}
83100

84-
// The rule will match the element following the router-outlet which will be the routed component.
85-
router-outlet + * {
86-
flex-grow: 1;
101+
// Add specific rule to prevent default rule conflict
102+
.docs-component-viewer-sidenav-container.mat-drawer-container{
103+
display: block;
104+
overflow: hidden;
105+
position: absolute;
106+
// Offset the top by the toolbar height
107+
top: 50px;
108+
bottom: 0;
109+
left: 0;
110+
right: 0;
111+
}
112+
113+
.docs-component-sidenav-inner-content {
114+
display: flex;
115+
flex-direction: column;
116+
}
117+
118+
.docs-component-sidenav-body-content {
119+
display: flex;
120+
// footer should always reside at the bottom of the screen.
121+
// if container not 100vh, push min height to that minus
122+
// the offset of the top bar and the footer height
123+
min-height: calc(100vh - 264px);
124+
}
125+
126+
@media (max-width: $small-breakpoint-width) {
127+
// Add specific rule to prevent default rule conflict
128+
.docs-component-viewer-sidenav-container .docs-component-viewer-sidenav {
129+
// offset the top by the header + tabs on a small screen
130+
top: 42px;
131+
}
132+
133+
.mat-sidenav-content {
134+
// offset the top by the header + tabs on a small screen
135+
margin-top: 42px;
136+
}
137+
138+
.docs-component-viewer-nav {
139+
position: relative;
140+
top: 0;
141+
142+
.docs-component-viewer-nav-content {
143+
box-sizing: border-box;
144+
margin: 0;
145+
max-height: initial;
146+
box-sizing: border-box;
147+
}
87148
}
88149
}

0 commit comments

Comments
 (0)