Files
weave-scope/client/app/styles/main.less
David Kaltschmidt d520cffec7 Performance tweaks
Add debug.html to show toolbar

Perfjankie test runner

Playing w/ the pure mixin for perf. improvements

* Works well! Smoother zooming/panning when things have settled.
* Extract node movement to node-container, make nodes pure

Extracted node chart elements into own components

Keep control objects immutable while in components

Keep layout state objects alive

Made other components pure, removed mixin from stateless components

Remove font size adjustment from scaling

Fix zoomscale

Move node transform to node

* makes more sense there because the coords are rounded in the container

dynamic coords precision based on topology size

Make edge points immutable

Remove nodes maximum for layout engine

Dont send all canvas state down to next component

moving layout handling back to nodes-chart.js

Omit some props for edges/nodes, dont animate edges on low precision

Moved AppStore access out of lower components
2016-04-05 15:45:13 +02:00

1113 lines
19 KiB
Plaintext

@font-face {
font-family: "Roboto";
src: url("../../node_modules/materialize-css/font/roboto/Roboto-Regular.woff2"),
url("../../node_modules/materialize-css/font/roboto/Roboto-Regular.woff"),
url("../../node_modules/materialize-css/font/roboto/Roboto-Regular.ttf");
}
.browsehappy {
margin: 0.2em 0;
background: #ccc;
color: #000;
padding: 0.2em 0;
}
/* weave company colours */
@weave-gray-blue: rgb(85,105,145);
@weave-blue: rgb(0,210,255);
@weave-orange: rgb(255,75,25);
@weave-charcoal-blue: rgb(50,50,75); // #32324B
@base-font: "Roboto", sans-serif;
@mono-font: "Menlo", "DejaVu Sans Mono", "Liberation Mono", monospace;
@base-ease: ease-in-out;
@primary-color: @weave-charcoal-blue;
@background-color: lighten(@primary-color, 66%);
@background-lighter-color: lighten(@background-color, 8%);
@background-darker-color: darken(@background-color, 8%);
@background-darker-secondary-color: darken(@background-color, 4%);
@background-dark-color: @primary-color;
@text-color: lighten(@primary-color, 5%);
@text-secondary-color: lighten(@text-color, 15%);
@text-tertiary-color: lighten(@text-color, 30%);
@border-light-color: lighten(@text-color, 60%);
@text-darker-color: @primary-color;
@white: @background-lighter-color;
@details-window-width: 420px;
@details-window-padding-left: 36px;
@border-radius: 4px;
@terminal-header-height: 34px;
@node-opacity-blurred: 0.25;
@node-highlight-fill-opacity: 0.1;
@node-highlight-stroke-opacity: 0.4;
@node-highlight-stroke-width: 1px;
@node-border-stroke-width: 2.5px;
@node-pseudo-opacity: 0.8;
@edge-highlight-opacity: 0.1;
@edge-opacity-blurred: 0.2;
@edge-opacity: 0.5;
@edge-link-stroke-width: 1px;
@btn-opacity-default: 0.7;
@btn-opacity-hover: 1;
@btn-opacity-selected: 0.9;
@link-opacity-default: 0.8;
/* add this class to truncate text with ellipsis, container needs width */
.truncate {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.colorable {
transition: background-color .3s @base-ease;
}
.palable {
transition: all .2s @base-ease;
}
.hideable {
transition: opacity .5s @base-ease;
}
.hang-around {
transition-delay: .5s;
}
.hide {
opacity: 0;
}
.shadow-2 {
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.16), 0 3px 10px rgba(0, 0, 0, 0.23);
}
.shadow-3 {
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.19), 0 6px 10px rgba(0, 0, 0, 0.23);
}
.btn-opacity {
.palable;
opacity: @btn-opacity-default;
&-selected {
opacity: @btn-opacity-selected;
}
&:hover {
opacity: @btn-opacity-hover;
}
}
* {
box-sizing: border-box;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
*:before,
*:after {
box-sizing: border-box;
}
html {
-webkit-font-smoothing: antialiased;
}
html,
body {
height: 100%;
width: 100%;
}
/* Space out content a bit */
body {
background: linear-gradient(30deg, @background-color 0%, @background-lighter-color 100%);
color: @text-color;
line-height: 150%;
font-family: @base-font;
font-size: 13px;
margin: 0;
}
p {
line-height: 20px;
padding-top: 6px;
margin-bottom: 14px;
letter-spacing: 0;
font-weight: 400;
color: @text-color;
}
h2 {
font-size: 34px;
line-height: 40px;
padding-top: 8px;
margin-bottom: 12px;
font-weight: 400;
}
.app {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
overflow: auto;
}
.header {
position: absolute;
top: 32px;
width: 100%;
height: 80px;
z-index: 20;
display: flex;
.logo {
margin: -8px 0 0 64px;
height: 64px;
width: 250px;
}
}
.footer {
position: absolute;
bottom: 16px;
right: 48px;
z-index: 20;
color: @text-tertiary-color;
font-size: 0.7rem;
display: flex;
a {
color: @text-secondary-color;
.btn-opacity;
text-decoration: none;
font-weight: bold;
font-size: 90%;
cursor: pointer;
}
&-status {
margin-right: 1em;
}
&-label {
text-transform: uppercase;
margin: 0 0.25em;
}
&-icon {
margin-left: 0.5em;
padding: 4px 3px;
color: @text-color;
position: relative;
top: -1px;
border: 1px solid transparent;
border-radius: 4px;
&:hover {
border: 1px solid @text-tertiary-color;
}
.fa {
font-size: 150%;
position: relative;
top: 2px;
}
&-active {
border: 1px solid @text-tertiary-color;
animation: blinking 1.5s infinite @base-ease;
}
}
&-icon &-label {
margin-right: 0.5em;
}
}
.topologies {
margin: 4px 0 0 128px;
display: flex;
.topologies-item {
margin: 0px 8px;
&-label {
font-size: .8rem;
text-transform: uppercase;
}
}
.topologies-sub {
&-item {
&-label {
font-size: .7rem;
text-transform: uppercase;
}
}
}
.topologies-item-main,
.topologies-sub-item {
// border: 1px solid @background-darker-secondary-color;
color: @text-secondary-color;
.btn-opacity;
cursor: pointer;
padding: 4px 8px;
border-radius: @border-radius;
opacity: 0.8;
margin-bottom: 3px;
&-active, &:hover {
color: @text-color;
background-color: @background-darker-secondary-color;
}
&-active {
opacity: 0.85;
}
}
.topologies-sub-item {
padding: 2px 8px;
}
}
.nodes-chart {
&-error {
.hideable;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
color: @text-secondary-color;
width: 33%;
.heading {
font-size: 125%;
}
&-icon {
text-align: center;
opacity: 0.25;
font-size: 320px;
}
}
svg {
.hideable;
position: absolute;
top: 0px;
}
.logo {
display: none;
}
svg.exported {
.logo {
display: inline;
}
}
text {
font-family: @base-font;
fill: @text-secondary-color;
&.node-label {
fill: @text-color;
}
&.node-sublabel {
fill: @text-secondary-color;
}
}
.nodes-chart-nodes > .node {
cursor: pointer;
transition: opacity .5s @base-ease;
&.pseudo {
cursor: default;
.node-label {
fill: @text-secondary-color;
}
.node-sublabel {
fill: @text-tertiary-color;
}
.node {
opacity: @node-pseudo-opacity;
}
.border {
opacity: @node-pseudo-opacity;
stroke: @text-tertiary-color;
}
}
&.blurred {
opacity: @node-opacity-blurred;
}
}
.edge {
transition: opacity .5s @base-ease;
&.blurred {
opacity: @edge-opacity-blurred;
}
&.focused {
animation: focusing 1.5s ease-in-out;
}
.link {
stroke: @text-secondary-color;
stroke-width: @edge-link-stroke-width;
fill: none;
stroke-opacity: @edge-opacity;
}
.shadow {
stroke: @weave-blue;
stroke-width: 10px;
fill: none;
stroke-opacity: 0;
}
&.highlighted {
.shadow {
stroke-opacity: @edge-highlight-opacity;
}
}
}
.stack .shape .highlighted {
display: none;
}
.stack .onlyHighlight .shape {
.border { display: none; }
.shadow { display: none; }
.node { display: none; }
.highlighted { display: inline; }
}
.stack .shape .metric-fill {
display: none;
}
.shape {
/* cloud paths have stroke-width set dynamically */
&:not(.shape-cloud) .border {
stroke-width: @node-border-stroke-width;
fill: @background-color;
transition: stroke-opacity 0.333s @base-ease, fill 0.333s @base-ease;
stroke-opacity: 1;
}
&.metrics .border {
fill: @background-lighter-color;
stroke-opacity: 0.3;
}
.metric-fill {
stroke: none;
fill: #A0BE7E;
fill-opacity: 0.7;
}
.shadow {
stroke: none;
fill: @background-lighter-color;
}
.node {
fill: @text-color;
stroke: @background-lighter-color;
stroke-width: 2px;
}
text {
font-size: 12px;
dominant-baseline: middle;
text-anchor: middle;
}
.highlighted {
fill: @weave-blue;
fill-opacity: @node-highlight-fill-opacity;
stroke: @weave-blue;
stroke-width: @node-highlight-stroke-width;
stroke-opacity: @node-highlight-stroke-opacity;
}
}
.stack .shape .border {
stroke-width: @node-border-stroke-width - 0.5;
}
}
.details {
&-wrapper {
position: fixed;
z-index: 1024;
right: @details-window-padding-left;
top: 24px;
bottom: 48px;
width: @details-window-width;
transition: transform 0.33333s cubic-bezier(0,0,0.21,1);
}
}
.node-details {
height: 100%;
background-color: rgba(255, 255, 255, 0.86);
display: flex;
flex-flow: column;
margin-bottom: 12px;
padding-bottom: 2px;
border-radius: 2px;
background-color: #fff;
.shadow-2;
&:last-child {
margin-bottom: 0;
}
&-tools-wrapper {
position: relative;
}
&-tools {
position: absolute;
top: 6px;
right: 8px;
span {
.btn-opacity;
padding: 4px 5px;
margin-left: 2px;
font-size: 110%;
color: @white;
cursor: pointer;
border: 1px solid rgba(255, 255, 255, 0);
border-radius: 10%;
&:hover {
border-color: rgba(255, 255, 255, 0.6);
}
}
}
&-header {
.colorable;
&-wrapper {
padding: 36px 36px 8px 36px;
}
&-label {
color: white;
margin: 0;
width: 348px;
padding-top: 0;
}
.details-tools {
position: absolute;
top: 16px;
right: 24px;
}
&-notavailable {
background-color: @background-dark-color;
}
}
&-relatives {
margin-top: 4px;
font-size: 120%;
color: @white;
&-link {
.truncate;
.btn-opacity;
display: inline-block;
margin-right: 0.5em;
cursor: pointer;
text-decoration: underline;
opacity: @link-opacity-default;
max-width: 12em;
}
&-more {
.btn-opacity;
padding: 0 2px;
text-transform: uppercase;
cursor: pointer;
font-size: 60%;
font-weight: bold;
display: inline-block;
position: relative;
top: -5px;
}
}
&-controls {
white-space: nowrap;
padding: 8px 0;
&-wrapper {
padding: 0 36px 0 32px;
}
.node-control-button {
.btn-opacity;
padding: 6px;
margin-left: 2px;
font-size: 110%;
color: @white;
cursor: pointer;
border: 1px solid rgba(255, 255, 255, 0);
border-radius: 10%;
&:hover {
border-color: rgba(255, 255, 255, 0.6);
}
&-pending, &-pending:hover {
opacity: 0.2;
border-color: rgba(255, 255, 255, 0);
cursor: not-allowed;
}
}
&-spinner {
.hideable;
color: @white;
margin-left: 8px;
}
&-error {
.truncate;
float: right;
width: 55%;
padding-top: 6px;
text-align: left;
color: @white;
&-icon {
margin-right: 0.5em;
animation: blinking 2.0s infinite @base-ease;
}
}
}
&-content {
flex: 1;
padding: 0 36px 0 36px;
overflow-y: auto;
&-loading {
margin-top: 48px;
text-align: center;
font-size: 48px;
color: @text-tertiary-color;
}
&-section {
margin: 16px 0;
&-header {
text-transform: uppercase;
font-size: 90%;
color: @text-tertiary-color;
padding: 4px 0;
}
}
}
&-health {
&-wrapper {
display: flex;
justify-content: space-around;
align-content: center;
text-align: center;
flex-wrap: wrap;
}
&-overflow {
.btn-opacity;
flex-basis: 33%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
opacity: 0.85;
cursor: pointer;
position: relative;
padding-bottom: 16px;
&-item {
padding: 4px 8px;
line-height: 1.2;
flex-basis: 48%;
&-value {
color: @text-secondary-color;
font-size: 100%;
}
&-label {
color: @text-secondary-color;
text-transform: uppercase;
font-size: 60%;
}
}
}
&-item {
padding: 8px 16px;
width: 33%;
&-label {
color: @text-secondary-color;
text-transform: uppercase;
font-size: 80%;
}
&-value {
color: @text-secondary-color;
font-size: 150%;
padding-bottom: 0.5em;
}
}
}
&-info {
&-field {
display: flex;
align-items: baseline;
&-label {
text-align: right;
width: 30%;
color: @text-secondary-color;
padding: 0 0.5em 0 0;
white-space: nowrap;
text-transform: uppercase;
font-size: 80%;
&::after {
content: ':';
}
}
&-value {
font-size: 105%;
flex: 1;
// Now required (from chrome 48) to get overflow + flexbox behaving:
min-width: 0;
color: @text-color;
}
}
}
&-labels {
&-field {
display: flex;
align-items: baseline;
&-label {
text-align: right;
width: 50%;
color: @text-secondary-color;
padding: 0 0.5em 0 0;
white-space: nowrap;
text-transform: uppercase;
font-size: 80%;
&::after {
content: ':';
}
}
&-value {
font-size: 105%;
flex: 1;
// Now required (from chrome 48) to get overflow + flexbox behaving:
min-width: 0;
color: @text-color;
}
}
}
&-table {
width: 100%;
border-spacing: 0;
/* need fixed for truncating, but that does not extend wide columns dynamically */
table-layout: fixed;
&-wrapper {
margin: 24px -4px;
}
&-header {
text-transform: uppercase;
color: @text-tertiary-color;
font-size: 90%;
text-align: right;
cursor: pointer;
padding: 0 4px;
&-sorted {
color: @text-secondary-color;
}
&-sorter {
margin: 0 0.25em;
}
&:first-child {
margin-right: 0;
text-align: left;
}
}
&-node {
font-size: 105%;
line-height: 1.5;
&:hover {
background-color: lighten(@background-color, 5%);
}
> * {
padding: 0 4px;
}
&-link {
.btn-opacity;
text-decoration: underline;
cursor: pointer;
opacity: @link-opacity-default;
}
&-value, &-metric {
flex: 1;
margin-left: 0.5em;
text-align: right;
}
&-value-scalar {
// width: 2em;
text-align: right;
margin-right: 0.5em;
}
&-value-minor,
&-value-unit {
font-size: 95%;
color: @text-secondary-color;
}
&-value-sparkline {
> div {
display: inline-block;
}
span {
margin-left: 1em;
}
}
}
}
}
.terminal {
&-app {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: flex;
flex-flow: column;
}
&-embedded {
z-index: 512;
position: fixed;
top: 24px;
bottom: 48px;
left: 36px;
right: (@details-window-width + @details-window-padding-left + 10px);
}
&-wrapper {
position: absolute;
bottom: 0;
top: 0;
left: 0;
right: 0;
border: 0px solid #000000;
border-radius: 4px;
color: #f0f0f0;
font-family: @mono-font;
.shadow-2;
}
&-header {
.truncate;
text-align: center;
color: @white;
height: @terminal-header-height;
padding: 8px 24px;
background-color: @text-color;
position: relative;
&-title {
cursor: default;
}
&-tools {
position: absolute;
right: 8px;
top: 6px;
&-icon {
.palable;
padding: 4px 5px;
color: @white;
cursor: pointer;
opacity: 0.7;
border: 1px solid rgba(255, 255, 255, 0);
border-radius: 10%;
&:hover {
opacity: 1;
border-color: rgba(255, 255, 255, 0.6);
}
}
}
}
&-embedded &-inner { top: @terminal-header-height; }
&-app &-inner { top: 0; }
&-inner {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.93);
padding: 8px;
border-radius: 0 0 2px 2px;
.terminal {
background-color: transparent !important;
}
}
&-status-bar {
font-family: @base-font;
position: absolute;
bottom: 16px;
right: 16px;
width: 50%;
padding: 16px 16px;
opacity: 0.8;
border-radius: 4px;
h3 {
margin: 4px 0;
}
p {
margin: 4px 0;
color: @white;
}
.link {
text-transform: uppercase;
font-weight: bold;
cursor: pointer;
float: right;
}
}
&-cursor {
color: #000;
background: #f0f0f0;
}
}
.terminal-inactive .terminal-cursor {
visibility: hidden;
}
.metric {
&-unit {
padding-left: 0.25em;
}
}
.show-more {
.btn-opacity;
border-top: 1px dotted @border-light-color;
padding: 0px 0;
margin-top: 4px;
text-align: right;
text-transform: uppercase;
cursor: pointer;
color: @text-secondary-color;
font-size: 90%;
&-icon {
color: @text-tertiary-color;
font-size: 120%;
position: relative;
top: 1px;
}
}
.status {
text-transform: uppercase;
padding: 2px 12px;
border-radius: @border-radius;
color: @text-secondary-color;
display: inline-block;
&-icon {
font-size: 1rem;
position: relative;
top: 0.125rem;
margin-right: 0.25rem;
}
&.status-loading {
animation: blinking 2.0s infinite @base-ease;
text-transform: none;
color: @text-color;
}
}
.topology-option, .metric-selector {
color: @text-secondary-color;
margin: 6px 0;
&:last-child {
margin-bottom: 0;
}
.fa {
margin-left: 4px;
color: darkred;
}
&-wrapper {
border-radius: @border-radius;
border: 1px solid @background-darker-color;
display: inline-block;
}
&-action {
.btn-opacity;
padding: 3px 12px;
cursor: pointer;
display: inline-block;
&-selected, &:hover {
color: @text-darker-color;
background-color: @background-darker-color;
}
&:first-child {
border-left: none;
border-top-left-radius: @border-radius;
border-bottom-left-radius: @border-radius;
}
&:last-child {
border-top-right-radius: @border-radius;
border-bottom-right-radius: @border-radius;
}
}
}
.topology-option {
&-action {
&-selected {
cursor: default;
}
}
}
.sidebar {
position: fixed;
bottom: 16px;
left: 16px;
font-size: .7rem;
}
@keyframes focusing {
0% {
opacity: 0;
} 33% {
opacity: 0.2;
} 100% {
opacity: 1;
}
}
@keyframes blinking {
0%, 100% {
opacity: 1.0;
} 50% {
opacity: 0.5;
}
}
//
// Debug panel!
//
.debug-panel {
.shadow-2;
background-color: #fff;
top: 80px;
position: absolute;
padding: 10px;
left: 10px;
z-index: 10000;
opacity: 0.3;
&:hover {
opacity: 1;
}
table {
display: inline-block;
border-collapse: collapse;
margin: 4px 2px;
td {
width: 10px;
height: 10px;
}
}
}