diff --git a/client/app/styles/_base.scss b/client/app/styles/_base.scss new file mode 100644 index 0000000000..22601a7d83 --- /dev/null +++ b/client/app/styles/_base.scss @@ -0,0 +1,1849 @@ +@import '~xterm/dist/xterm.css'; +@import '~font-awesome/scss/font-awesome.scss'; + +@font-face { + font-family: "Roboto"; + src: url("../../node_modules/materialize-css/fonts/roboto/Roboto-Regular.woff2"), + url("../../node_modules/materialize-css/fonts/roboto/Roboto-Regular.woff"), + url("../../node_modules/materialize-css/fonts/roboto/Roboto-Regular.ttf"); +} + +.browsehappy { + margin: 0.2em 0; + background: #ccc; + color: #000; + padding: 0.2em 0; +} + +/* 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; +} + +.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 { + @extend .palable; + opacity: $btn-opacity-default; + &-selected { + opacity: $btn-opacity-selected; + } + &:hover { + opacity: $btn-opacity-hover; + } +} + +.hide { + opacity: 0; +} + +.scope-app { + -webkit-font-smoothing: antialiased; + background: $body-background-color; + bottom: 0; + color: $text-color; + font-family: $base-font; + font-size: 13px; + height: 100%; + left: 0; + line-height: 150%; + margin: 0; + overflow: auto; + position: fixed; + right: 0; + top: 0; + width: 100%; + + * { + box-sizing: border-box; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + } + *:before, + *:after { + box-sizing: border-box; + } + + 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; + } +} + +.header { + pointer-events: none; + + position: absolute; + top: 32px; + width: 100%; + height: 80px; + z-index: 20; + display: flex; + + .logo { + margin: -10px 0 0 64px; + height: 64px; + width: 250px; + } +} + +.footer { + padding: 5px; + position: absolute; + bottom: 11px; + right: 43px; + color: $text-tertiary-color; + background-color: fade-out($background-average-color, .1); + font-size: 0.7rem; + display: flex; + + a { + color: $text-secondary-color; + @extend .btn-opacity; + cursor: pointer; + } + + &-status { + margin-right: 1em; + } + + &-label { + text-transform: uppercase; + margin: 0 0.25em; + } + + &-versionupdate { + margin-right: 0.5em; + text-transform: uppercase; + } + + &-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; + } + + .tooltip { + // above everything + z-index: 20000; + } +} + +.topologies { + margin: 8px 4px; + 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; + pointer-events: all; + + color: $text-secondary-color; + @extend .btn-opacity; + cursor: pointer; + padding: 4px 8px; + border-radius: $border-radius; + opacity: 0.9; + margin-bottom: 3px; + border: 1px solid transparent; + + &-active, &:hover { + color: $text-color; + background-color: $background-darker-secondary-color; + } + + &-active { + opacity: 0.85; + } + + &-matched { + border-color: $weave-blue; + } + + } + + .topologies-sub-item { + padding: 2px 8px; + } + +} + +.nodes-chart { + + &-error, &-loading { + @extend .hideable; + pointer-events: none; + position: absolute; + left: 50%; + top: 50%; + margin-left: -16.5%; + margin-top: -275px; + color: $text-secondary-color; + width: 33%; + height: 550px; + + .heading { + font-size: 125%; + } + + &-icon { + text-align: center; + opacity: 0.25; + font-size: 320px; + } + } + + &-loading &-error-icon-container { + animation: blinking 2.0s infinite $base-ease; + } + + &-loading { + text-align: center; + } + + svg { + @extend .hideable; + position: absolute; + top: 0px; + } + + .logo { + display: none; + } + + svg.exported { + .logo { + display: inline; + } + } + + text { + font-family: $base-font; + fill: $text-secondary-color; + } + + .nodes-chart-nodes > .node { + transition: opacity .5s $base-ease; + text-align: center; + + .node-network { + // stroke: $background-lighter-color; + // stroke-width: 4px; + } + + .node-sublabel { + line-height: 125%; + } + + .node-label { + color: $text-color; + } + + .node-label-wrapper { + // + // Base line height doesn't hop across foreignObject =/ + // + line-height: 150%; + + // + // inline-block so wrapper is only as wide as content. + // + display: inline-block; + + // + // - inline-block gets a different baseline depending on overflow value + // - this element gets its overflow value changed sometimes. + // - explicitly set the baseline so the text doesn't jump up and down. + // http://stackoverflow.com/questions/9273016 + // + vertical-align: top; + + cursor: pointer; + } + + .node-sublabel { + color: $text-secondary-color; + font-size: 0.85em; + } + + .node-label, .node-sublabel { + + span { + border-radius: 2px; + } + span:not(.match) { + padding: 0 0.25em; + background-color: $label-background-color; + } + span:empty { + padding: 0; + } + } + .matched-results { + background-color: $label-background-color; + } + + &.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; + } + + &.matched .shape { + animation: throb 0.5s $base-ease; + } + + .node-label, .node-sublabel { + text-align: center; + } + + .match { + background-color: lighten(rgba(0, 210, 255, 0.5), 30%); + border: 1px solid $weave-blue; + } + } + + .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 { + transform: scale(1); + cursor: pointer; + + /* 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; + } + +} + +.matched-results { + text-align: center; + + &-match { + font-size: 0.8em; + + &-wrapper { + display: inline-block; + margin: 1px; + padding: 2px 4px; + background-color: fade-out($weave-blue, .9); + } + + &-label { + color: $text-secondary-color; + margin-right: 0.5em; + } + } + + &-more { + text-transform: uppercase; + font-size: 0.7em; + color: darken($weave-blue, 10%); + margin-top: -2px; + } +} + +.details { + &-wrapper { + position: fixed; + display: flex; + z-index: 1024; + right: $details-window-padding-left; + top: 24px; + bottom: 48px; + transition: transform 0.33333s cubic-bezier(0,0,0.21,1); + } +} + +.node-details { + height: 100%; + width: $details-window-width; + 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; + @extend .shadow-2; + // keep node-details above the terminal. + z-index: 2; + + &:last-child { + margin-bottom: 0; + } + + &-tools-wrapper { + position: relative; + } + + + &-tools { + position: absolute; + top: 6px; + right: 8px; + + + > span { + @extend .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: 4px; + + span { + font-family: $base-font; + font-size: 0.9em; + margin-left: 4px; + + span { + font-size: 1em; + margin-left: 0; + text-transform: uppercase; + } + } + + &:hover { + border-color: rgba(255, 255, 255, 0.6); + } + } + } + + .match { + background-color: fade-out($weave-blue, .7); + border: 1px solid $weave-blue; + } + + &-header { + @extend .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 { + @extend .truncate; + @extend .btn-opacity; + display: inline-block; + margin-right: 0.5em; + cursor: pointer; + text-decoration: underline; + opacity: $link-opacity-default; + max-width: 12em; + } + + &-more { + @extend .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 { + color: $white; + } + + &-spinner { + @extend .hideable; + color: $white; + margin-left: 8px; + } + + &-error { + @extend .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 { + @extend .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; + } + } + } + + &-property-list { + &-controls { + margin-left: -4px; + } + + &-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; + } + } + } + + &-generic-table { + width: 100%; + + tr { + display: flex; + th, td { + padding: 0 5px; + } + } + } + + &-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; + } + } + + tbody { + position: relative; + + .min-height-constraint { + position: absolute; + width: 0 !important; + opacity: 0; + top: 0; + } + } + + &-node { + font-size: 105%; + line-height: 1.5; + + &:hover, &.selected { + background-color: lighten($background-color, 5%); + } + + > * { + padding: 0 4px; + } + + &-link { + @extend .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; + } + } + + } + } +} + +// This part sets the styles only for the 'real' node details table, not applying +// them to the nodes grid, because there we control hovering from the JS. +// NOTE: Maybe it would be nice to separate the class names between the two places +// where node tables are used - i.e. it doesn't make sense that node-details-table +// can also refer to the tables in the nodes grid. +.details-wrapper .node-details-table { + &-node { + &:hover, &.selected { + background-color: lighten($background-color, 5%); + } + } +} + +.node-control-button { + @extend .btn-opacity; + padding: 6px; + margin-left: 2px; + font-size: 110%; + color: $text-secondary-color; + 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; + } +} + +.terminal { + + &-app { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + display: flex; + flex-flow: column; + } + + &-embedded { + position: relative; + // shadow of animation-wrapper is 10px, let it fit in here without being + // overflow hiddened. + flex: 1; + overflow-x: hidden; + } + + &-animation-wrapper { + position: absolute; + // some room for the drop shadow. + top: 10px; + left: 10px; + bottom: 10px; + right: 0; + transition: transform 0.5s cubic-bezier(0.230, 1.000, 0.320, 1.000); + @extend .shadow-2; + } + + &-wrapper { + width: 100%; + height: 100%; + border: 0px solid #000000; + color: #f0f0f0; + } + + &-header { + @extend .truncate; + color: $white; + height: $terminal-header-height; + padding: 8px 24px; + background-color: $text-color; + position: relative; + font-size: 14px; + line-height: 28px; + border-radius: 4px 0 0 0; + + &-title { + cursor: default; + } + + &-tools { + position: absolute; + right: 8px; + top: 6px; + + &-item, &-item-icon { + @extend .palable; + padding: 4px 5px; + color: $white; + cursor: pointer; + opacity: 0.7; + border: 1px solid rgba(255, 255, 255, 0); + border-radius: 10%; + + font-size: 0.8em; + font-weight: bold; + text-transform: uppercase; + + &:hover { + opacity: 1; + border-color: rgba(255, 255, 255, 0.6); + } + } + + &-item-icon { + font-size: 1em; + } + } + } + + &-embedded &-inner { top: $terminal-header-height; } + &-app &-inner { top: 0; } + &-inner { + cursor: text; + font-family: $mono-font; + position: absolute; + bottom: 0; + left: 0; + right: 0; + background-color: black; + padding: 8px; + border-radius: 0 0 0 4px; + + .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; + } + + &-message { + 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 { + @extend .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; + } +} + +.plugins { + margin-right: 0.5em; + + &-label { + text-transform: uppercase; + margin-right: 0.25em; + } + + &-plugin { + cursor: default; + } + + &-plugin + &-plugin:before { + content: ', '; + } + + &-plugin-icon { + top: 1px; + position: relative; + font-size: 120%; + margin-right: 2px; + } + + .error { + animation: blinking 2.0s 60 $base-ease; // blink for 2 minute; + color: $text-secondary-color; + } + + &-empty { + opacity: $text-secondary-color; + } +} + +.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 150 $base-ease; // keep blinking for 5 minutes + text-transform: none; + color: $text-color; + } +} + +.topology-option, .metric-selector, .network-selector, .grid-mode-selector { + color: $text-secondary-color; + margin: 6px 0; + + &:last-child { + margin-bottom: 0; + } + + .fa { + margin-left: 4px; + color: darkred; + } + + &-wrapper { + pointer-events: all; + border-radius: $border-radius; + border: 1px solid $background-darker-color; + display: inline-block; + } + + &-action { + @extend .btn-opacity; + padding: 3px 12px; + cursor: pointer; + display: inline-block; + background-color: $background-color; + + &-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; + } + } +} + +.grid-mode-selector { + + margin-top: 8px; + margin-left: 8px; + min-width: 161px; + + &-wrapper { + pointer-events: all; + border-color: $background-darker-secondary-color; + overflow: hidden; + } + + &:first-child, + &:last-child { + .grid-mode-selector-action { + border-radius: 0; + } + } + + &-action { + background-color: transparent; + text-transform: uppercase; + + &-selected, &:hover { + background-color: $background-darker-secondary-color; + } + } +} + +.topology-option { + &-action { + &-selected { + cursor: default; + } + } +} + +.grid-mode-selector .fa { + margin-right: 4px; + margin-left: 0; + color: $text-secondary-color; +} + +.network-selector-action { + border-top: 3px solid transparent; + border-bottom: 3px solid $background-dark-color; +} + +.warning { + display: inline-block; + cursor: pointer; + border: 1px dashed transparent; + text-transform: none; + border-radius: $border-radius; + margin-left: 4px; + + &-wrapper { + display: flex; + } + + &-text { + display: inline-block; + color: $text-secondary-color; + padding-left: 0.5em; + } + + &-icon { + @extend .btn-opacity; + } + + &-expanded { + margin-left: 0; + padding: 2px 4px; + border-color: $text-tertiary-color; + } + + &-expanded &-icon { + position: relative; + top: 4px; + left: 2px; + } + +} + +.sidebar { + position: fixed; + bottom: 12px; + left: 12px; + padding: 4px; + font-size: .7rem; + border-radius: 8px; + border: 1px solid transparent; + pointer-events: none; +} + +.sidebar-gridmode { + background-color: #e9e9f1; + border-color: $background-darker-color; + opacity: 0.9; +} + +.search { + pointer-events: all; + + display: inline-block; + position: relative; + width: 10em; + transition: width 0.3s 0s $base-ease; + + &-wrapper { + flex: 0 1 20%; + margin: 8px; + text-align: right; + } + + &-disabled { + opacity: 0.5; + cursor: disabled; + } + + &-hint { + font-size: 0.7rem; + position: absolute; + padding: 0 1em; + color: $text-tertiary-color; + top: 0; + opacity: 0; + transition: transform 0.3s 0s $base-ease, opacity 0.3s 0s $base-ease; + text-align: left; + } + + &-help-link { + @extend .btn-opacity; + cursor: pointer; + font-size: 150%; + } + + &-label { + position: absolute; + pointer-events: none; + user-select: none; + top: 0; + left: 4px; + z-index: 1024; + padding: 4px; + color: $text-secondary-color; + + &-icon { + margin-right: 0.5em; + } + + &-hint { + font-size: 0.8rem; + text-transform: uppercase; + transition: opacity 0.3s 0.5s $base-ease; + opacity: 1; + } + } + + &-input { + overflow: hidden; + background: #fff; + position: relative; + z-index: 1; + display: flex; + border-radius: $border-radius; + width: 100%; + border: $search-border-width solid $search-border-color; + padding: 2px 4px; + text-align: left; + flex-wrap: wrap; + + &-field { + font-size: 0.8rem; + line-height: 150%; + position: relative; + padding: 1px 4px 1px 1.5em; + border: none; + border-radius: 0; + background: transparent; + color: $text-color; + width: 100px; + + &:focus { + outline: none; + } + } + } + + &-focused &-label-hint, + &-pinned &-label-hint, + &-filled &-label-hint { + transition: opacity 0.1s 0s $base-ease; + opacity: 0; + } + + &-focused &-hint, + &-filled &-hint, + &-pinned &-hint { + opacity: 1; + transform: translate3d(0, 2.75em, 0); + transition: transform 0.3s 0.3s $base-ease, opacity 0.3s 0.3s $base-ease; + } + + &-focused &-input-field, + &-filled &-input-field, + &-pinned &-input-field { + flex: 1; + } + + &-focused, + &-filled, + &-pinned { + width: 100%; + } + + &-matched &-input { + border-color: $weave-blue; + } + +} + +.search-item { + background-color: fade-out($weave-blue, .2); + border-radius: $border-radius / 2; + margin: 1px 0 1px 1.5em; + display: inline-block; + + & + .search-item { + margin-left: 4px; + } + + & + .search-input-field { + padding-left: 4px; + } + + &-label { + padding: 2px 4px; + } + + &-icon { + @extend .btn-opacity; + padding: 2px 4px 2px 2px; + cursor: pointer; + font-size: 80%; + position: relative; + top: -1px; + } +} + +@keyframes focusing { + 0% { + opacity: 0; + } 33% { + opacity: 0.2; + } 100% { + opacity: 1; + } +} + +@keyframes blinking { + 0%, 50%, 100% { + opacity: 1.0; + } 25% { + opacity: 0.5; + } +} + +@keyframes throb { + 0%, 50%, 100% { + transform: scale(1); + } 25%, 75% { + transform: scale(1.2); + } +} + +// +// Help panel! +// + +.help-panel { + z-index: 2048; + background-color: white; + @extend .shadow-2; + display: flex; + position: relative; + + &-wrapper { + position: absolute; + width: 100%; + height: 100%; + + display: flex; + justify-content: center; + align-items: flex-start; + } + + &-header { + background-color: $weave-blue; + padding: 12px 24px; + color: white; + + h2 { + margin: 0; + text-transform: uppercase; + font-size: 125%; + } + } + + &-tools { + position: absolute; + top: 6px; + right: 8px; + + span { + @extend .btn-opacity; + padding: 4px 5px; + margin-left: 2px; + font-size: 110%; + color: #8383ac; + cursor: pointer; + border: 1px solid rgba(131, 131, 172, 0); + border-radius: 10%; + + &:hover { + border-color: rgba(131, 131, 172, 0.6); + } + } + + } + + &-main { + display: flex; + padding: 12px 36px 36px 36px; + flex-direction: row; + align-items: stretch; + + h2 { + text-transform: uppercase; + line-height: 150%; + font-size: 125%; + color: #8383ac; + padding: 4px 0; + border-bottom: 1px solid rgba(131, 131, 172, 0.1); + } + + h3 { + text-transform: uppercase; + font-size: 90%; + color: #8383ac; + padding: 4px 0; + } + + p { + margin: 0; + } + } + + &-shortcuts { + margin-right: 36px; + + &-shortcut { + kbd { + display: inline-block; + padding: 3px 5px; + font-size: 11px; + line-height: 10px; + color: #555; + vertical-align: middle; + background-color: #fcfcfc; + border: solid 1px #ccc; + border-bottom-color: #bbb; + border-radius: 3px; + box-shadow: inset 0 -1px 0 #bbb; + } + div.key { + width: 80px; + display: inline-block; + } + div.label { + display: inline-block; + } + } + } + + &-search { + margin-right: 36px; + + &-row { + display: flex; + flex-direction: row; + + &-term { + flex: 1; + color: #5b5b88; + } + + &-term-label { + flex: 1; + b { + color: #5b5b88; + } + } + } + } + + &-fields { + display: flex; + flex-direction: column; + + &-current-topology { + text-transform: uppercase; + color: #8383ac; + } + + &-fields { + display: flex; + align-items: stretch; + + &-column { + display: flex; + flex-direction: column; + flex: 1; + margin-right: 12px; + + &-content { + overflow: auto; + // 160px for top and bottom margins and the rest of the help window + // is about 160px too. + // Notes: Firefox gets a bit messy if you try and bubble + // heights + overflow up (min-height issue + still doesn't work v.well), + // so this is a bit of a hack. + max-height: "calc(100vh - 160px - 160px - 160px)"; + } + } + } + } +} + +// +// Debug panel! +// + +.debug-panel { + @extend .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; + } + } +} + +// +// Nodes grid. +// + +.nodes-grid { + + tr { + border-radius: 6px; + } + + &-label-minor { + opacity: 0.7; + } + + &-id-column { + margin: -3px -4px; + padding: 2px 4px; + display: flex; + div { + flex: 1; + } + } + + .node-details-table-wrapper-wrapper { + + flex: 1; + display: flex; + flex-direction: row; + width: 100%; + + .node-details-table-wrapper { + margin: 0; + flex: 1; + } + + .nodes-grid-graph { + position: relative; + margin-top: 24px; + } + + .node-details-table-node > * { + padding: 3px 4px; + } + + // Keeping the row height fixed is important for locking the rows on hover. + .node-details-table-node, thead tr { + height: 28px; + } + + tr:nth-child(even) { + background: $background-color; + } + + tbody tr { + border: 1px solid transparent; + border-radius: 4px; + cursor: pointer; + } + + // We fully control hovering of the grid rows from JS, + // because we want consistent behaviour between the + // visual and row locking logic that happens on hover. + tbody tr.selected, tbody tr.focused { + background-color: #d7ecf5; + border: 1px solid $weave-blue; + } + + tbody tr.selected { + // box-shadow: 0 4px 2px -2px rgba(0, 0, 0, 0.16); + } + } + + .scroll-body { + + table { + border-bottom: 1px solid #ccc; + } + + thead { + // osx scrollbar width: 0 + // linux scrollbar width: 16 + // avg scrollbar width: 8 + padding-right: 8px; + } + + thead, tbody tr { + display: table; + width: 100%; + table-layout: fixed; + } + + tbody:after { + content: ''; + display: block; + // height of the controls so you can scroll the last row up above them + // and have a good look. + height: 140px; + } + + thead { + box-shadow: 0 4px 2px -2px rgba(0, 0, 0, 0.16); + border-bottom: 1px solid #aaa; + } + + tbody { + display: block; + overflow-y: scroll; + } + } +} + +.troubleshooting-menu { + display: flex; + position: relative; + + &-wrapper { + height: 100%; + width: 100%; + align-items: center; + display: flex; + justify-content: center; + position: absolute; + } + + &-content { + position: relative; + background-color: $white; + padding: 20px; + @extend .shadow-2; + z-index: 2048; + } + + &-item { + height: 40px; + } + + .fa { + width: 20px; + text-align: center; + margin-right: 10px; + } + + .fa-close { + width: 25px; + } +} diff --git a/client/app/styles/_contrast-overrides.scss b/client/app/styles/_contrast-overrides.scss new file mode 100644 index 0000000000..adcc592566 --- /dev/null +++ b/client/app/styles/_contrast-overrides.scss @@ -0,0 +1,36 @@ +@import "variables"; +$background-color: lighten($primary-color, 75%); +$background-lighter-color: lighten($background-color, 10%); +$background-darker-color: darken($background-color, 20%); +$background-darker-secondary-color: darken($background-color, 15%); +$background-dark-color: $primary-color; +$text-color: black; +$text-secondary-color: lighten($text-color, 10%); +$text-tertiary-color: lighten($text-color, 20%); +$border-light-color: lighten($text-color, 50%); +$text-darker-color: darken($text-color, 20%); +$white: white; + +$node-opacity-blurred: 0.6; +$node-highlight-fill-opacity: 0.3; +$node-highlight-stroke-opacity: 0.5; +$node-highlight-stroke-width: 3px; +$node-border-stroke-width: 5px; +$node-pseudo-opacity: 1; +$edge-highlight-opacity: 0.3; +$edge-opacity-blurred: 0; +$edge-opacity: 0.5; +$edge-link-stroke-width: 3px; + +$btn-opacity-default: 1; +$btn-opacity-hover: 1; +$btn-opacity-selected: 1; + +$link-opacity-default: 1; + +$search-border-color: $background-darker-color; +$search-border-width: 2px; + +/* specific elements */ +$body-background-color: #FFF; +$label-background-color: #FFF; diff --git a/client/app/styles/_variables.scss b/client/app/styles/_variables.scss new file mode 100644 index 0000000000..8e28a72e2a --- /dev/null +++ b/client/app/styles/_variables.scss @@ -0,0 +1,55 @@ +$fa-font-path: "~font-awesome/fonts"; +/* 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-average-color: mix($background-color, $background-lighter-color); +$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: 44px; + +$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; + +$search-border-color: transparent; +$search-border-width: 1px; + +/* specific elements */ +$body-background-color: linear-gradient(30deg, $background-color 0%, $background-lighter-color 100%); +$label-background-color: fade-out($background-average-color, .3); diff --git a/client/app/styles/contrast.scss b/client/app/styles/contrast.scss index d2674ebe08..2862d38423 100644 --- a/client/app/styles/contrast.scss +++ b/client/app/styles/contrast.scss @@ -1,37 +1,3 @@ -@import "main"; - -$background-color: lighten($primary-color, 75%); -$background-lighter-color: lighten($background-color, 10%); -$background-darker-color: darken($background-color, 20%); -$background-darker-secondary-color: darken($background-color, 15%); -$background-dark-color: $primary-color; -$text-color: black; -$text-secondary-color: lighten($text-color, 10%); -$text-tertiary-color: lighten($text-color, 20%); -$border-light-color: lighten($text-color, 50%); -$text-darker-color: darken($text-color, 20%); -$white: white; - -$node-opacity-blurred: 0.6; -$node-highlight-fill-opacity: 0.3; -$node-highlight-stroke-opacity: 0.5; -$node-highlight-stroke-width: 3px; -$node-border-stroke-width: 5px; -$node-pseudo-opacity: 1; -$edge-highlight-opacity: 0.3; -$edge-opacity-blurred: 0; -$edge-opacity: 0.5; -$edge-link-stroke-width: 3px; - -$btn-opacity-default: 1; -$btn-opacity-hover: 1; -$btn-opacity-selected: 1; - -$link-opacity-default: 1; - -$search-border-color: $background-darker-color; -$search-border-width: 2px; - -/* specific elements */ -$body-background-color: #FFF; -$label-background-color: #FFF; +@import "variables"; +@import "contrast-overrides"; +@import "base"; diff --git a/client/app/styles/main.scss b/client/app/styles/main.scss index 62be5fa873..2f446a301e 100644 --- a/client/app/styles/main.scss +++ b/client/app/styles/main.scss @@ -1,1907 +1,2 @@ -// Settings -$fa-font-path: "~font-awesome/fonts"; -@import '~xterm/dist/xterm.css'; -@import '~font-awesome/scss/font-awesome.scss'; - -@font-face { - font-family: "Roboto"; - src: url("../../node_modules/materialize-css/fonts/roboto/Roboto-Regular.woff2"), - url("../../node_modules/materialize-css/fonts/roboto/Roboto-Regular.woff"), - url("../../node_modules/materialize-css/fonts/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-average-color: mix($background-color, $background-lighter-color); -$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: 44px; - -$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; - -$search-border-color: transparent; -$search-border-width: 1px; - -/* specific elements */ -$body-background-color: linear-gradient(30deg, $background-color 0%, $background-lighter-color 100%); -$label-background-color: fade-out($background-average-color, .3); - - -/* 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; -} - -.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 { - @extend .palable; - opacity: $btn-opacity-default; - &-selected { - opacity: $btn-opacity-selected; - } - &:hover { - opacity: $btn-opacity-hover; - } -} - -.hide { - opacity: 0; -} - -.scope-app { - -webkit-font-smoothing: antialiased; - background: $body-background-color; - bottom: 0; - color: $text-color; - font-family: $base-font; - font-size: 13px; - height: 100%; - left: 0; - line-height: 150%; - margin: 0; - overflow: auto; - position: fixed; - right: 0; - top: 0; - width: 100%; - - * { - box-sizing: border-box; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - } - *:before, - *:after { - box-sizing: border-box; - } - - 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; - } -} - -.header { - pointer-events: none; - - position: absolute; - top: 32px; - width: 100%; - height: 80px; - z-index: 20; - display: flex; - - .logo { - margin: -10px 0 0 64px; - height: 64px; - width: 250px; - } -} - -.footer { - padding: 5px; - position: absolute; - bottom: 11px; - right: 43px; - color: $text-tertiary-color; - background-color: fade-out($background-average-color, .1); - font-size: 0.7rem; - display: flex; - - a { - color: $text-secondary-color; - @extend .btn-opacity; - cursor: pointer; - } - - &-status { - margin-right: 1em; - } - - &-label { - text-transform: uppercase; - margin: 0 0.25em; - } - - &-versionupdate { - margin-right: 0.5em; - text-transform: uppercase; - } - - &-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; - } - - .tooltip { - // above everything - z-index: 20000; - } -} - -.topologies { - margin: 8px 4px; - 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; - pointer-events: all; - - color: $text-secondary-color; - @extend .btn-opacity; - cursor: pointer; - padding: 4px 8px; - border-radius: $border-radius; - opacity: 0.9; - margin-bottom: 3px; - border: 1px solid transparent; - - &-active, &:hover { - color: $text-color; - background-color: $background-darker-secondary-color; - } - - &-active { - opacity: 0.85; - } - - &-matched { - border-color: $weave-blue; - } - - } - - .topologies-sub-item { - padding: 2px 8px; - } - -} - -.nodes-chart { - - &-error, &-loading { - @extend .hideable; - pointer-events: none; - position: absolute; - left: 50%; - top: 50%; - margin-left: -16.5%; - margin-top: -275px; - color: $text-secondary-color; - width: 33%; - height: 550px; - - .heading { - font-size: 125%; - } - - &-icon { - text-align: center; - opacity: 0.25; - font-size: 320px; - } - } - - &-loading &-error-icon-container { - animation: blinking 2.0s infinite $base-ease; - } - - &-loading { - text-align: center; - } - - svg { - @extend .hideable; - position: absolute; - top: 0px; - } - - .logo { - display: none; - } - - svg.exported { - .logo { - display: inline; - } - } - - text { - font-family: $base-font; - fill: $text-secondary-color; - } - - .nodes-chart-nodes > .node { - transition: opacity .5s $base-ease; - text-align: center; - - .node-network { - // stroke: $background-lighter-color; - // stroke-width: 4px; - } - - .node-sublabel { - line-height: 125%; - } - - .node-label { - color: $text-color; - } - - .node-label-wrapper { - // - // Base line height doesn't hop across foreignObject =/ - // - line-height: 150%; - - // - // inline-block so wrapper is only as wide as content. - // - display: inline-block; - - // - // - inline-block gets a different baseline depending on overflow value - // - this element gets its overflow value changed sometimes. - // - explicitly set the baseline so the text doesn't jump up and down. - // http://stackoverflow.com/questions/9273016 - // - vertical-align: top; - - cursor: pointer; - } - - .node-sublabel { - color: $text-secondary-color; - font-size: 0.85em; - } - - .node-label, .node-sublabel { - - span { - border-radius: 2px; - } - span:not(.match) { - padding: 0 0.25em; - background-color: $label-background-color; - } - span:empty { - padding: 0; - } - } - .matched-results { - background-color: $label-background-color; - } - - &.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; - } - - &.matched .shape { - animation: throb 0.5s $base-ease; - } - - .node-label, .node-sublabel { - text-align: center; - } - - .match { - background-color: lighten(rgba(0, 210, 255, 0.5), 30%); - border: 1px solid $weave-blue; - } - } - - .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 { - transform: scale(1); - cursor: pointer; - - /* 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; - } - -} - -.matched-results { - text-align: center; - - &-match { - font-size: 0.8em; - - &-wrapper { - display: inline-block; - margin: 1px; - padding: 2px 4px; - background-color: fade-out($weave-blue, .9); - } - - &-label { - color: $text-secondary-color; - margin-right: 0.5em; - } - } - - &-more { - text-transform: uppercase; - font-size: 0.7em; - color: darken($weave-blue, 10%); - margin-top: -2px; - } -} - -.details { - &-wrapper { - position: fixed; - display: flex; - z-index: 1024; - right: $details-window-padding-left; - top: 24px; - bottom: 48px; - transition: transform 0.33333s cubic-bezier(0,0,0.21,1); - } -} - -.node-details { - height: 100%; - width: $details-window-width; - 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; - @extend .shadow-2; - // keep node-details above the terminal. - z-index: 2; - - &:last-child { - margin-bottom: 0; - } - - &-tools-wrapper { - position: relative; - } - - - &-tools { - position: absolute; - top: 6px; - right: 8px; - - - > span { - @extend .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: 4px; - - span { - font-family: $base-font; - font-size: 0.9em; - margin-left: 4px; - - span { - font-size: 1em; - margin-left: 0; - text-transform: uppercase; - } - } - - &:hover { - border-color: rgba(255, 255, 255, 0.6); - } - } - } - - .match { - background-color: fade-out($weave-blue, .7); - border: 1px solid $weave-blue; - } - - &-header { - @extend .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 { - @extend .truncate; - @extend .btn-opacity; - display: inline-block; - margin-right: 0.5em; - cursor: pointer; - text-decoration: underline; - opacity: $link-opacity-default; - max-width: 12em; - } - - &-more { - @extend .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 { - color: $white; - } - - &-spinner { - @extend .hideable; - color: $white; - margin-left: 8px; - } - - &-error { - @extend .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 { - @extend .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; - } - } - } - - &-property-list { - &-controls { - margin-left: -4px; - } - - &-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; - } - } - } - - &-generic-table { - width: 100%; - - tr { - display: flex; - th, td { - padding: 0 5px; - } - } - } - - &-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; - } - } - - tbody { - position: relative; - - .min-height-constraint { - position: absolute; - width: 0 !important; - opacity: 0; - top: 0; - } - } - - &-node { - font-size: 105%; - line-height: 1.5; - - &:hover, &.selected { - background-color: lighten($background-color, 5%); - } - - > * { - padding: 0 4px; - } - - &-link { - @extend .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; - } - } - - } - } -} - -// This part sets the styles only for the 'real' node details table, not applying -// them to the nodes grid, because there we control hovering from the JS. -// NOTE: Maybe it would be nice to separate the class names between the two places -// where node tables are used - i.e. it doesn't make sense that node-details-table -// can also refer to the tables in the nodes grid. -.details-wrapper .node-details-table { - &-node { - &:hover, &.selected { - background-color: lighten($background-color, 5%); - } - } -} - -.node-control-button { - @extend .btn-opacity; - padding: 6px; - margin-left: 2px; - font-size: 110%; - color: $text-secondary-color; - 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; - } -} - -.terminal { - - &-app { - position: fixed; - top: 0; - bottom: 0; - left: 0; - right: 0; - display: flex; - flex-flow: column; - } - - &-embedded { - position: relative; - // shadow of animation-wrapper is 10px, let it fit in here without being - // overflow hiddened. - flex: 1; - overflow-x: hidden; - } - - &-animation-wrapper { - position: absolute; - // some room for the drop shadow. - top: 10px; - left: 10px; - bottom: 10px; - right: 0; - transition: transform 0.5s cubic-bezier(0.230, 1.000, 0.320, 1.000); - @extend .shadow-2; - } - - &-wrapper { - width: 100%; - height: 100%; - border: 0px solid #000000; - color: #f0f0f0; - } - - &-header { - @extend .truncate; - color: $white; - height: $terminal-header-height; - padding: 8px 24px; - background-color: $text-color; - position: relative; - font-size: 14px; - line-height: 28px; - border-radius: 4px 0 0 0; - - &-title { - cursor: default; - } - - &-tools { - position: absolute; - right: 8px; - top: 6px; - - &-item, &-item-icon { - @extend .palable; - padding: 4px 5px; - color: $white; - cursor: pointer; - opacity: 0.7; - border: 1px solid rgba(255, 255, 255, 0); - border-radius: 10%; - - font-size: 0.8em; - font-weight: bold; - text-transform: uppercase; - - &:hover { - opacity: 1; - border-color: rgba(255, 255, 255, 0.6); - } - } - - &-item-icon { - font-size: 1em; - } - } - } - - &-embedded &-inner { top: $terminal-header-height; } - &-app &-inner { top: 0; } - &-inner { - cursor: text; - font-family: $mono-font; - position: absolute; - bottom: 0; - left: 0; - right: 0; - background-color: black; - padding: 8px; - border-radius: 0 0 0 4px; - - .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; - } - - &-message { - 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 { - @extend .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; - } -} - -.plugins { - margin-right: 0.5em; - - &-label { - text-transform: uppercase; - margin-right: 0.25em; - } - - &-plugin { - cursor: default; - } - - &-plugin + &-plugin:before { - content: ', '; - } - - &-plugin-icon { - top: 1px; - position: relative; - font-size: 120%; - margin-right: 2px; - } - - .error { - animation: blinking 2.0s 60 $base-ease; // blink for 2 minute; - color: $text-secondary-color; - } - - &-empty { - opacity: $text-secondary-color; - } -} - -.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 150 $base-ease; // keep blinking for 5 minutes - text-transform: none; - color: $text-color; - } -} - -.topology-option, .metric-selector, .network-selector, .grid-mode-selector { - color: $text-secondary-color; - margin: 6px 0; - - &:last-child { - margin-bottom: 0; - } - - .fa { - margin-left: 4px; - color: darkred; - } - - &-wrapper { - pointer-events: all; - border-radius: $border-radius; - border: 1px solid $background-darker-color; - display: inline-block; - } - - &-action { - @extend .btn-opacity; - padding: 3px 12px; - cursor: pointer; - display: inline-block; - background-color: $background-color; - - &-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; - } - } -} - -.grid-mode-selector { - - margin-top: 8px; - margin-left: 8px; - min-width: 161px; - - &-wrapper { - pointer-events: all; - border-color: $background-darker-secondary-color; - overflow: hidden; - } - - &:first-child, - &:last-child { - .grid-mode-selector-action { - border-radius: 0; - } - } - - &-action { - background-color: transparent; - text-transform: uppercase; - - &-selected, &:hover { - background-color: $background-darker-secondary-color; - } - } -} - -.topology-option { - &-action { - &-selected { - cursor: default; - } - } -} - -.grid-mode-selector .fa { - margin-right: 4px; - margin-left: 0; - color: $text-secondary-color; -} - -.network-selector-action { - border-top: 3px solid transparent; - border-bottom: 3px solid $background-dark-color; -} - -.warning { - display: inline-block; - cursor: pointer; - border: 1px dashed transparent; - text-transform: none; - border-radius: $border-radius; - margin-left: 4px; - - &-wrapper { - display: flex; - } - - &-text { - display: inline-block; - color: $text-secondary-color; - padding-left: 0.5em; - } - - &-icon { - @extend .btn-opacity; - } - - &-expanded { - margin-left: 0; - padding: 2px 4px; - border-color: $text-tertiary-color; - } - - &-expanded &-icon { - position: relative; - top: 4px; - left: 2px; - } - -} - -.sidebar { - position: fixed; - bottom: 12px; - left: 12px; - padding: 4px; - font-size: .7rem; - border-radius: 8px; - border: 1px solid transparent; - pointer-events: none; -} - -.sidebar-gridmode { - background-color: #e9e9f1; - border-color: $background-darker-color; - opacity: 0.9; -} - -.search { - pointer-events: all; - - display: inline-block; - position: relative; - width: 10em; - transition: width 0.3s 0s $base-ease; - - &-wrapper { - flex: 0 1 20%; - margin: 8px; - text-align: right; - } - - &-disabled { - opacity: 0.5; - cursor: disabled; - } - - &-hint { - font-size: 0.7rem; - position: absolute; - padding: 0 1em; - color: $text-tertiary-color; - top: 0; - opacity: 0; - transition: transform 0.3s 0s $base-ease, opacity 0.3s 0s $base-ease; - text-align: left; - } - - &-help-link { - @extend .btn-opacity; - cursor: pointer; - font-size: 150%; - } - - &-label { - position: absolute; - pointer-events: none; - user-select: none; - top: 0; - left: 4px; - z-index: 1024; - padding: 4px; - color: $text-secondary-color; - - &-icon { - margin-right: 0.5em; - } - - &-hint { - font-size: 0.8rem; - text-transform: uppercase; - transition: opacity 0.3s 0.5s $base-ease; - opacity: 1; - } - } - - &-input { - overflow: hidden; - background: #fff; - position: relative; - z-index: 1; - display: flex; - border-radius: $border-radius; - width: 100%; - border: $search-border-width solid $search-border-color; - padding: 2px 4px; - text-align: left; - flex-wrap: wrap; - - &-field { - font-size: 0.8rem; - line-height: 150%; - position: relative; - padding: 1px 4px 1px 1.5em; - border: none; - border-radius: 0; - background: transparent; - color: $text-color; - width: 100px; - - &:focus { - outline: none; - } - } - } - - &-focused &-label-hint, - &-pinned &-label-hint, - &-filled &-label-hint { - transition: opacity 0.1s 0s $base-ease; - opacity: 0; - } - - &-focused &-hint, - &-filled &-hint, - &-pinned &-hint { - opacity: 1; - transform: translate3d(0, 2.75em, 0); - transition: transform 0.3s 0.3s $base-ease, opacity 0.3s 0.3s $base-ease; - } - - &-focused &-input-field, - &-filled &-input-field, - &-pinned &-input-field { - flex: 1; - } - - &-focused, - &-filled, - &-pinned { - width: 100%; - } - - &-matched &-input { - border-color: $weave-blue; - } - -} - -.search-item { - background-color: fade-out($weave-blue, .2); - border-radius: $border-radius / 2; - margin: 1px 0 1px 1.5em; - display: inline-block; - - & + .search-item { - margin-left: 4px; - } - - & + .search-input-field { - padding-left: 4px; - } - - &-label { - padding: 2px 4px; - } - - &-icon { - @extend .btn-opacity; - padding: 2px 4px 2px 2px; - cursor: pointer; - font-size: 80%; - position: relative; - top: -1px; - } -} - -@keyframes focusing { - 0% { - opacity: 0; - } 33% { - opacity: 0.2; - } 100% { - opacity: 1; - } -} - -@keyframes blinking { - 0%, 50%, 100% { - opacity: 1.0; - } 25% { - opacity: 0.5; - } -} - -@keyframes throb { - 0%, 50%, 100% { - transform: scale(1); - } 25%, 75% { - transform: scale(1.2); - } -} - -// -// Help panel! -// - -.help-panel { - z-index: 2048; - background-color: white; - @extend .shadow-2; - display: flex; - position: relative; - - &-wrapper { - position: absolute; - width: 100%; - height: 100%; - - display: flex; - justify-content: center; - align-items: flex-start; - } - - &-header { - background-color: $weave-blue; - padding: 12px 24px; - color: white; - - h2 { - margin: 0; - text-transform: uppercase; - font-size: 125%; - } - } - - &-tools { - position: absolute; - top: 6px; - right: 8px; - - span { - @extend .btn-opacity; - padding: 4px 5px; - margin-left: 2px; - font-size: 110%; - color: #8383ac; - cursor: pointer; - border: 1px solid rgba(131, 131, 172, 0); - border-radius: 10%; - - &:hover { - border-color: rgba(131, 131, 172, 0.6); - } - } - - } - - &-main { - display: flex; - padding: 12px 36px 36px 36px; - flex-direction: row; - align-items: stretch; - - h2 { - text-transform: uppercase; - line-height: 150%; - font-size: 125%; - color: #8383ac; - padding: 4px 0; - border-bottom: 1px solid rgba(131, 131, 172, 0.1); - } - - h3 { - text-transform: uppercase; - font-size: 90%; - color: #8383ac; - padding: 4px 0; - } - - p { - margin: 0; - } - } - - &-shortcuts { - margin-right: 36px; - - &-shortcut { - kbd { - display: inline-block; - padding: 3px 5px; - font-size: 11px; - line-height: 10px; - color: #555; - vertical-align: middle; - background-color: #fcfcfc; - border: solid 1px #ccc; - border-bottom-color: #bbb; - border-radius: 3px; - box-shadow: inset 0 -1px 0 #bbb; - } - div.key { - width: 80px; - display: inline-block; - } - div.label { - display: inline-block; - } - } - } - - &-search { - margin-right: 36px; - - &-row { - display: flex; - flex-direction: row; - - &-term { - flex: 1; - color: #5b5b88; - } - - &-term-label { - flex: 1; - b { - color: #5b5b88; - } - } - } - } - - &-fields { - display: flex; - flex-direction: column; - - &-current-topology { - text-transform: uppercase; - color: #8383ac; - } - - &-fields { - display: flex; - align-items: stretch; - - &-column { - display: flex; - flex-direction: column; - flex: 1; - margin-right: 12px; - - &-content { - overflow: auto; - // 160px for top and bottom margins and the rest of the help window - // is about 160px too. - // Notes: Firefox gets a bit messy if you try and bubble - // heights + overflow up (min-height issue + still doesn't work v.well), - // so this is a bit of a hack. - max-height: "calc(100vh - 160px - 160px - 160px)"; - } - } - } - } -} - -// -// Debug panel! -// - -.debug-panel { - @extend .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; - } - } -} - -// -// Nodes grid. -// - -.nodes-grid { - - tr { - border-radius: 6px; - } - - &-label-minor { - opacity: 0.7; - } - - &-id-column { - margin: -3px -4px; - padding: 2px 4px; - display: flex; - div { - flex: 1; - } - } - - .node-details-table-wrapper-wrapper { - - flex: 1; - display: flex; - flex-direction: row; - width: 100%; - - .node-details-table-wrapper { - margin: 0; - flex: 1; - } - - .nodes-grid-graph { - position: relative; - margin-top: 24px; - } - - .node-details-table-node > * { - padding: 3px 4px; - } - - // Keeping the row height fixed is important for locking the rows on hover. - .node-details-table-node, thead tr { - height: 28px; - } - - tr:nth-child(even) { - background: $background-color; - } - - tbody tr { - border: 1px solid transparent; - border-radius: 4px; - cursor: pointer; - } - - // We fully control hovering of the grid rows from JS, - // because we want consistent behaviour between the - // visual and row locking logic that happens on hover. - tbody tr.selected, tbody tr.focused { - background-color: #d7ecf5; - border: 1px solid $weave-blue; - } - - tbody tr.selected { - // box-shadow: 0 4px 2px -2px rgba(0, 0, 0, 0.16); - } - } - - .scroll-body { - - table { - border-bottom: 1px solid #ccc; - } - - thead { - // osx scrollbar width: 0 - // linux scrollbar width: 16 - // avg scrollbar width: 8 - padding-right: 8px; - } - - thead, tbody tr { - display: table; - width: 100%; - table-layout: fixed; - } - - tbody:after { - content: ''; - display: block; - // height of the controls so you can scroll the last row up above them - // and have a good look. - height: 140px; - } - - thead { - box-shadow: 0 4px 2px -2px rgba(0, 0, 0, 0.16); - border-bottom: 1px solid #aaa; - } - - tbody { - display: block; - overflow-y: scroll; - } - } -} - -.troubleshooting-menu { - display: flex; - position: relative; - - &-wrapper { - height: 100%; - width: 100%; - align-items: center; - display: flex; - justify-content: center; - position: absolute; - } - - &-content { - position: relative; - background-color: $white; - padding: 20px; - @extend .shadow-2; - z-index: 2048; - } - - &-item { - height: 40px; - } - - .fa { - width: 20px; - text-align: center; - margin-right: 10px; - } - - .fa-close { - width: 25px; - } -} +@import "variables"; +@import "base";