User Menu (#478)

This commit is contained in:
Kyle Knight
2016-11-15 11:17:33 -06:00
committed by GitHub
parent 752710ccf1
commit 0746e15cad
4 changed files with 276 additions and 73 deletions
-1
View File
@@ -3,7 +3,6 @@ files:
include: 'frontend/**/*.s+(a|c)ss'
ignore:
- 'frontend/styles/_fonts.scss'
- 'frontend/styles/_icons.scss'
options:
formatter: stylish
merge-default-rules: false
@@ -8,6 +8,7 @@ import { activeTabFromPathname, activeSubTabFromPathname } from './helpers';
import configInterface from '../../../interfaces/config';
import kolideLogo from '../../../../assets/images/kolide-logo.svg';
import navItems from './navItems';
import UserMenu from './UserMenu';
import userInterface from '../../../interfaces/user';
class SiteNavSidePanel extends Component {
@@ -32,6 +33,7 @@ class SiteNavSidePanel extends Component {
activeTab,
activeSubItem,
showSubItems: false,
userMenuOpened: false,
};
}
@@ -94,35 +96,58 @@ class SiteNavSidePanel extends Component {
};
}
toggleUserMenu = () => {
const { userMenuOpened } = this.state;
this.setState({ userMenuOpened: !userMenuOpened });
}
renderHeader = () => {
const {
config: {
org_name: orgName,
},
user: {
enabled,
username,
},
user,
} = this.props;
const { userMenuOpened } = this.state;
const { toggleUserMenu } = this;
const { enabled, username } = user;
const headerBaseClass = 'site-nav-header';
const headerToggleClass = classnames(
headerBaseClass,
'button',
'button--unstyled',
{ [`${headerBaseClass}--open`]: userMenuOpened }
);
const userStatusClass = classnames(
`${headerBaseClass}__user-status`,
{ [`${headerBaseClass}__user-status--enabled`]: enabled }
);
return (
<header className={headerBaseClass}>
<img
alt="Company logo"
src={kolideLogo}
className={`${headerBaseClass}__logo`}
/>
<h1 className={`${headerBaseClass}__org-name`}>{orgName}</h1>
<div className={userStatusClass} />
<h2 className={`${headerBaseClass}__username`}>{username}</h2>
<i className={`${headerBaseClass}__org-chevron kolidecon-chevrondownbold`} />
<header>
<button className={headerToggleClass} onClick={toggleUserMenu}>
<div className={`${headerBaseClass}__org`}>
<img
alt="Company logo"
src={kolideLogo}
className={`${headerBaseClass}__logo`}
/>
<h1 className={`${headerBaseClass}__org-name`}>{orgName}</h1>
<div className={userStatusClass} />
<h2 className={`${headerBaseClass}__username`}>{username}</h2>
<i className={`${headerBaseClass}__org-chevron kolidecon-chevrondown`} />
</div>
<UserMenu
user={user}
isOpened={userMenuOpened}
/>
</button>
</header>
);
}
@@ -147,17 +172,14 @@ class SiteNavSidePanel extends Component {
onClick={setActiveTab(navItem)}
style={{ width: '100%' }}
>
{active && <div className={`${navItemBaseClass}__active-nav`} />}
<li
key={name}
className={navItemClasses}
>
<div style={{ position: 'relative', textAlign: 'left' }}>
<i className={`${navItemBaseClass}__icon ${icon}`} />
<span className={`${navItemBaseClass}__name`}>
{name}
</span>
</div>
<i className={`${navItemBaseClass}__icon ${icon}`} />
<span className={`${navItemBaseClass}__name`}>
{name}
</span>
</li>
</button>
{active && renderSubItems(subItems)}
@@ -0,0 +1,56 @@
import React, { Component, PropTypes } from 'react';
import classnames from 'classnames';
class UserMenu extends Component {
static propTypes = {
isOpened: PropTypes.bool,
user: PropTypes.shape({
gravatarURL: PropTypes.string,
name: PropTypes.string,
position: PropTypes.string,
}).isRequired,
};
static defaultProps = {
isOpened: false,
};
render () {
const {
isOpened,
user: {
gravatarURL,
name,
position,
},
} = this.props;
const toggleBaseClass = 'user-menu-toggle';
const userMenuClass = classnames(
toggleBaseClass,
{ [`${toggleBaseClass}--open`]: isOpened }
);
return (
<div className={userMenuClass}>
<img
alt="User Avatar"
src={gravatarURL}
className={`${toggleBaseClass}__avatar`}
/>
<p className={`${toggleBaseClass}__name`}>{ name }</p>
<p className={`${toggleBaseClass}__position`}>{ position }</p>
<nav className={`${toggleBaseClass}__nav`}>
<ul className={`${toggleBaseClass}__nav-list`}>
<li className={`${toggleBaseClass}__nav-item`}><a href="#user-settings"><i className="kolidecon-user-settings" /><span>Account Settings</span></a></li>
<li className={`${toggleBaseClass}__nav-item`}><a href="#logout"><i className="kolidecon-logout" /><span>Log Out</span></a></li>
</ul>
</nav>
</div>
);
}
}
export default UserMenu;
@@ -1,35 +1,51 @@
.site-nav-header {
border-bottom: 1px solid $accent-light;
height: 62px;
@include transition(background 150ms $ease-in-quad);
cursor: pointer;
padding-left: 54px;
padding-top: 26px;
margin-right: 16px;
padding: $pad-large $pad-medium 0;
position: relative;
display: block;
width: 100%;
color: $text-ultradark;
text-align: left;
border-radius: 0;
&:hover {
background: $bg-medium;
}
@media (max-width: 760px) {
padding: 0;
}
&__org {
@include transition(border 150ms $ease-in-quad);
@include clearfix;
position: relative;
z-index: 2;
border-bottom: 1px solid $accent-light;
padding-bottom: $pad-medium;
max-height: 100px;
}
&__logo {
position: absolute;
left: 0;
top: 23px;
height: 42px;
@include size(42px);
float: left;
margin-right: 10px;
border: 1px solid $accent-medium;
border-radius: 100%;
border-radius: 50%;
@media (max-width: 760px) {
left: 5px;
margin: $pad-half 5px;
}
}
&__org-name {
@include ellipsis(110px);
font-size: 16px;
letter-spacing: 0.5px;
margin: 0;
overflow: hidden;
padding: 0;
position: relative;
text-overflow: ellipsis;
top: 1px;
display: block;
white-space: nowrap;
@media (max-width: 760px) {
@@ -55,15 +71,14 @@
}
&__username {
position: relative;
display: inline-block;
@include ellipsis(110px);
margin: 0;
padding: 0;
top: -3px;
left: 4px;
font-size: 13px;
letter-spacing: 0.6px;
text-transform: uppercase;
position: relative;
line-height: 16px;
@media (max-width: 760px) {
display: none;
@@ -71,19 +86,128 @@
}
&__org-chevron {
@include transition(transform 150ms $ease-in-quad);
color: $accent-medium;
font-size: 12px;
position: absolute;
top: 50px;
right: 35px;
float: right;
@media (max-width: 760px) {
top: auto;
left: 0;
right: 0;
bottom: 6px;
float: none;
text-align: center;
display: block;
clear: both;
}
}
&--open {
background-color: $text-dark;
.site-nav-header__org {
border-color: $text-ultradark;
}
.site-nav-header__org-name,
.site-nav-header__username {
color: $white;
}
.site-nav-header__org-chevron {
@include transform(rotate(180deg));
}
&:hover {
background-color: $text-dark;
}
}
}
.user-menu-toggle {
@include transition(opacity 150ms ease-in-out);
height: 0;
background-color: $text-dark;
width: 222px;
position: absolute;
left: 0;
padding: 0;
z-index: 2;
overflow: hidden;
opacity: 0;
box-sizing: border-box;
@media (max-width: 760px) {
width: 53px;
}
&--open {
height: auto;
padding: $pad-medium 0 0;
opacity: 1;
}
&__avatar {
@include size(42px);
float: left;
border: solid 1px $accent-medium;
border-radius: 50%;
margin: 0 10px 0 $pad-medium;
@media (max-width: 760px) {
margin: $pad-xsmall 5px;
}
}
&__name,
&__position {
@include ellipsis(135px);
color: $white;
font-size: $small;
margin: 0;
line-height: $large;
float: left;
@media (max-width: 760px) {
display: none;
}
}
&__nav {
clear: both;
padding-top: $pad-small;
}
&__nav-list {
list-style: none;
margin: 0;
padding: 0;
}
&__nav-item {
font-size: $small;
text-transform: uppercase;
a {
@include transition(background 150ms $ease-in-quad);
letter-spacing: 0.5px;
color: $white;
display: block;
line-height: 50px;
text-decoration: none;
padding: 0 $pad-medium;
i {
margin-right: $pad-half;
font-size: $large;
}
&:hover {
background: $accent-text;
}
}
@media (max-width: 760px) {
span {
display: none;
}
}
}
}
@@ -93,36 +217,21 @@
&__icon {
position: relative;
font-size: 22px;
margin-right: 16px;
top: 4px;
left: 0;
font-size: $large;
margin-right: $pad-medium;
vertical-align: middle;
@media (max-width: 760px) {
display: block;
text-align: center;
margin-right: 0;
}
}
&__active-nav {
content: '';
width: 6px;
height: 50px;
position: absolute;
left: -16px;
top: 0;
bottom: 0;
background-color: #9a61c6;
@media (max-width: 760px) {
left: 0;
line-height: 40px;
}
}
&__name {
display: inline-block;
text-decoration: none;
vertical-align: middle;
@media (max-width: 760px) {
display: none;
@@ -131,14 +240,15 @@
&__item {
@include transition(color 200ms ease-in-out);
min-height: 40px;
line-height: 40px;
position: relative;
color: $text-light;
cursor: pointer;
font-size: 13px;
font-size: $small;
letter-spacing: 0.5px;
text-transform: uppercase;
padding-top: $pad-half;
padding: 0 $pad-medium;
text-align: left;
&:hover {
color: $text-dark;
@@ -152,8 +262,25 @@
color: $brand-dark;
}
&::before {
content: '';
width: 6px;
height: 55px;
position: absolute;
left: 0;
top: 0;
background-color: $brand;
z-index: 1;
}
@media (max-width: 760px) {
border-bottom: 6px solid #9a61c6;
border-left: 6px solid #9a61c6;
padding: 0;
&::before {
display: none;
}
}
}
}
@@ -289,7 +416,6 @@
box-shadow: 2px 0 8px 0 rgba($black, 0.1);
box-sizing: border-box;
left: 0;
padding-left: 16px;
position: fixed;
top: 0;
width: 223px;
@@ -302,7 +428,7 @@
@media (max-width: 760px) {
.sub-nav {
width: 22px;
width: 0;
&-expanded {
width: 188px;