refactor(GUI): CSS color-scheme (#674)

This is a big PR that extracts out a sensible set of SCSS color
variables that can be used to customise Etcher's look.

To achieve such goal, the following changes were introduced:

- Create a separate `lib/gui/scss/modules/_theme.scss` to conveniently
  hold all SCSS color variables.

- Decouple button styles from Bootstrap's `.btn`.

- Stop configuring Bootstrap colors as a whole using the SCSS variables
  it exposes and instead declare them directly in the modules that make
  use of them.

- Normalize all modal layouts into one. We had like 3 different modal
  layouts, each with their own title/body colors, etc. To simplify the
  color palette, we make use of a single modal layout everywhere.

- Remove `.progress-button--primary`. `.progress-button` is now
  "primary" by default.

- Be precise about `tick` foreground colors.

- Rename `.label-default` to `.label-inset`.

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
This commit is contained in:
Juan Cruz Viotti 2016-09-02 09:35:25 -04:00 committed by GitHub
parent 2c9c06a882
commit e1f843652b
29 changed files with 665 additions and 725 deletions

View File

@ -3,8 +3,6 @@ scss_files: 'lib/gui/scss/**/*.scss'
linters: linters:
Comment: Comment:
enabled: false enabled: false
ColorVariable:
enabled: false
ImportantRule: ImportantRule:
enabled: false enabled: false
PlaceholderInExtend: PlaceholderInExtend:

File diff suppressed because it is too large Load Diff

View File

@ -36,7 +36,8 @@ module.exports = function(ModalService, $q) {
this.open = () => { this.open = () => {
modal = ModalService.open({ modal = ModalService.open({
template: './components/drive-selector/templates/drive-selector-modal.tpl.html', template: './components/drive-selector/templates/drive-selector-modal.tpl.html',
controller: 'DriveSelectorController as modal' controller: 'DriveSelectorController as modal',
size: 'drive-selector-modal'
}); });
return modal.result; return modal.result;

View File

@ -14,10 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
.modal-drive-selector-modal .modal-content {
width: 300px;
height: 320px;
}
.component-drive-selector-body .list-group-item-footer { .component-drive-selector-body .list-group-item-footer {
margin-top: 8px; margin-top: 8px;
} }
.component-drive-selector-body .list-group-item[disabled] .list-group-item-heading {
color: darken($gray-light, 20%);
}

View File

@ -39,7 +39,7 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button class="btn btn-primary btn-block" <button class="button button-primary button-block"
ng-click="modal.closeModal()" ng-click="modal.closeModal()"
ng-disabled="!modal.state.hasDrive()">CONTINUE</button> ng-disabled="!modal.state.hasDrive()">CONTINUE</button>
</div> </div>

View File

@ -22,9 +22,6 @@
* The state of the progress bar is controller by the width, in percentage, * The state of the progress bar is controller by the width, in percentage,
* of `.progress-button__bar`. * of `.progress-button__bar`.
* *
* The current percentage also needs to be reflected in the top level
* `.progress-button` element as a `percentage` attribute, without the percentage sign.
*
* If there is an action in place, the `active` attribute must be set to `true`. * If there is an action in place, the `active` attribute must be set to `true`.
* This is useful to determine if the progress bar is paused from the point of view * This is useful to determine if the progress bar is paused from the point of view
* of the styling. * of the styling.
@ -38,7 +35,7 @@
* *
* Usage: * Usage:
* *
* <button class="progress-button progress-button--primary" percentage="50" active="true"> * <button class="progress-button" active="true">
* <span class="progress-button__content">Button text</span> * <span class="progress-button__content">Button text</span>
* <span class="progress-button__bar" style="width: 50%;"></span> * <span class="progress-button__bar" style="width: 50%;"></span>
* </button> * </button>
@ -48,55 +45,37 @@ $progress-button-stripes-width: 20px;
$progress-button-stripes-animation-duration: 1s; $progress-button-stripes-animation-duration: 1s;
.progress-button { .progress-button {
@extend .btn; @extend .button;
} @extend .button-primary;
.progress-button--primary {
@extend .btn-primary;
.progress-button__bar { .progress-button__bar {
background: lighten($brand-primary, 5); background-color: lighten($palette-theme-primary-background, 5%);
} }
$progress-button-stripes-background-color: desaturate($brand-primary, 5%);
$progress-button-stripes-color: desaturate(darken($brand-primary, 18%), 20%);
&.progress-button--striped { &.progress-button--striped {
$progress-button-stripes-background-color: desaturate($palette-theme-primary-background, 5%);
$progress-button-stripes-foreground-color: desaturate(darken($palette-theme-primary-background, 18%), 20%);
// Notice that we add `0.01` to certain gradient stop positions. // Notice that we add `0.01` to certain gradient stop positions.
// That workarounds a Chrome rendering issue where diagonal // That workarounds a Chrome rendering issue where diagonal
// lines look spiky. // lines look spiky.
// See https://github.com/resin-io/etcher/issues/472 // See https://github.com/resin-io/etcher/issues/472
background-image: -webkit-gradient(linear, 0 0, 100% 100%, background-image: -webkit-gradient(linear, 0 0, 100% 100%,
color-stop(0.25, $progress-button-stripes-color), color-stop(0.25, $progress-button-stripes-foreground-color),
color-stop(0.25 + 0.01, $progress-button-stripes-background-color), color-stop(0.25 + 0.01, $progress-button-stripes-background-color),
color-stop(0.50, $progress-button-stripes-background-color), color-stop(0.50, $progress-button-stripes-background-color),
color-stop(0.50 + 0.01, $progress-button-stripes-color), color-stop(0.50 + 0.01, $progress-button-stripes-foreground-color),
color-stop(0.75, $progress-button-stripes-color), color-stop(0.75, $progress-button-stripes-foreground-color),
color-stop(0.75 + 0.01, $progress-button-stripes-background-color), color-stop(0.75 + 0.01, $progress-button-stripes-background-color),
to($progress-button-stripes-background-color)); to($progress-button-stripes-background-color));
} }
} }
.progress-button--primary[active="true"]:active {
box-shadow: none;
background-color: $brand-success;
border-color: $btn-primary-border;
}
.progress-button[percentage="100"][active="false"] .progress-button__bar {
background-color: $brand-success;
}
.progress-button[percentage="100"][active="true"] .progress-button__bar {
background-color: $brand-warning;
}
// Prevent the button from being clickable // Prevent the button from being clickable
// when it has an active progress bar. // when it has an active progress bar.
.progress-button[active="true"] { .progress-button[active="true"] {
pointer-events: none; @extend .button-no-hover;
} }
.progress-button__content { .progress-button__content {

View File

@ -1,4 +1,4 @@
<button class="progress-button progress-button--primary" <button class="progress-button"
ng-class="{ ng-class="{
'progress-button--striped': striped && striped != 'false' 'progress-button--striped': striped && striped != 'false'
}"> }">

View File

@ -1,19 +0,0 @@
/*
* Copyright 2016 Resin.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.svg-icon[disabled] path {
fill: $color-disabled;
}

View File

@ -14,45 +14,12 @@
* limitations under the License. * limitations under the License.
*/ */
.modal-tooltip-modal { .modal-tooltip-modal .modal-body {
max-width: 50%; text-align: center;
margin: 15px;
.modal-header { color: $palette-theme-light-foreground;
border: none; background-color: darken($palette-theme-light-background, 5%);
padding: 8px;
.close { overflow: hidden;
position: absolute; word-wrap: break-word;
$modal-tooltip-close-position: 8px;
right: -($modal-tooltip-close-position + 1px);
top: -$modal-tooltip-close-position;
background-color: $gray-dark;
color: $gray-lighter;
opacity: 1;
font-weight: 200;
font-size: 150%;
padding: 0px 5px 3px;
text-shadow: none;
margin: 0;
border-radius: 50%;
}
}
.modal-content {
height: auto;
border-radius: 3px;
}
.modal-body {
@extend .text-center;
margin: 0px 15px 15px;
color: $gray-darker;
background-color: $gray-lighter;
padding: 8px;
overflow: hidden;
word-wrap: break-word;
}
} }

View File

@ -1,6 +1,6 @@
<div class="modal-header"> <div class="modal-header">
<button class="close" ng-click="modal.closeModal()">&times;</button>
<h4 class="modal-title">{{ ::modal.data.title }}</h4> <h4 class="modal-title">{{ ::modal.data.title }}</h4>
<button class="close" ng-click="modal.closeModal()">&times;</button>
</div> </div>
<div class="modal-body">{{ ::modal.data.message }}</div> <div class="modal-body">{{ ::modal.data.message }}</div>

View File

@ -20,50 +20,25 @@
} }
.modal-update-notifier { .modal-update-notifier {
width: 400px;
// Move it a bit to the top for
// aesthetic reasons
margin-top: -10px;
.modal-content {
height: 245px;
}
}
.update-notifier-modal-body__content {
@extend .text-center;
padding-bottom: 15px;
margin-bottom: 25px;
border-bottom: 1px solid $gray-lighter;
}
.update-notifier-modal-body__title {
margin-bottom: 15px;
}
.update-notifier-modal-body__menu {
display: flex;
justify-content: center;
> .btn {
flex-grow: 1;
// This causes flex children buttons to be
// equally resized independently of the
// button text length
width: 0;
.modal-body {
padding: 20px;
padding-bottom: 0;
} }
> .btn + .btn { .modal-footer .checkbox {
margin-left: 10px; color: $palette-theme-light-soft-foreground;
font-size: 11px;
margin-bottom: 0;
} }
.modal-menu {
display: flex;
& > .button {
flex-basis: 50%;
}
}
} }
.update-notifier-modal-body .checkbox {
color: lighten($gray, 25%);
font-size: 11px;
}

View File

@ -1,13 +1,16 @@
<div class="modal-body update-notifier-modal-body"> <div class="modal-header">
<div class="update-notifier-modal-body__content"> <h4 class="modal-title">New Update Available!</h4>
<h4 class="update-notifier-modal-body__title">New Update Available!</h4> </div>
<p>A new version of Etcher is available for download</p>
</div>
<div class="update-notifier-modal-body__menu"> <div class="modal-body">
<button class="btn btn-primary" <p>A new version of Etcher is available for download</p>
</div>
<div class="modal-footer">
<div class="modal-menu">
<button class="button button-primary"
os-open-external="http://etcher.io">DOWNLOAD</button> os-open-external="http://etcher.io">DOWNLOAD</button>
<button class="btn btn-default" <button class="button button-default"
ng-click="modal.closeModal()">SKIP</button> ng-click="modal.closeModal()">SKIP</button>
</div> </div>
@ -20,3 +23,4 @@
</label> </label>
</div> </div>
</div> </div>

View File

@ -19,15 +19,15 @@
</head> </head>
<body ng-app="Etcher"> <body ng-app="Etcher">
<header class="section-header"> <header class="section-header">
<button class="btn btn-link" os-open-external="https://github.com/resin-io/etcher/blob/master/SUPPORT.md"> <button class="button button-link" os-open-external="https://github.com/resin-io/etcher/blob/master/SUPPORT.md">
<span class="glyphicon glyphicon-question-sign"></span> Need Help? <span class="glyphicon glyphicon-question-sign"></span> Need Help?
</button> </button>
<button class="btn btn-link" ui-sref="settings" hide-if-state="settings"> <button class="button button-link" ui-sref="settings" hide-if-state="settings">
<span class="glyphicon glyphicon-cog"></span> <span class="glyphicon glyphicon-cog"></span>
</button> </button>
<button class="btn btn-link" ui-sref="main" show-if-state="settings"> <button class="button button-link" ui-sref="main" show-if-state="settings">
<span class="glyphicon glyphicon-chevron-left"></span> Back <span class="glyphicon glyphicon-chevron-left"></span> Back
</button> </button>
</header> </header>

View File

@ -21,21 +21,26 @@
max-width: $btn-min-width - 5px; max-width: $btn-min-width - 5px;
} }
.page-finish .label { .page-finish .title {
display: inline-block; color: $palette-theme-dark-foreground;
} }
.page-finish .monospace { .page-finish .label {
font-family: monospace; display: inline-block;
> b {
color: $palette-theme-dark-soft-foreground;
font-family: monospace;
}
} }
.page-finish .soft { .page-finish .soft {
color: $gray-light; color: $palette-theme-dark-soft-foreground;
} }
.page-finish .separator-xs { .page-finish .separator-xs {
flex-grow: 0; flex-grow: 0;
background-color: darken($color-disabled, 8%); background-color: $palette-theme-dark-soft-background;
padding: 0px; padding: 0px;
min-width: 2px; min-width: 2px;
} }

View File

@ -1,7 +1,7 @@
<div class="page-finish row around-xs"> <div class="page-finish row around-xs">
<div class="col-xs"> <div class="col-xs">
<div class="box text-center"> <div class="box text-center">
<h3><span class="tick tick--success" class="space-right-tiny"></span> Flash Complete!</h3> <h3 class="title"><span class="tick tick--success" class="space-right-tiny"></span> Flash Complete!</h3>
<p class="soft space-vertical-small" ng-show="finish.settings.get('unmountOnSuccess')">Safely ejected and ready for use</p> <p class="soft space-vertical-small" ng-show="finish.settings.get('unmountOnSuccess')">Safely ejected and ready for use</p>
<div class="row center-xs space-vertical-medium"> <div class="row center-xs space-vertical-medium">
@ -9,7 +9,7 @@
<div class="box"> <div class="box">
<p class="soft button-label">Would you like to flash the same image?</p> <p class="soft button-label">Would you like to flash the same image?</p>
<button class="btn btn-primary btn-brick" ng-click="finish.restart({ preserveImage: true })"> <button class="button button-primary button-brick" ng-click="finish.restart({ preserveImage: true })">
Use <b>same</b> image Use <b>same</b> image
</button> </button>
</div> </div>
@ -21,15 +21,15 @@
<div class="box"> <div class="box">
<p class="soft button-label">Would you like to flash a new image?</p> <p class="soft button-label">Would you like to flash a new image?</p>
<button class="btn btn-primary btn-brick" ng-click="finish.restart()"> <button class="button button-primary button-brick" ng-click="finish.restart()">
Use <b>new</b> image Use <b>new</b> image
</button> </button>
</div> </div>
</div> </div>
</div> </div>
<span class="label label-big label-default" <span class="label label-big label-inset"
ng-if="finish.checksum">CRC32 CHECKSUM : <b class="monospace">{{ ::finish.checksum }}</b></span> ng-if="finish.checksum">CRC32 CHECKSUM : <b>{{ ::finish.checksum }}</b></span>
</div> </div>
</div> </div>
</div> </div>

View File

@ -16,17 +16,29 @@
.page-main .icon-caption { .page-main .icon-caption {
@extend .caption; @extend .caption;
@extend .center-block;
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 10px; margin-top: 10px;
color: $palette-theme-dark-foreground;
&[disabled] { &[disabled] {
color: $color-disabled; color: $palette-theme-dark-disabled-foreground;
} }
} }
.page-main .soft { .svg-icon[disabled] path {
color: $color-disabled; fill: $palette-theme-dark-disabled-foreground;
}
.page-main .step-selection-text {
color: $palette-theme-dark-foreground;
}
.page-main .text-disabled {
color: $palette-theme-dark-disabled-foreground;
} }
.page-main .relative { .page-main .relative {
@ -35,13 +47,13 @@
%step-border { %step-border {
height: 2px; height: 2px;
background-color: $text-color; background-color: $palette-theme-dark-foreground;
position: absolute; position: absolute;
width: 230px; width: 230px;
top: 95px; top: 95px;
&[disabled] { &[disabled] {
background-color: $color-disabled; background-color: $palette-theme-dark-disabled-foreground;
} }
} }
@ -58,14 +70,14 @@
.page-main .step-tooltip { .page-main .step-tooltip {
display: block; display: block;
margin: -5px auto -20px; margin: -5px auto -20px;
color: lighten($color-disabled, 5%); color: $palette-theme-dark-disabled-foreground;
font-size: 10px; font-size: 10px;
} }
.page-main .step-footer { .page-main .step-footer {
margin-top: 10px; margin-top: 10px;
margin-bottom: -40px; margin-bottom: -40px;
color: lighten($color-disabled, 5%); color: $palette-theme-dark-disabled-foreground;
font-size: 10px; font-size: 10px;
} }
@ -82,7 +94,7 @@
padding-bottom: 2px; padding-bottom: 2px;
} }
.page-main .btn.step-footer { .page-main .button.step-footer {
font-size: 12px; font-size: 12px;
border-bottom: 1px dashed; border-bottom: 1px dashed;
border-radius: 0; border-radius: 0;

View File

@ -7,7 +7,7 @@
<div class="space-vertical-large"> <div class="space-vertical-large">
<div ng-hide="main.selection.hasImage()"> <div ng-hide="main.selection.hasImage()">
<button class="btn btn-primary btn-brick" ng-click="image.openImageSelector()">Select image</button> <button class="button button-primary button-brick" ng-click="image.openImageSelector()">Select image</button>
<p class="step-footer"> <p class="step-footer">
{{ ::image.mainSupportedExtensions.join(', ') }}, and {{ ::image.mainSupportedExtensions.join(', ') }}, and
@ -16,16 +16,17 @@
</p> </p>
</div> </div>
<div ng-if="main.selection.hasImage()"> <div ng-if="main.selection.hasImage()">
<div ng-click="main.external.open(main.selection.getImageUrl())" <div class="step-selection-text"
ng-click="main.external.open(main.selection.getImageUrl())"
ng-bind="main.selection.getImageName() || main.selection.getImagePath() | basename | middleEllipses:25"></div> ng-bind="main.selection.getImageName() || main.selection.getImagePath() | basename | middleEllipses:25"></div>
<button class="btn btn-link step-tooltip" <button class="button button-link step-tooltip"
ng-click="main.tooltipModal.show({ ng-click="main.tooltipModal.show({
title: 'IMAGE FILE NAME', title: 'IMAGE FILE NAME',
message: main.selection.getImagePath() message: main.selection.getImagePath()
})">SHOW FULL FILE NAME</button> })">SHOW FULL FILE NAME</button>
<button class="btn btn-link step-footer" <button class="button button-link step-footer"
ng-click="image.reselectImage()" ng-click="image.reselectImage()"
ng-hide="main.state.isFlashing()">Change</button> ng-hide="main.state.isFlashing()">Change</button>
</div> </div>
@ -50,21 +51,23 @@
<div ng-hide="main.selection.hasDrive()"> <div ng-hide="main.selection.hasDrive()">
<div ng-show="main.drives.hasAvailableDrives() || main.shouldDriveStepBeDisabled()"> <div ng-show="main.drives.hasAvailableDrives() || main.shouldDriveStepBeDisabled()">
<button class="btn btn-primary btn-brick" <button class="button button-primary button-brick"
ng-disabled="main.shouldDriveStepBeDisabled()" ng-disabled="main.shouldDriveStepBeDisabled()"
ng-click="drive.openDriveSelector()">Select drive</button> ng-click="drive.openDriveSelector()">Select drive</button>
</div> </div>
<div ng-hide="main.drives.hasAvailableDrives() || main.shouldDriveStepBeDisabled()"> <div ng-hide="main.drives.hasAvailableDrives() || main.shouldDriveStepBeDisabled()">
<button class="btn btn-danger btn-brick">Connect a drive</button> <button class="button button-danger button-brick button-no-hover">Connect a drive</button>
</div> </div>
</div> </div>
<div ng-show="main.selection.hasDrive()"> <div ng-show="main.selection.hasDrive()">
<div ng-class="{
soft: main.shouldDriveStepBeDisabled() <div class="step-selection-text"
}">{{ main.selection.getDrive().name }} - {{ main.selection.getDrive().size | gigabyte | number:1 }} GB</div> ng-class="{
<button class="btn btn-link step-footer" 'text-disabled': main.shouldDriveStepBeDisabled()
}">{{ main.selection.getDrive().name }} - {{ main.selection.getDrive().size | gigabyte | number:1 }} GB</div>
<button class="button button-link step-footer"
ng-click="drive.reselectDrive()" ng-click="drive.reselectDrive()"
ng-hide="main.state.isFlashing()">Change</button> ng-hide="main.state.isFlashing()">Change</button>
</div> </div>
@ -83,7 +86,7 @@
<span class="badge space-top-medium" ng-disabled="main.shouldFlashStateBeDisabled()">3</span> <span class="badge space-top-medium" ng-disabled="main.shouldFlashStateBeDisabled()">3</span>
<div class="space-vertical-large"> <div class="space-vertical-large">
<progress-button class="btn-brick" <progress-button class="button-brick"
percentage="main.state.getFlashState().percentage" percentage="main.state.getFlashState().percentage"
striped="{{ main.state.getFlashState().type == 'check' }}" striped="{{ main.state.getFlashState().type == 'check' }}"
ng-attr-active="{{ main.state.isFlashing() }}" ng-attr-active="{{ main.state.isFlashing() }}"
@ -93,20 +96,20 @@
<span ng-bind="flash.getProgressButtonLabel()"></span> <span ng-bind="flash.getProgressButtonLabel()"></span>
</progress-button> </progress-button>
<div class="alert-ribbon alert-warning" ng-class="{ 'alert-ribbon--open': !main.state.wasLastFlashSuccessful() }"> <div class="alert-ribbon" ng-class="{ 'alert-ribbon--open': !main.state.wasLastFlashSuccessful() }">
<span class="glyphicon glyphicon-warning-sign"></span> <span class="glyphicon glyphicon-warning-sign"></span>
<span ng-show="main.state.getLastFlashErrorCode() === 'ENOSPC'"> <span ng-show="main.state.getLastFlashErrorCode() === 'ENOSPC'">
Not enough space on the drive.<br>Please insert larger one and <button class="btn btn-link" ng-click="main.restartAfterFailure()">try again</button> Not enough space on the drive.<br>Please insert larger one and <button class="button button-link" ng-click="main.restartAfterFailure()">try again</button>
</span> </span>
<span ng-show="main.state.getLastFlashErrorCode() !== 'ENOSPC' && main.settings.get('validateWriteOnSuccess')"> <span ng-show="main.state.getLastFlashErrorCode() !== 'ENOSPC' && main.settings.get('validateWriteOnSuccess')">
Your removable drive may be corrupted.<br>Try inserting a different one and <button class="btn btn-link" ng-click="main.restartAfterFailure()">press "retry"</button> Your removable drive may be corrupted.<br>Try inserting a different one and <button class="button button-link" ng-click="main.restartAfterFailure()">press "retry"</button>
</span> </span>
<span ng-show="main.state.getLastFlashErrorCode() !== 'ENOSPC' && !main.settings.get('validateWriteOnSuccess')"> <span ng-show="main.state.getLastFlashErrorCode() !== 'ENOSPC' && !main.settings.get('validateWriteOnSuccess')">
Oops, seems something went wrong. Click <button class="btn btn-link" ng-click="main.restartAfterFailure()">here</button> to retry Oops, seems something went wrong. Click <button class="button button-link" ng-click="main.restartAfterFailure()">here</button> to retry
</span> </span>
</div> </div>
<button class="btn btn-warning btn-brick" ng-hide="main.state.wasLastFlashSuccessful()" ng-click="main.restartAfterFailure()"> <button class="button button-warning button-brick" ng-hide="main.state.wasLastFlashSuccessful()" ng-click="main.restartAfterFailure()">
<span class="glyphicon glyphicon-repeat"></span> Retry <span class="glyphicon glyphicon-repeat"></span> Retry
</button> </button>

View File

@ -14,55 +14,38 @@
* limitations under the License. * limitations under the License.
*/ */
.page-settings .checkbox input[type="checkbox"] + * {
color: $palette-theme-dark-foreground;
}
.page-settings .checkbox input[type="checkbox"]:not(:checked) + * { .page-settings .checkbox input[type="checkbox"]:not(:checked) + * {
color: $gray-light; color: $palette-theme-dark-soft-foreground;
}
.page-settings .title {
color: $palette-theme-dark-foreground;
} }
.page-settings .subtitle { .page-settings .subtitle {
@extend .space-top-large; color: $palette-theme-dark-foreground;
@extend .space-bottom-medium; margin-top: 30px;
margin-bottom: 15px;
} }
.modal-settings-dangerous-modal { .modal-settings-dangerous-modal {
max-width: 50%;
.modal-header { .modal-title .glyphicon {
text-align: center; color: $palette-theme-danger-background;
font-weight: bold;
color: $gray;
text-transform: initial;
font-size: 15px;
border-bottom: none;
padding: 0 0 15px;
}
.modal-title {
display: flex;
justify-content: center;
align-items: center;
.glyphicon {
margin-right: 3px;
color: $btn-danger-bg;
}
}
.modal-content {
padding: 25px 30px;
height: 220px;
} }
.modal-body { .modal-body {
padding: 0; padding: 20px;
} }
.modal-footer { .modal-footer {
padding: 0;
padding-top: 20px;
border-top: 1px solid $gray-lighter;
display: flex; display: flex;
& > .btn { & > .button {
flex-basis: 50%; flex-basis: 50%;
} }
} }

View File

@ -10,9 +10,9 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button class="btn btn-danger" <button class="button button-danger"
ng-click="modal.accept()">YES, CONTINUE</button> ng-click="modal.accept()">YES, CONTINUE</button>
<button class="btn btn-default" <button class="button button-default"
ng-click="modal.reject()">CANCEL</button> ng-click="modal.reject()">CANCEL</button>
</div> </div>

View File

@ -1,5 +1,5 @@
<div class="page-settings text-left"> <div class="page-settings text-left">
<h1 class="space-bottom-large">Settings</h1> <h1 class="title space-bottom-large">Settings</h1>
<div class="checkbox"> <div class="checkbox">
<label> <label>

View File

@ -17,6 +17,10 @@
.alert-ribbon { .alert-ribbon {
@extend .alert; @extend .alert;
background-color: $palette-theme-warning-background;
color: $palette-theme-warning-foreground;
border-color: lighten($palette-theme-warning-background, 25%);
width: 60%; width: 60%;
position: fixed; position: fixed;
@ -42,24 +46,15 @@
} }
} }
.btn-link { .button-link {
@extend .btn-sm;
padding: 0; padding: 0;
font-size: inherit; font-size: inherit;
vertical-align: baseline; vertical-align: baseline;
border-radius: 0; border-radius: 0;
border-bottom: 1px solid; border-bottom: 1px solid;
}
&.alert-warning .btn-link { border-color: $palette-theme-warning-foreground;
border-color: lighten($alert-warning-bg, 25%); color: $palette-theme-warning-foreground;
color: $alert-warning-text;
&:hover {
color: darken($alert-warning-text, 10%);
border-color: lighten($alert-warning-bg, 15%);
}
} }
} }

View File

@ -21,10 +21,11 @@
position: relative; position: relative;
z-index: 10; z-index: 10;
letter-spacing: 0; letter-spacing: 0;
background-color: $body-bg; background-color: $palette-theme-dark-background;
color: $palette-theme-dark-foreground;
} }
.badge[disabled] { .badge[disabled] {
background-color: #5c5e5c; background-color: darken($palette-theme-dark-disabled-foreground, 12%);
color: $color-disabled; color: $palette-theme-dark-disabled-foreground;
} }

View File

@ -14,7 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
.btn { .button {
@extend .btn;
padding: 10px; padding: 10px;
padding-top: 11px; padding-top: 11px;
@ -32,80 +34,70 @@
} }
&[disabled] { &[disabled] {
background-color: $btn-disabled; @extend .button-no-hover;
color: $color-disabled; background-color: $palette-theme-dark-disabled-background;
pointer-events: none; color: $palette-theme-dark-disabled-foreground;
&:hover {
background-color: lighten($btn-disabled, 2);
}
} }
} }
.btn-brick { .button-link {
min-width: $btn-min-width; @extend .btn-link;
} }
.btn-sm { .button-block {
font-size: 10px; display: block;
padding: 4px 12px; width: 100%;
}
.button-no-hover {
pointer-events: none;
}
.button-brick {
min-width: $btn-min-width;
} }
// Create map from Bootstrap `.btn` type styles // Create map from Bootstrap `.btn` type styles
// since its not possible to perform variable // since its not possible to perform variable
// interpolation (e.g: `$btn-${type}-bg`). // interpolation (e.g: `$btn-${type}-bg`).
// See https://github.com/sass/sass/issues/132 // See https://github.com/sass/sass/issues/132
$btn-types-styles: ( $button-types-styles: (
default: ( default: (
bg: $btn-default-bg, bg: $palette-theme-default-background,
color: $btn-default-color, color: $palette-theme-default-foreground
border: $btn-default-border
), ),
primary: ( primary: (
bg: $btn-primary-bg, bg: $palette-theme-primary-background,
color: $btn-primary-color, color: $palette-theme-primary-foreground
border: $btn-primary-border
),
success: (
bg: $btn-success-bg,
color: $btn-success-color,
border: $btn-success-border
),
info: (
bg: $btn-info-bg,
color: $btn-info-color,
border: $btn-info-border
), ),
warning: ( warning: (
bg: $btn-warning-bg, bg: $palette-theme-warning-background,
color: $btn-warning-color, color: $palette-theme-warning-foreground
border: $btn-warning-border
), ),
danger: ( danger: (
bg: $btn-danger-bg, bg: $palette-theme-danger-background,
color: $btn-danger-color, color: $palette-theme-danger-foreground
border: $btn-danger-border
) )
); );
// Undo `:focus` styles from Bootstrap. @each $style in map-keys($button-types-styles) {
// On Electron, the user can click and press over a button, $button-styles: map-get($button-types-styles, $style);
// then move the mouse away from the button and release,
// and the button will erroneusly keep the `:focus` state style. .button-#{$style},
@each $style in map-keys($btn-types-styles) {
.btn-#{$style}:focus { // Undo `:focus` styles from Bootstrap.
$btn-styles: map-get($btn-types-styles, $style); // On Electron, the user can click and press over a button,
background-color: map-get($btn-styles, "bg"); // then move the mouse away from the button and release,
color: map-get($btn-styles, "color"); // and the button will erroneusly keep the `:focus` state style.
border-color: map-get($btn-styles, "border"); .button-#{$style}:focus {
background-color: map-get($button-styles, "bg");
color: map-get($button-styles, "color");
outline: none;
}
.button-#{$style}:hover {
background-color: darken(map-get($button-styles, "bg"), 10%);
color: map-get($button-styles, "color");
} }
} }
/*
* Remove blue/orange outline
* !important is needed here for some reason
* despite the rule having top precedence.
*/
button.btn:focus {
outline: none !important;
}

View File

@ -24,11 +24,7 @@
padding: 8px 25px; padding: 8px 25px;
} }
.label-default { .label-inset {
background-color: #3e4147; background-color: darken($palette-theme-dark-background, 10%);
color: darken($gray-light, 30%); color: darken($palette-theme-dark-foreground, 43%);
> b {
color: darken(#fff, 5%);
}
} }

View File

@ -15,12 +15,11 @@
*/ */
.modal-content { .modal-content {
background-color: $palette-theme-light-background;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin: 0 auto;
// Since Etcher opens with a known width & height and its height: auto;
// not resizable, we can safely use an absolute value here
height: 320px;
} }
.modal-header { .modal-header {
@ -28,7 +27,7 @@
align-items: baseline; align-items: baseline;
text-transform: uppercase; text-transform: uppercase;
font-size: 11px; font-size: 11px;
color: $btn-default-color; color: $palette-theme-light-soft-foreground;
padding: 11px 20px; padding: 11px 20px;
flex-grow: 0; flex-grow: 0;
} }
@ -40,7 +39,7 @@
.modal-body { .modal-body {
flex-grow: 1; flex-grow: 1;
color: #666; color: $palette-theme-light-foreground;
padding: 0 20px; padding: 0 20px;
max-height: 250px; max-height: 250px;
overflow: auto; overflow: auto;
@ -51,7 +50,7 @@
border-left: 0; border-left: 0;
border-right: 0; border-right: 0;
border-radius: 0; border-radius: 0;
border-color: #eee; border-color: darken($palette-theme-light-background, 7%);
padding: 12px 0; padding: 12px 0;
> .tick { > .tick {
@ -65,6 +64,10 @@
&:first-child { &:first-child {
border-top: 0; border-top: 0;
} }
&[disabled] .list-group-item-heading {
color: $palette-theme-light-soft-foreground;
}
} }
.list-group-item-heading { .list-group-item-heading {
@ -74,7 +77,7 @@
.list-group-item-text { .list-group-item-text {
line-height: 1; line-height: 1;
font-size: 11px; font-size: 11px;
color: #aaa; color: $palette-theme-light-soft-foreground;
} }
} }
@ -101,13 +104,15 @@
justify-content: center; justify-content: center;
align-items: center; align-items: center;
.btn-primary[disabled] { .button[disabled] {
background-color: darken($gray-lighter, 10%); background-color: $palette-theme-light-disabled-background;
color: $palette-theme-light-disabled-foreground;
} }
} }
.modal-dialog { .modal-dialog {
margin: 0; margin: 0;
position: initial; position: initial;
max-width: 50%;
} }

View File

@ -21,12 +21,11 @@
border-radius: 50%; border-radius: 50%;
padding: 3px; padding: 3px;
font-size: 18px; font-size: 18px;
color: #fff;
border: 2px solid; border: 2px solid;
&[disabled] { &[disabled] {
color: lighten($color-disabled, 40); color: $palette-theme-dark-soft-foreground;
border-color: lighten($color-disabled, 40); border-color: $palette-theme-dark-soft-foreground;
background-color: transparent; background-color: transparent;
} }
} }
@ -34,13 +33,15 @@
.tick--success { .tick--success {
@extend .glyphicon-ok; @extend .glyphicon-ok;
background-color: rgb(95, 184, 53); color: $palette-theme-success-foreground;
border-color: rgb(95, 184, 53); background-color: $palette-theme-success-background;
border-color: $palette-theme-success-background;
} }
.tick--error { .tick--error {
@extend .glyphicon-remove; @extend .glyphicon-remove;
background-color: #d9534f; color: $palette-theme-danger-foreground;
border-color: #d9534f; background-color: $palette-theme-danger-background;
border-color: $palette-theme-danger-background;
} }

View File

@ -15,26 +15,15 @@
*/ */
$icon-font-path: "../../node_modules/bootstrap-sass/assets/fonts/bootstrap/"; $icon-font-path: "../../node_modules/bootstrap-sass/assets/fonts/bootstrap/";
$body-bg: rgb(83, 87, 96);
$text-color: #fff;
$brand-primary: rgb(87, 147, 219);
$gray-light: #ddd;
$font-size-base: 13px; $font-size-base: 13px;
$cursor-disabled: initial; $cursor-disabled: initial;
$color-disabled: rgb(120, 124, 127);
$btn-disabled: rgb(49, 51, 57);
$btn-min-width: 170px;
$link-color: $gray-light;
$link-hover-decoration: none; $link-hover-decoration: none;
$btn-default-bg: #ececec;
$btn-default-color: #b3b3b3;
$brand-warning: rgb(233, 152, 82);
$alert-warning-bg: $brand-warning;
$alert-warning-text: #fff;
$alert-padding: 13px; $alert-padding: 13px;
$btn-min-width: 170px;
$link-color: #ddd;
@import "../../../node_modules/bootstrap-sass/assets/stylesheets/bootstrap"; @import "../../../node_modules/bootstrap-sass/assets/stylesheets/bootstrap";
@import "./modules/theme";
@import "./modules/bootstrap"; @import "./modules/bootstrap";
@import "./modules/space"; @import "./modules/space";
@import "./components/label"; @import "./components/label";
@ -46,7 +35,6 @@ $alert-padding: 13px;
@import "./components/alert-ribbon"; @import "./components/alert-ribbon";
@import "../components/update-notifier/styles/update-notifier"; @import "../components/update-notifier/styles/update-notifier";
@import "../components/progress-button/styles/progress-button"; @import "../components/progress-button/styles/progress-button";
@import "../components/svg-icon/styles/svg-icon";
@import "../components/drive-selector/styles/drive-selector"; @import "../components/drive-selector/styles/drive-selector";
@import "../components/tooltip-modal/styles/tooltip-modal"; @import "../components/tooltip-modal/styles/tooltip-modal";
@import "../pages/main/styles/main"; @import "../pages/main/styles/main";
@ -58,8 +46,6 @@ body {
} }
.section-footer { .section-footer {
@extend .text-center;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@ -68,10 +54,11 @@ body {
bottom: 20px; bottom: 20px;
left: 0; left: 0;
right: 0; right: 0;
color: $color-disabled; color: $palette-theme-dark-disabled-foreground;
margin: 0 60px; margin: 0 60px;
padding-top: 15px; padding-top: 15px;
border-top: 2px solid darken($color-disabled, 8%); border-top: 2px solid $palette-theme-dark-soft-background;
text-align: center;
// Override default column padding // Override default column padding
// set by flexboxgrid. // set by flexboxgrid.
@ -88,7 +75,7 @@ body {
padding-bottom: 2px; padding-bottom: 2px;
&:hover { &:hover {
color: lighten($color-disabled, 5%); color: lighten($palette-theme-dark-disabled-foreground, 5%);
} }
} }
@ -105,11 +92,11 @@ body {
} }
.section-header { .section-header {
@extend .text-right; text-align: right;
padding: 5px 8px; padding: 5px 8px;
font-size: 15px; font-size: 15px;
> .btn { > .button {
padding-left: 3px; padding-left: 3px;
padding-right: 3px; padding-right: 3px;
} }

View File

@ -19,7 +19,11 @@
// Prevent white flash when running application // Prevent white flash when running application
html { html {
background-color: $body-bg; background-color: $palette-theme-dark-background;
}
body {
background-color: $palette-theme-dark-background;
} }
// Fix slighly checkbox vertical alignment issue // Fix slighly checkbox vertical alignment issue
@ -34,8 +38,7 @@ html {
} }
.alert { .alert {
@extend .text-center; text-align: center;
border: 0; border: 0;
border-radius: 2px; border-radius: 2px;
} }

View File

@ -0,0 +1,37 @@
/*
* Copyright 2016 Resin.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
$palette-theme-dark-foreground: #fff;
$palette-theme-dark-background: #535760;
$palette-theme-light-foreground: #666;
$palette-theme-light-background: #fff;
$palette-theme-dark-soft-foreground: #ddd;
$palette-theme-dark-soft-background: #64686a;
$palette-theme-light-soft-foreground: #b3b3b3;
$palette-theme-dark-disabled-background: #313339;
$palette-theme-dark-disabled-foreground: #787c7f;
$palette-theme-light-disabled-background: #d5d5d5;
$palette-theme-light-disabled-foreground: #787c7f;
$palette-theme-default-background: #ececec;
$palette-theme-default-foreground: #b3b3b3;
$palette-theme-primary-background: #5793db;
$palette-theme-primary-foreground: #fff;
$palette-theme-warning-background: #e99852;
$palette-theme-warning-foreground: #fff;
$palette-theme-danger-background: #d9534f;
$palette-theme-danger-foreground: #fff;
$palette-theme-success-background: #5fb835;
$palette-theme-success-foreground: #fff;