@c8y/style
Version:
Styles for Cumulocity IoT applications
1,173 lines (1,091 loc) • 26.5 kB
text/less
// Normalize non-controls
fieldset {
margin: 0;
padding: 0;
min-width: 0;
border: 0;
}
fieldset.c8y-fieldset {
display: block;
margin: 1rem 0;
border: solid 1px @form-control-border-color-default;
border-radius: @margin-8;
margin-inline-start: 2px;
margin-inline-end: 2px;
padding-block-start: 0.25rem;
padding-inline-end: 0.75em;
padding-block-end: 0;
padding-inline-start: 0.75em;
min-inline-size: 100%;
&--lg {
padding-block-start: 1rem;
padding-inline-end: 1.5em;
padding-block-end: 0;
padding-inline-start: 1.5em;
}
&.expanded {
margin: 1rem -1.15rem;
}
legend {
margin: 0;
width: auto;
text-transform: none;
padding-inline-start: 4px;
padding-inline-end: 4px;
min-height: 24px;
display: flex;
align-items: center;
}
legend[align='left'] {
justify-self: left;
}
legend[align='center'] {
justify-self: center;
}
legend[align='right'] {
justify-self: right;
}
+ .c8y-fieldset {
margin-top: @margin-24;
}
}
legend,
.legend {
display: block;
margin: @margin-16 0 @margin-8 0;
padding: 0;
width: 100%;
border: 0;
color: @form-legend-color;
text-transform: @form-legend-text-transform;
font-weight: @form-legend-font-weight;
font-size: @form-legend-font-size;
line-height: inherit;
&.form-block {
display: flex;
align-items: center;
flex-flow: row nowrap;
&:after {
align-self: center;
flex: 1 1 auto;
margin-left: 8px;
border-top-width: 1px;
border-top-style: solid;
content: '';
opacity: 0.5;
}
&.center {
&:before {
align-self: center;
flex: 1 1 auto;
margin-right: 8px;
border-top-width: 1px;
border-top-style: solid;
content: '';
opacity: 0.5;
}
}
&.last-record {
margin-right: auto;
margin-left: auto;
max-width: 180px;
> [class^='dlt-c8y-icon-'],
> [class*=' dlt-c8y-icon-'] {
font-size: 0.5rem;
}
}
}
> .dot {
margin-right: 5px;
width: 30px;
height: 30px;
font-size: 14px;
line-height: 32px;
}
}
label {
display: inline-block;
margin-bottom: @margin-4;
max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)
color: @form-label-color;
text-transform: @form-label-text-transform;
font-weight: @form-label-font-weight;
font-size: @form-label-font-size;
font-family: @form-control-font-family;
> a {
display: inline-block;
font-size: inherit;
}
&[tooltip],
[tooltip],
[uib-tooltip] {
cursor: pointer;
}
.form-group & {
display: block;
}
fieldset[disabled] & {
&:not(.c8y-checkbox):not(.c8y-radio) {
opacity: @form-control-disabled-opacity;
}
}
&:has(.btn-help){
display: flex;
align-items: center;
}
}
// Normalize form controls
// While most of our form styles require extra classes, some basic normalization
// is required to ensure optimum display with or without those classes to better address browser inconsistencies.
// Override content-box in Normalize (* isn't specific enough)
input[type='search'] {
.box-sizing(border-box);
}
// Position radios and checkboxes better
input[type='radio'],
input[type='checkbox'] {
margin: 1px 0 0;
margin-top: 1px \9; // IE8-9
font-size: 16px;
line-height: normal;
}
.plain input[type='checkbox'] {
margin: 3px 0 0;
}
input[type='file'] {
display: block;
}
// remove icon in chrome
input[type='date']::-webkit-inner-spin-button,
input[type='date']::-webkit-calendar-picker-indicator {
display: none;
-webkit-appearance: none;
}
// Make multiple select elements height not fixed
select[multiple],
select[size] {
height: auto;
}
// Adjust output element
output {
display: block;
color: @form-control-color-default;
font-size: @font-size-base;
line-height: inherit;
}
// Common form controls
// Shared size and type resets for form controls. Apply `.form-control` to any of the following form controls:
.form-control {
display: block;
padding: @form-control-padding-base-vertical @form-control-padding-base-horizontal;
width: 100%;
height: @form-control-height-base;
border: 0;
border-radius: @form-control-border-radius;
background-color: @form-control-background-default;
background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214
box-shadow: inset 0 0 0 @form-control-border-width @form-control-border-color-default;
color: @form-control-color-default;
font-weight: @form-control-font-weight;
font-size: @font-size-base;
font-family: @form-control-font-family;
line-height: @form-control-line-height;
transition:
border-color 0.15s ease-in-out,
box-shadow 0.15s ease-in-out;
.form-control-focus();
.placeholder();
&:has(.c8y-colorpicker){
width: auto;
}
&[disabled],
fieldset[disabled] & {
opacity: @form-control-disabled-opacity;
}
&[readonly],
&[readonly]:focus {
background-color: @form-control-background-default;
color: @text-muted;
opacity: 1;
}
&[disabled],
fieldset[disabled] & {
cursor: @cursor-disabled;
}
textarea & {
height: auto;
}
}
textarea.form-control {
min-height: @form-control-height-base;
height: auto;
resize: vertical;
.c8y-scrollbar();
&.no-resize {
resize: none;
}
}
// color picker
.c8y-colorpicker {
position: relative;
width: 20px;
height: 20px;
input {
position: absolute;
top: 0;
left: 0;
z-index: 10;
box-sizing: border-box;
width: 20px;
height: 20px;
opacity: 0;
cursor: pointer;
+ span {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 9;
border-radius: 50%;
border: 1px solid @form-control-border-color-default;
}
&:focus + span {
box-shadow: 0 0 0 2px @form-control-border-color-focus;
}
}
&--alarm, &--event{
input + span{
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
color: var(--component-background-default, var(--c8y-root-component-background-default, #fff));
> i{
transform: translateY(.3px);
}
}
}
}
// Search inputs in iOS
//
// This overrides the extra rounded corners on search inputs in iOS so that our
// `.form-control` class can properly style them. Note that this cannot simply
// be added to `.form-control` as it's not specific enough. For details, see
// https://github.com/twbs/bootstrap/issues/11586.
input[type='search'] {
-webkit-appearance: none;
appearance: none;
}
select,
select.form-control {
.form-control();
&[multiple],
&[size] {
height: auto;
background-image: none;
}
}
.c8y-select-wrapper {
position: relative;
select {
padding-right: 24px ;
background-image: none;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
&::-ms-expand {
display: none;
}
}
&:after {
.c8y-glyph();
position: absolute;
top: 50%;
right: 5px;
z-index: 2;
color: @form-control-icon-color;
content: @c8y-glyph-caret;
font-size: 18px;
transform: translate(0, -50%);
pointer-events: none;
}
}
// Form groups
// Designed to help with the organization and spacing of vertical forms. For
// horizontal forms, wrap form-groups in the predefined grid classes.
.form-group {
display: block;
margin-bottom: @form-validation-bottom-margin;
}
td.form-group,
th.form-group {
margin-bottom: 0;
}
// Checkboxes and radios
label.c8y-checkbox,
label.c8y-radio {
position: relative;
display: flex;
align-items: center;
margin: 0;
color: @form-control-color-default;
text-transform: none;
font-weight: @form-control-font-weight;
font-size: inherit;
line-height: @form-control-height-base;
cursor: pointer;
input[type='checkbox'],
input[type='radio'] {
position: absolute;
top: 0;
left: 0;
z-index: 1;
margin: 0;
opacity: 0;
}
input + span {
position: relative;
z-index: 2;
display: inline-block;
}
input[type='checkbox'] + span,
input[type='radio'] + span {
position: relative;
display: inline-block;
flex-shrink: 0;
width: @checkbox-size;
height: @checkbox-size;
border-radius: @form-control-border-radius;
background-color: @form-control-background-default;
box-shadow: inset 0 0 0 1px @form-control-border-color-default;
transition:
border-color 0.15s ease-in-out,
box-shadow 0.15s ease-in-out;
margin: 2px 0;
+ span {
margin-left: 8px;
line-height: @form-control-line-height;
}
}
input[type='radio'] + span {
border-radius: 50%;
}
&:hover,
input:focus {
+ span {
background-color: @form-control-background-focus;
box-shadow: inset 0 0 0 2px @form-control-border-color-focus;
color: @form-control-color-focus;
}
}
input[type='checkbox']:checked + span::after {
position: absolute;
top: 4.4px;
left: 3.7px;
display: block;
width: 9px;
height: 5px;
border-bottom: 2px solid;
border-left: 2px solid;
color: @form-control-border-color-focus;
content: '';
transform: rotate(-45deg);
}
input[type='radio']:checked + span::after {
position: absolute;
top: 50%;
left: 50%;
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
background-color: @form-control-border-color-focus;
content: '';
font-size: 10px;
line-height: inherit;
transform: translate(-50%, -50%);
pointer-events: none;
}
//checkbox indeterminate
input[type='checkbox']:indeterminate + span::after {
position: absolute;
top: 4.4px;
left: 4px;
display: block;
width: 8px;
height: 5px;
border-bottom: 2px solid;
border-left: 0;
color: @form-control-border-color-focus;
content: '';
}
//disabled
input[disabled],
input[disabled]:checked {
cursor: @cursor-disabled;
+ span {
background-color: @form-control-background-disabled;
opacity: @form-control-disabled-opacity;
cursor: @cursor-disabled;
}
~ span {
opacity: @form-control-disabled-opacity;
}
}
input[readonly],
input[readonly]:checked {
pointer-events: none;
~ span {
opacity: @form-control-disabled-opacity;
}
}
&.disabled,
[disabled] & {
cursor: @cursor-disabled;
span {
opacity: @form-control-disabled-opacity;
cursor: @cursor-disabled;
&::before {
opacity: 1;
}
}
}
&.checkbox-inline,
&.radio-inline {
display: inline-flex;
padding: 0;
&:not(:last-child) {
margin-right: @margin-16;
}
}
&.has-error {
input + span {
box-shadow: inset 0 0 0 2px @form-control-validation-error;
}
}
}
.form-group {
> label + .c8y-checkbox,
> label + .c8y-radio {
margin-top: @margin-8;
}
}
// Form control help & feedback states
// set feedback min height to avoid field jumping
c8y-error-feedback,
c8y-messages,
.c8y-messages {
display: block;
margin-bottom: calc(@form-validation-bottom-margin * -1);
min-height: @form-validation-bottom-margin;
.has-error.form-group--tooltip-validation &,
.input-group-array .has-error & {
display: none;
.form-control-feedback-message:not(.ng-inactive) {
padding-top: 0.25em;
margin-top: 0;
&::before {
color: @tooltip-color-default;
}
}
}
.has-error.form-group--tooltip-validation & {
.form-control-feedback-message:before {
color: var(--c8y-palette-high) ;
}
}
.has-error.form-group--tooltip-validation:hover &,
.input-group-array .has-error:hover & {
position: absolute;
bottom: 61px;
left: calc(20% - @margin-16);
z-index: 10;
display: block;
padding: 0 5px;
max-width: calc(100% - @margin-16);
border-radius: @tooltip-radius;
background-color: @form-control-validation-error;
color: @tooltip-color-default;
&:after {
position: absolute;
bottom: -5px;
left: 50%;
margin-top: 0;
width: 0;
height: 0;
border-width: @tooltip-arrow-width @tooltip-arrow-width 0;
border-style: solid;
border-color: transparent;
border-top-color: @form-control-validation-error;
content: '';
opacity: @tooltip-opacity;
}
}
}
.form-group .help-block,
.form-group .form-control-feedback-message {
position: relative;
display: block;
margin-top: 0;
min-height: @form-validation-bottom-margin;
font-size: @font-size-small;
line-height: 1.5;
&:empty {
display: none;
}
}
.help-block {
font-style: italic;
&.has-info,
.form-control-feedback-message:has(.help-block) & {
display: flex;
&:before {
font: normal normal normal 16px/1 '@{icon-font-family}';
font-size: 16px;
color: @form-control-validation-info;
content: @alert-info-icon;
margin-right: 2px;
}
}
}
.form-control-feedback-message:has(.help-block) {
padding-left: 0 ;
}
// icon in feedback message
.form-control-feedback-message,
.input-group + .help-block,
select ~ .help-block,
c8y-field-input ~ .help-block,
textarea ~ .help-block,
input ~ .help-block,
file-picker ~ .help-block,
.form-control ~ .help-block {
&:before {
position: absolute;
top: 2px;
left: 1px;
display: inline-block;
font: normal normal normal 14px/1 '@{icon-font-family}';
font-size: 16px;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
}
// Apply contextual and semantic states to individual form controls.
.form-control-feedback-message:not(.ng-inactive),
.input-group + .help-block,
select ~ .help-block,
textarea ~ .help-block,
file-picker ~ .help-block,
.form-control ~ .help-block,
c8y-field-input ~ .help-block,
input ~ .help-block {
position: relative;
padding-top: calc(@margin-base * 0.25);
padding-left: 20px;
margin-top: 0;
}
file-picker ~ .help-block {
margin-top: -24px;
}
.has-success:not(.schema-form-text) {
.form-control-validation(@form-control-color-default; @form-control-validation-success; transparent);
.form-control-feedback-message {
&:before {
content: @alert-success-icon;
}
}
}
.has-warning {
.form-control-validation(@form-control-color-default; @form-control-validation-warning;transparent);
.form-control-feedback-message {
&:before {
content: @alert-warning-icon;
}
}
}
.has-error {
.form-control-validation(@form-control-color-default; @form-control-validation-error;transparent);
.form-control-feedback-message {
&:before {
content: @alert-danger-icon;
}
}
}
.form-control-feedback-message.has-error {
margin-bottom: 8px;
line-height: 1.2;
&:before {
color: @form-control-validation-error;
content: @alert-danger-icon;
}
.table-data-grid & {
display: none ;
}
}
.has-info {
.form-control-validation(@form-control-color-default; @form-control-validation-info;transparent);
.form-control-feedback-message {
&:before {
content: @alert-info-icon;
}
}
}
textarea ~ .help-block:not(:empty),
file-picker ~ .help-block:not(:empty),
select ~ .help-block:not(:empty),
input ~ .help-block:not(:empty),
c8y-field-input ~ .help-block:not(:empty),
.form-control ~ .help-block:not(:empty),
.input-group ~ .help-block:not(:empty) {
&:before {
color: @form-control-validation-info;
content: @alert-info-icon;
}
}
// legacy compliant
.form-control.ng-invalid.ng-invalid-required.ng-touched,
.form-control.ng-invalid.ng-touched {
box-shadow:
inset 1px 0 0 0 @form-control-border-color-default,
inset -1px 0 0 0 @form-control-border-color-default,
inset 0 1px 0 0 @form-control-border-color-default,
inset 0 -4px 0 @form-control-validation-error;
&:focus {
box-shadow:
inset 2px 0 0 0 @form-control-border-color-focus,
inset -2px 0 0 0 @form-control-border-color-focus,
inset 0 2px 0 0 @form-control-border-color-focus,
inset 0 -4px 0 @form-control-validation-error;
}
+ * > .form-control-feedback-message:not(:empty) {
&:before {
color: @form-control-validation-error;
content: @alert-danger-icon;
}
}
}
// error message for drop-zone
.drop-zone .has-errors .form-control-feedback-message {
font-size: @font-size-base;
&:not(:empty):before {
color: @form-control-validation-error;
content: @alert-danger-icon;
}
}
// Feedback icon
// hidden - it was deprecated
.form-control-feedback {
display: none ;
}
// Static form control text
//
// Apply class to a `p` element to make any string of text align with labels in
// a horizontal form layout.
.form-control-static {
display: flex;
align-items: center;
margin: 1px 0 0;
min-height: @form-control-height-base;
line-height: @form-control-line-height;
}
// Form control sizing
// Build on `.form-control` with modifier classes to decrease or increase the
// height and font-size of form controls.
//
.form-group-sm > label {
margin-bottom: 0;
font-size: @font-size-small;
}
.form-group-sm .form-control,
.form-group-sm > .form-group .form-control,
.form-group-sm .form-control-static,
.input-sm {
&:not(.c8y-radio):not(.c8y-checkbox) {
padding: @form-control-padding-small-vertical @form-control-padding-small-horizontal;
height: @form-control-height-sm;
font-size: @font-size-small;
line-height: @line-height-small;
}
}
.form-group-lg > label {
font-size: @font-size-large;
}
.form-group-lg .form-control,
.form-group-lg .form-control-static,
.input-lg {
&:not(.c8y-radio):not(.c8y-checkbox) {
padding: @form-control-padding-large-vertical @form-control-padding-large-horizontal;
max-height: unset ;
height: @form-control-height-lg;
font-size: @font-size-large;
}
}
// disable editing in forms
.form-read-only {
position: relative;
// covers all inputs within the form
label {
pointer-events: none;
}
input,
select{
pointer-events: none;
}
&.hidden-labels {
.form-group > label {
display: none;
}
}
.form-group {
margin: 0;
label {
margin: 0;
color: @form-label-color;
opacity: 1 ;
}
}
.form-control,
.form-control.input-sm,
.form-control.input-lg {
padding: 0;
background-color: transparent;
box-shadow: none;
opacity: 1 ;
resize: none;
&.ng-empty {
display: none;
}
}
textarea.form-control {
height: auto;
line-height: @form-control-line-height;
}
.btn:not(.form-edit-btn) {
display: none;
}
.form-edit-btn {
display: inline-block;
}
input[type='number'] {
-moz-appearance: textfield;
-webkit-appearance: none;
appearance: none;
}
}
// hide the .form-edit-btn outside a .form-read-only container
.form-edit-btn {
position: relative;
z-index: 1001;
display: none;
margin: 0;
padding: 0;
border: 0;
background: none;
color: @link-color;
font-size: @font-size-small;
cursor: pointer;
&:hover {
color: @link-color-hover;
text-decoration: none;
}
&:focus {
outline: none;
box-shadow: inset 0 -2px 0 @form-control-border-color-focus;
}
}
// Editable inputs
label.editable {
position: relative;
display: flex;
align-items: flex-start;
margin: 0;
padding: 0;
color: @form-control-color-default;
text-transform: none;
font-weight: inherit;
font-size: inherit;
cursor: pointer;
.form-control {
min-width: 4ch;
max-width: 100%;
-moz-appearance: textfield;
appearance: textfield;
&::-webkit-inner-spin-button,
&::-webkit-outer-spin-button {
margin: 0;
-webkit-appearance: none;
}
&[c8y-textarea-autoresize] {
transition:
border-color 0.15s ease-in-out,
box-shadow 0.15s ease-in-out,
padding 0.35s ease ;
}
}
&:has(.ng-pristine):after {
position: relative;
display: inline-block;
margin-top: 0.9rem;
color: @component-brand-primary;
.dlt-c8y-icon();
content: @dlt-c8y-icon-pencil;
}
.form-control + span {
display: none;
}
&:not(.updated) {
.form-control:not(.ng-dirty) {
position: relative;
z-index: 9;
transition: all 0.35s ease;
&[c8y-textarea-autoresize] {
transition:
border-color 0.15s ease-in-out,
box-shadow 0.15s ease-in-out,
padding 0.35s ease ;
}
&:not(:focus):not(:hover) {
z-index: 2;
overflow: hidden;
padding-right: 0;
padding-left: 0;
background-color: transparent;
box-shadow: none;
text-overflow: ellipsis;
}
}
}
&.updated {
width: 100%;
&:after {
display: none;
}
}
&.updated .form-control,
.form-control:focus,
.form-control.ng-dirty {
margin-right: -24px;
min-width: 100%;
opacity: 1;
transition: all 0.25s ease;
~ span {
display: none;
}
}
&:not(.updated):hover {
.form-control {
min-width: 100%;
}
&:after {
opacity: 0;
}
.form-control:not(:focus) {
background-color: transparent;
}
}
.form-control.ng-invalid-required + span,
.form-control.ng-invalid-required + span span {
color: @form-control-validation-error;
&:after {
color: @form-control-validation-error;
}
}
.has-error &,
.has-warning &,
.has-info &,
.has-success & {
&:after {
display: none;
}
.form-control {
padding: @form-control-padding-base-vertical @form-control-padding-base-horizontal;
}
}
}
// Inline forms
//
// Make forms appear inline(-block) by adding the `.form-inline` class. Inline
// forms begin stacked on extra small (mobile) devices and then go inline when
// viewports reach <768px.
//
// Requires wrapping inputs and labels with `.form-group` for proper display of
// default HTML form controls and our custom form controls (e.g., input groups).
//
// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.
.form-inline {
@media (min-width: @screen-sm-min) {
.form-group {
display: inline-block;
margin-bottom: 0;
max-height: 32px ;
vertical-align: middle;
> label {
margin-right: @margin-8;
}
+ .form-group, + .btn {
margin-left: @margin-8;
}
}
label {
display: inline-block;
margin-bottom: 0;
}
.form-control {
display: inline-block;
width: auto;
vertical-align: middle;
}
.form-control-static {
display: inline-block;
}
.input-group {
display: inline-flex;
width: auto;
vertical-align: middle;
.input-group-addon,
.input-group-btn,
.form-control {
width: auto;
}
}
.control-label {
margin-bottom: 0;
vertical-align: middle;
}
.c8y-select-wrapper {
display: inline-block;
vertical-align: middle;
}
.radio,
.checkbox {
display: inline-block;
margin-top: 0;
margin-bottom: 0;
vertical-align: middle;
label {
padding-left: 0;
}
}
.radio input[type='radio'],
.checkbox input[type='checkbox'] {
position: relative;
margin-left: 0;
} // Re-override the feedback icon.
.has-feedback .form-control-feedback {
top: 0;
}
.has-feedback .form-control-feedback-message {
top: @form-control-height-base;
}
}
}
// Legacy radio and checkboxes
.radio,
.checkbox {
label {
display: inline-flex;
align-items: center;
margin: 0 0 8px 0;
padding-left: 0;
> input[type='radio'],
> input[type='checkbox'] {
flex-grow: 0;
margin: 0 8px 0 0;
height: 18px;
+ span {
flex-grow: 1;
font-weight: normal;
}
}
}
}
// Horizontal forms
// Horizontal forms are built on grid classes and allow you to create forms with labels on the left and inputs on the right.
.form-horizontal {
.radio,
.checkbox,
.radio-inline,
.checkbox-inline {
margin-top: 0;
margin-bottom: 0;
padding-top: calc(@component-padding-base-vertical + 1px);
}
.radio,
.checkbox {
min-height: calc(~'@{line-height-computed} + @{component-padding-base-vertical} + 1');
} // Make form groups behave like rows
.form-group {
.make-row();
.form-group {
position: relative;
margin-right: 0;
margin-left: 0;
.form-control-feedback {
right: 5px;
}
}
}
@media (min-width: @screen-sm-min) {
.control-label {
margin-bottom: 0;
padding-top: calc(@component-padding-base-vertical + 2px);
}
}
// Validation states
//
// Reposition the icon because it's now within a grid column and columns have
// `position: relative;` on them. Also accounts for the grid gutter padding.
.has-feedback .form-control-feedback {
right: calc(@grid-gutter-width * 0.5 + 5);
}
.form-group-lg {
@media (min-width: @screen-sm-min) {
.control-label {
padding-top: calc(~'@{component-padding-large-vertical} * @{line-height-large} + 1');
font-size: @font-size-large;
}
}
}
.form-group-sm {
@media (min-width: @screen-sm-min) {
.control-label {
padding-top: calc(~'@{component-padding-small-vertical} + 1');
font-size: @font-size-small;
}
}
}
}
// Slide form action buttons into the viewport on long forms
.btn-save-wrapper {
animation-duration: 0.5s;
&.changed-remove-active {
animation-duration: 0;
}
}
.btn-save-wrapper.changed {
position: fixed;
right: 0;
bottom: 0;
left: 0;
z-index: (@zindex-navbar-fixed - 1);
padding: 16px 48px;
background-color: @component-background-default;
transition: left 0.4s ease-in-out; //horizontal tabs
.mcontainerHorizontal & {
left: 0;
padding: 10px 15px;
}
.open & {
left: @navigatorWidth;
}
}
.open {
.has-tabs.page-tabs-vertical + .container-fluid {
.btn-save-wrapper.changed {
left: calc(@navigatorWidth + @nav-tabs-vertical-width);
}
}
}