Skip to content

Commit a7ee1ea

Browse files
committed
feat: redesigning the sidebar
Using an img shield to display the webpack version Updating the styling to match @pastelsky's comp (see #438) Cleaning up some of the code in Sidebar and SidebarItem
1 parent 63ce480 commit a7ee1ea

File tree

4 files changed

+123
-77
lines changed

4 files changed

+123
-77
lines changed

components/sidebar-item/sidebar-item-style.scss

Lines changed: 51 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,81 +3,82 @@
33

44
.sidebar-item {
55
position: relative;
6-
font-size: getFontSize(-1);
7-
margin-bottom: 0.75em;
8-
9-
&__title {
10-
padding-right: 15px;
11-
font-weight: 400;
12-
text-decoration: none;
13-
color: inherit;
14-
15-
&:hover {
16-
color: $text-color-highlight;
17-
}
18-
}
6+
display: flex;
7+
flex-wrap: wrap;
8+
font-size: 15px;
9+
margin: 0.6em 0;
1910

2011
&__toggle {
21-
position: absolute;
22-
right: 0;
23-
line-height: 1.5;
12+
flex: 0 0 auto;
13+
margin-top: 0.125em;
14+
margin-right: 0.5em;
2415
cursor: pointer;
25-
color: getColor(dusty-grey);
26-
transition: color 250ms;
27-
margin-left: 1.5rem;
16+
color: getColor(denim);
17+
transition: all 250ms;
2818

2919
&:hover {
3020
color: getColor(mine-shaft);
3121
}
3222
}
3323

24+
&__title {
25+
flex: 1 1 auto;
26+
font-weight: 600;
27+
color: getColor(dove-grey);
28+
}
29+
3430
&__anchors {
35-
display:none;
31+
position: relative;
32+
display: none;
33+
flex: 0 0 100%;
34+
flex-wrap: wrap;
35+
margin: 0.35em 0;
36+
padding-left: 1.5em;
37+
overflow: hidden;
3638
list-style: none;
37-
padding: 0;
38-
margin: 0.5em 0 1em;
39-
}
4039

41-
&__version {
42-
margin-bottom: 10px;
40+
&:before {
41+
content: '';
42+
position: absolute;
43+
height: calc(100% - 0.6em);
44+
top: 0;
45+
left: 1.5em;
46+
border-left: 1px dashed getColor(dusty-grey);
47+
}
4348
}
4449

4550
&__anchor {
46-
margin:0.25em 0;
51+
position: relative;
52+
flex: 0 0 100%;
53+
margin: 0.25em 0;
54+
padding-left: 1em;
55+
@include control-overflow;
4756

48-
a {
49-
display: inline-block;
50-
max-width: 100%;
51-
overflow: hidden;
52-
white-space: nowrap;
53-
text-overflow: ellipsis;
54-
color: getColor(dusty-grey);
57+
&:first-child { margin-top: 0; }
58+
&:last-child { margin-bottom: 0; }
59+
&:before {
60+
content: '';
61+
position: absolute;
62+
width: 0.5em;
63+
left: 0;
64+
top: 60%;
65+
border-bottom: 1px dashed getColor(dusty-grey);
66+
}
5567

56-
&:hover {
57-
color: getColor(mine-shaft);
58-
}
68+
a {
69+
color: getColor(emperor);
70+
&:hover { color: getColor(denim); }
5971
}
6072
}
6173

6274
&--open {
6375
.sidebar-item__anchors {
64-
display:block;
65-
}
66-
67-
.sidebar-item__title {
68-
color: $text-color-highlight;
76+
display: flex;
6977
}
7078

7179
.sidebar-item__toggle {
72-
margin-left:-2px;
73-
transform:rotate(180deg) translateX(1px);
74-
}
75-
}
76-
77-
&--empty {
78-
.sidebar-item__toggle,
79-
.sidebar-item__anchors {
80-
display: none;
80+
transform-origin: center center;
81+
transform: rotate(90deg);
8182
}
8283
}
8384
}
Lines changed: 64 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,77 @@
11
import React from 'react';
22
import Link from '../link/link';
33

4+
const block = 'sidebar-item';
5+
46
export default class SidebarItem extends React.Component {
57
constructor(props) {
68
super(props);
79

810
this.state = {
9-
open: this.isOpen(props)
11+
open: this._isOpen(props)
1012
};
1113
}
1214

1315
render() {
14-
let { index, url, title, anchors = [], currentPage } = this.props;
15-
16-
let emptyMod = !anchors.length ? 'sidebar-item--empty' : '';
17-
let openMod = (this.state.open) ? 'sidebar-item--open' : '';
18-
let anchorUrl = url + '#';
19-
let isCurrentPage = `/${currentPage}` === url;
16+
let { title, anchors = [] } = this.props;
17+
let openMod = this.state.open ? `${block}--open` : '';
2018

2119
return (
22-
<div className={ `sidebar-item ${emptyMod} ${openMod}` }>
23-
<Link className="sidebar-item__title" to={ url }>{ title }</Link>
24-
<i className="sidebar-item__toggle icon-chevron-down" onClick={ this.toggle.bind(this) } />
25-
<ul className="sidebar-item__anchors">
26-
{
27-
anchors.map((anchor, j) => (
28-
<li className="sidebar-item__anchor" key={ `anchor-${index}-${j}` }>
29-
<a href={ isCurrentPage ? `#${anchor.id}` : anchorUrl + anchor.id }>{ anchor.title}</a>
30-
</li>
31-
))
32-
}
33-
</ul>
20+
<div className={ `${block} ${openMod}` }>
21+
{ anchors.length > 0 ? (
22+
<i
23+
className={ `${block}__toggle icon-chevron-right` }
24+
onClick={ this._toggle.bind(this) } />
25+
) : null }
26+
27+
<Link
28+
className={ `${block}__title` }
29+
to={ this.props.url }>
30+
{ title }
31+
</Link>
32+
33+
{ anchors.length > 0 ? (
34+
<ul className={ `${block}__anchors` }>
35+
{
36+
anchors.map(anchor => (
37+
<li
38+
className={ `${block}__anchor` }
39+
key={ `anchor-${title}-${anchor.id}` }>
40+
<a href={ this._generateAnchorURL(anchor) }>
41+
{ anchor.title }
42+
</a>
43+
</li>
44+
))
45+
}
46+
</ul>
47+
) : null }
3448
</div>
3549
);
3650
}
3751

3852
componentWillReceiveProps(nextProps) {
39-
if (nextProps.currentPage == this.props.currentPage) return;
40-
41-
this.setState({ open: this.isOpen(nextProps) });
53+
if ( nextProps.currentPage !== this.props.currentPage ) {
54+
this.setState({
55+
open: this._isOpen(nextProps)
56+
});
57+
}
4258
}
4359

44-
isOpen(props) {
60+
/**
61+
* Checks whether the item should be expanded
62+
*
63+
* @param {object} props - The current props
64+
*/
65+
_isOpen(props) {
4566
return `/${props.currentPage}` === props.url;
4667
}
4768

48-
toggle(e) {
69+
/**
70+
* Toggles the open state (expanded/collapsed)
71+
*
72+
* @param {object} e - Click event
73+
*/
74+
_toggle(e) {
4975
let { onToggle } = this.props;
5076

5177
this.setState({
@@ -56,4 +82,18 @@ export default class SidebarItem extends React.Component {
5682
}
5783
});
5884
}
85+
86+
/**
87+
* Generate the url for the given [anchor] depending on the current page
88+
*
89+
* @return {object} anchor - The anchor object containing its id
90+
*/
91+
_generateAnchorURL(anchor) {
92+
let { currentPage, url } = this.props;
93+
94+
if ( `/${currentPage}` === url ) {
95+
return `#${anchor.id}`;
96+
97+
} else return `${url}#${anchor.id}`;
98+
}
5999
}

components/sidebar/sidebar.jsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,12 @@ export default class Sidebar extends Component {
3535
height={ availableHeight } />
3636

3737
<div className="sidebar__inner">
38-
<h3 className="sidebar-item__version">Version 2.2</h3>
38+
<img src="https://img.shields.io/badge/webpack-v2.2.1-blue.svg" />
3939

4040
<SidebarItem
4141
url={ `/${sectionName}` }
4242
title="Introduction"
43-
currentPage= { currentPage }
44-
/>
43+
currentPage= { currentPage } />
4544

4645
{
4746
pages.map(({ url, title, anchors }, i) =>

styles/partials/_mixins.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44
}
55
}
66

7+
@mixin control-overflow {
8+
overflow: hidden;
9+
white-space: nowrap;
10+
text-overflow: ellipsis;
11+
}
12+
713
@mixin fontantialias ($on) {
814
@if $on == true {
915
-webkit-font-smoothing: antialiased;

0 commit comments

Comments
 (0)