Merge pull request #4536 from hashicorp/f-ui-mobile-views

UI: Mobile Views
This commit is contained in:
Michael Lange
2018-08-06 11:31:46 -07:00
committed by GitHub
20 changed files with 270 additions and 13 deletions

View File

@@ -0,0 +1,5 @@
import Component from '@ember/component';
export default Component.extend({
onHamburgerClick() {},
});

View File

@@ -32,6 +32,8 @@ export default Component.extend({
});
}),
onHamburgerClick() {},
gotoJobsForNamespace(namespace) {
if (!namespace || !namespace.get('id')) return;

View File

@@ -2,4 +2,6 @@ import Component from '@ember/component';
export default Component.extend({
classNames: ['page-layout'],
isGutterOpen: false,
});

View File

@@ -6,12 +6,14 @@
@import './components/empty-message';
@import './components/error-container';
@import './components/gutter';
@import './components/gutter-toggle';
@import './components/inline-definitions';
@import './components/job-diff';
@import './components/json-viewer';
@import './components/loading-spinner';
@import './components/metrics';
@import './components/node-status-light';
@import './components/nomad-logo';
@import './components/page-layout';
@import './components/simple-list';
@import './components/status-text';

View File

@@ -0,0 +1,19 @@
.gutter-toggle {
display: none;
position: absolute;
left: 0;
padding: 1.25rem 0.7rem;
z-index: 1; // Make sure the toggle is on top of its siblings
height: 100%;
fill: desaturate(lighten($nomad-green, 20%), 30%);
cursor: pointer;
> svg {
width: 15px;
}
@media #{$mq-hidden-gutter} {
display: inline-block;
}
}

View File

@@ -1,4 +1,74 @@
.gutter {
height: 100%;
border-right: 1px solid $grey-blue;
overflow: hidden;
@media #{$mq-hidden-gutter} {
border-right: none;
&.is-open {
box-shadow: 0 0 30px darken($nomad-green-darker, 20%);
}
}
.collapsed-menu {
display: none;
position: relative;
height: 3.5rem;
width: $gutter-width;
transform: translateX($gutter-width);
z-index: $z-gutter;
transition: transform ease-in-out 0.2s;
&.is-open {
transform: translateX(0);
}
.gutter-toggle {
fill: $grey-light;
}
.nomad-logo {
fill: $grey-light;
}
.logo-container {
display: flex;
align-items: center;
height: 100%;
padding: 0.5rem 1rem;
margin-left: 20px;
}
@media #{$mq-hidden-gutter} {
display: block;
}
}
.menu {
z-index: $z-gutter;
}
}
// Treated as an element of the gutter component despite not being nested within
// for z-index reasons.
.gutter-backdrop {
display: block;
position: fixed;
background: darken($nomad-green-darker, 10%);
opacity: 0;
width: calc(100vw + #{$gutter-width});
height: 100vh;
top: 0;
left: 0;
transform: translateY(-100%);
transition: opacity ease-in-out 0.2s;
z-index: $z-gutter-backdrop;
@media #{$mq-hidden-gutter} {
&.is-open {
transform: translateY(0);
opacity: 0.7;
}
}
}

View File

@@ -0,0 +1,9 @@
.nomad-logo {
height: 26px;
max-height: 26px;
fill: $white;
.faded {
opacity: 0.7;
}
}

View File

@@ -31,10 +31,28 @@
bottom: 0;
top: $header-height;
z-index: $z-gutter;
background: $white;
}
&.is-right {
margin-left: $gutter-width;
overflow-x: auto;
}
@media #{$mq-hidden-gutter} {
&.is-left {
top: 0;
transform: translateX(-$gutter-width);
transition: transform ease-in-out 0.2s;
&.is-open {
transform: translateX(0);
}
}
&.is-right {
margin-left: 0;
}
}
}
}

View File

@@ -1,10 +1,13 @@
.navbar {
display: flex;
&.is-primary {
background: linear-gradient(to right, $nomad-green-darker, $nomad-green-dark);
height: 3.5rem;
color: $primary-invert;
padding-left: 20px;
padding-right: 20px;
overflow: hidden;
.navbar-item {
color: rgba($primary-invert, 0.8);
@@ -35,11 +38,13 @@
top: 1.25em;
}
}
}
&.is-logo img {
height: 26px;
max-height: 26px;
}
.navbar-end {
display: flex;
align-items: stretch;
justify-content: flex-end;
margin-left: auto;
}
.navbar-end > a.navbar-item {
@@ -65,8 +70,15 @@
}
.navbar-item {
display: flex;
align-items: center;
&.is-gutter {
width: $gutter-width;
@media #{$mq-hidden-gutter} {
width: 0;
}
}
}
}

View File

@@ -42,5 +42,9 @@
+ * {
margin-top: 5em;
}
@media #{$mq-hidden-gutter} {
left: 0;
}
}
}

View File

@@ -39,3 +39,5 @@ $breadcrumb-item-color: $white;
$breadcrumb-item-hover-color: $white;
$breadcrumb-item-active-color: $white;
$breadcrumb-item-separator-color: $primary;
$mq-hidden-gutter: 'only screen and (max-width : 960px)';

View File

@@ -1,5 +1,6 @@
$z-tooltip: 250;
$z-header: 200;
$z-gutter: 200;
$z-header: 210;
$z-gutter: 220;
$z-gutter-backdrop: 219;
$z-subnav: 200;
$z-base: 100;

View File

@@ -1,8 +1,11 @@
{{#freestyle-usage "header" title="Global Header"}}
<nav class="navbar is-primary">
<div class="navbar-brand">
<span class="gutter-toggle" aria-label="menu">
{{partial "partials/hamburger-menu"}}
</span>
<span class="navbar-item is-logo">
<img src="/ui/images/nomad-logo.svg" alt="Nomad" />
{{partial "partials/nomad-logo"}}
</span>
</div>
<div class="navbar-end">

View File

@@ -1,7 +1,10 @@
<nav class="navbar is-primary">
<div class="navbar-brand">
<span data-test-header-gutter-toggle class="gutter-toggle" aria-label="menu" onclick={{action onHamburgerClick}}>
{{partial "partials/hamburger-menu"}}
</span>
<span class="navbar-item is-logo">
<img src="/ui/images/nomad-logo.svg" alt="Nomad" />
{{partial "partials/nomad-logo"}}
</span>
</div>
<div class="navbar-end">

View File

@@ -1,5 +1,13 @@
<div class="page-column is-left">
<div class="gutter">
<div data-test-gutter-menu class="page-column is-left {{if isOpen "is-open"}}">
<div class="gutter {{if isOpen "is-open"}}">
<header class="collapsed-menu {{if isOpen "is-open"}}">
<span data-test-gutter-gutter-toggle class="gutter-toggle" aria-label="menu" onclick={{action onHamburgerClick}}>
{{partial "partials/hamburger-menu"}}
</span>
<span class="logo-container">
{{partial "partials/nomad-logo"}}
</span>
</header>
<aside class="menu">
<p class="menu-label">
Workload
@@ -42,3 +50,4 @@
<div data-test-page-content class="page-column is-right">
{{yield}}
</div>
<div data-test-gutter-backdrop class="gutter-backdrop {{if isOpen "is-open"}}" onclick={{action onHamburgerClick}}></div>

View File

@@ -1,6 +1,11 @@
{{#global-header class="page-header"}}
{{#global-header
class="page-header"
onHamburgerClick=(action (mut isGutterOpen) true)}}
{{app-breadcrumbs}}
{{/global-header}}
{{#gutter-menu class="page-body"}}
{{#gutter-menu
class="page-body"
isOpen=isGutterOpen
onHamburgerClick=(action (mut isGutterOpen) false)}}
{{yield}}
{{/gutter-menu}}

View File

@@ -0,0 +1,5 @@
<svg class="hamburger-menu" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="100" height="16" />
<rect x="0" y="42" width="100" height="16" />
<rect x="0" y="84" width="100" height="16" />
</svg>

After

Width:  |  Height:  |  Size: 236 B

View File

@@ -0,0 +1,14 @@
<svg class="nomad-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 206.31 60.07">
<g>
<g>
<path d="M78.49,21.83V46.07h-5.9v-32h8.06L92.79,38.39V14.1h5.9v32H90.63Z"/>
<path d="M113.09,46.55c-8,0-10.18-4.42-10.18-9.22V31.43c0-4.8,2.16-9.22,10.18-9.22s10.18,4.42,10.18,9.22v5.91C123.27,42.13,121.11,46.55,113.09,46.55Zm0-19.35c-3.12,0-4.32,1.39-4.32,4v6.29c0,2.64,1.2,4,4.32,4s4.32-1.39,4.32-4V31.24C117.41,28.6,116.21,27.2,113.09,27.2Z"/>
<path d="M141.08,46.07V29.75c0-1.25-.53-1.87-1.87-1.87a16.16,16.16,0,0,0-6.1,2V46.07h-5.86V22.69h4.46l.58,2a23.43,23.43,0,0,1,9.36-2.45,4.44,4.44,0,0,1,4.42,2.5,23,23,0,0,1,9.41-2.5c3.89,0,5.28,2.74,5.28,6.91V46.07H154.9V29.75c0-1.25-.53-1.87-1.87-1.87a15.5,15.5,0,0,0-6.1,2V46.07Z"/>
<path d="M182.88,46.07h-4.8l-.43-1.58a12.79,12.79,0,0,1-7,2.06c-4.27,0-6.1-2.93-6.1-7,0-4.75,2.06-6.58,6.82-6.58H177V30.56c0-2.59-.72-3.5-4.46-3.5a32.71,32.71,0,0,0-6.48.72l-.72-4.46a30.52,30.52,0,0,1,8-1.1c7.34,0,9.5,2.59,9.5,8.45ZM177,37.24h-4.32c-1.92,0-2.45.53-2.45,2.3s.53,2.35,2.35,2.35a9.2,9.2,0,0,0,4.42-1.2Z"/>
<path d="M186.48,30.47c0-5.18,2.3-8.26,7.73-8.26a32.22,32.22,0,0,1,6.24.67V13.14l5.86-.82V46.07h-4.66l-.58-2a12.31,12.31,0,0,1-7.39,2.45c-4.7,0-7.2-2.79-7.2-8.11Zm14-2.64a26,26,0,0,0-5.18-.62c-2.11,0-2.93,1-2.93,3.12v8.26c0,1.92.72,3,2.88,3a8.28,8.28,0,0,0,5.23-2.11Z"/>
<polygon class="faded" points="38.02 23.13 38.02 33.08 31.09 37.09 26.25 34.09 26.25 60.06 26.38 60.07 52.49 45.07 52.49 15.11 52.01 15.11 38.02 23.13"/>
<polygon points="26.03 0.07 0 15.11 17.56 25.43 21.11 23.27 29.75 28.08 29.75 18.08 38.02 13.11 38.02 23.13 52.49 15.11 52.49 15.07 26.03 0.07"/>
<polygon points="22.75 32.09 22.75 42.08 14.87 47.08 14.87 27.08 17.86 25.25 0.15 15.11 0 15.11 0 45.07 26.25 60.06 26.25 34.09 22.75 32.09"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 206.31 60.07"><defs><style>.cls-1,.cls-2{fill:#fff;}.cls-2{opacity:0.7;}</style></defs><title>Asset 1</title><g id="Layer_2" data-name="Layer 2"><g id="Logo"><path class="cls-1" d="M78.49,21.83V46.07h-5.9v-32h8.06L92.79,38.39V14.1h5.9v32H90.63Z"/><path class="cls-1" d="M113.09,46.55c-8,0-10.18-4.42-10.18-9.22V31.43c0-4.8,2.16-9.22,10.18-9.22s10.18,4.42,10.18,9.22v5.91C123.27,42.13,121.11,46.55,113.09,46.55Zm0-19.35c-3.12,0-4.32,1.39-4.32,4v6.29c0,2.64,1.2,4,4.32,4s4.32-1.39,4.32-4V31.24C117.41,28.6,116.21,27.2,113.09,27.2Z"/><path class="cls-1" d="M141.08,46.07V29.75c0-1.25-.53-1.87-1.87-1.87a16.16,16.16,0,0,0-6.1,2V46.07h-5.86V22.69h4.46l.58,2a23.43,23.43,0,0,1,9.36-2.45,4.44,4.44,0,0,1,4.42,2.5,23,23,0,0,1,9.41-2.5c3.89,0,5.28,2.74,5.28,6.91V46.07H154.9V29.75c0-1.25-.53-1.87-1.87-1.87a15.5,15.5,0,0,0-6.1,2V46.07Z"/><path class="cls-1" d="M182.88,46.07h-4.8l-.43-1.58a12.79,12.79,0,0,1-7,2.06c-4.27,0-6.1-2.93-6.1-7,0-4.75,2.06-6.58,6.82-6.58H177V30.56c0-2.59-.72-3.5-4.46-3.5a32.71,32.71,0,0,0-6.48.72l-.72-4.46a30.52,30.52,0,0,1,8-1.1c7.34,0,9.5,2.59,9.5,8.45ZM177,37.24h-4.32c-1.92,0-2.45.53-2.45,2.3s.53,2.35,2.35,2.35a9.2,9.2,0,0,0,4.42-1.2Z"/><path class="cls-1" d="M186.48,30.47c0-5.18,2.3-8.26,7.73-8.26a32.22,32.22,0,0,1,6.24.67V13.14l5.86-.82V46.07h-4.66l-.58-2a12.31,12.31,0,0,1-7.39,2.45c-4.7,0-7.2-2.79-7.2-8.11Zm14-2.64a26,26,0,0,0-5.18-.62c-2.11,0-2.93,1-2.93,3.12v8.26c0,1.92.72,3,2.88,3a8.28,8.28,0,0,0,5.23-2.11Z"/><polygon class="cls-2" points="38.02 23.13 38.02 33.08 31.09 37.09 26.25 34.09 26.25 60.06 26.38 60.07 52.49 45.07 52.49 15.11 52.01 15.11 38.02 23.13"/><polygon class="cls-1" points="26.03 0.07 0 15.11 17.56 25.43 21.11 23.27 29.75 28.08 29.75 18.08 38.02 13.11 38.02 23.13 52.49 15.11 52.49 15.07 26.03 0.07"/><polygon class="cls-1" points="22.75 32.09 22.75 42.08 14.87 47.08 14.87 27.08 17.86 25.25 0.15 15.11 0 15.11 0 45.07 26.25 60.06 26.25 34.09 22.75 32.09"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -0,0 +1,73 @@
import { test, moduleForComponent } from 'ember-qunit';
import { find, click } from 'ember-native-dom-helpers';
import wait from 'ember-test-helpers/wait';
import hbs from 'htmlbars-inline-precompile';
import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
moduleForComponent('page-layout', 'Integration | Component | page layout', {
integration: true,
beforeEach() {
this.server = startMirage();
},
afterEach() {
this.server.shutdown();
},
});
test('the global-header hamburger menu opens the gutter menu', function(assert) {
this.render(hbs`{{page-layout}}`);
assert.notOk(
find('[data-test-gutter-menu]').classList.contains('is-open'),
'Gutter menu is not open'
);
click('[data-test-header-gutter-toggle]');
return wait().then(() => {
assert.ok(find('[data-test-gutter-menu]').classList.contains('is-open'), 'Gutter menu is open');
});
});
test('the gutter-menu hamburger menu closes the gutter menu', function(assert) {
this.render(hbs`{{page-layout}}`);
click('[data-test-header-gutter-toggle]');
return wait()
.then(() => {
assert.ok(
find('[data-test-gutter-menu]').classList.contains('is-open'),
'Gutter menu is open'
);
click('[data-test-gutter-gutter-toggle]');
return wait();
})
.then(() => {
assert.notOk(
find('[data-test-gutter-menu]').classList.contains('is-open'),
'Gutter menu is not open'
);
});
});
test('the gutter-menu backdrop closes the gutter menu', function(assert) {
this.render(hbs`{{page-layout}}`);
click('[data-test-header-gutter-toggle]');
return wait()
.then(() => {
assert.ok(
find('[data-test-gutter-menu]').classList.contains('is-open'),
'Gutter menu is open'
);
click('[data-test-gutter-backdrop]');
return wait();
})
.then(() => {
assert.notOk(
find('[data-test-gutter-menu]').classList.contains('is-open'),
'Gutter menu is not open'
);
});
});