summaryrefslogtreecommitdiff
path: root/addons/web/static/src/scss
diff options
context:
space:
mode:
authorqsm-odoo <qsm@odoo.com>2018-03-12 16:27:41 +0100
committerqsm-odoo <qsm@odoo.com>2018-04-18 15:59:15 +0200
commitb04dec4025013c60e4857c1e177bb20d811cd41a (patch)
treedb8b38a5e1df34ee6f0402fab9a0bd8b4b769f8e /addons/web/static/src/scss
parenta6393130e6fcc4ad706f3df08557e5434416e4ab (diff)
[REF] *: rename all LESS files to SCSS
This is a simple renaming without adaptation.
Diffstat (limited to 'addons/web/static/src/scss')
-rw-r--r--addons/web/static/src/scss/animation.scss162
-rw-r--r--addons/web/static/src/scss/base_settings.scss235
-rw-r--r--addons/web/static/src/scss/bootstrap_overridden.scss168
-rw-r--r--addons/web/static/src/scss/control_panel.scss133
-rw-r--r--addons/web/static/src/scss/data_export.scss109
-rw-r--r--addons/web/static/src/scss/datepicker.scss78
-rw-r--r--addons/web/static/src/scss/debug_manager.scss8
-rw-r--r--addons/web/static/src/scss/domain_selector.scss204
-rw-r--r--addons/web/static/src/scss/dropdown.scss80
-rw-r--r--addons/web/static/src/scss/dropdown_extra.scss63
-rw-r--r--addons/web/static/src/scss/fields.scss385
-rw-r--r--addons/web/static/src/scss/fields_extra.scss59
-rw-r--r--addons/web/static/src/scss/fonts.scss37
-rw-r--r--addons/web/static/src/scss/form_view.scss747
-rw-r--r--addons/web/static/src/scss/form_view_extra.scss190
-rw-r--r--addons/web/static/src/scss/graph_view.scss20
-rw-r--r--addons/web/static/src/scss/import_bootstrap.scss1
-rw-r--r--addons/web/static/src/scss/kanban_column_progressbar.scss152
-rw-r--r--addons/web/static/src/scss/kanban_dashboard.scss243
-rw-r--r--addons/web/static/src/scss/kanban_examples_dialog.scss71
-rw-r--r--addons/web/static/src/scss/kanban_view.scss648
-rw-r--r--addons/web/static/src/scss/kanban_view_mobile.scss52
-rw-r--r--addons/web/static/src/scss/layout_background.scss68
-rw-r--r--addons/web/static/src/scss/layout_boxed.scss73
-rw-r--r--addons/web/static/src/scss/layout_clean.scss85
-rw-r--r--addons/web/static/src/scss/list_view.scss243
-rw-r--r--addons/web/static/src/scss/list_view_extra.scss10
-rw-r--r--addons/web/static/src/scss/mimetypes.scss70
-rw-r--r--addons/web/static/src/scss/modal.scss83
-rw-r--r--addons/web/static/src/scss/model_field_selector.scss130
-rw-r--r--addons/web/static/src/scss/navbar.scss233
-rw-r--r--addons/web/static/src/scss/pivot_view.scss78
-rw-r--r--addons/web/static/src/scss/progress_bar.scss36
-rw-r--r--addons/web/static/src/scss/rainbow.scss257
-rw-r--r--addons/web/static/src/scss/report.editor.scss26
-rw-r--r--addons/web/static/src/scss/report.scss35
-rw-r--r--addons/web/static/src/scss/report_backend.scss14
-rw-r--r--addons/web/static/src/scss/search_view.scss220
-rw-r--r--addons/web/static/src/scss/search_view_extra.scss43
-rw-r--r--addons/web/static/src/scss/tooltip.scss59
-rw-r--r--addons/web/static/src/scss/ui.scss11
-rw-r--r--addons/web/static/src/scss/ui_extra.scss10
-rw-r--r--addons/web/static/src/scss/utils.scss274
-rw-r--r--addons/web/static/src/scss/variables.scss92
-rw-r--r--addons/web/static/src/scss/views.scss103
-rw-r--r--addons/web/static/src/scss/web_calendar.scss230
-rw-r--r--addons/web/static/src/scss/webclient.scss140
-rw-r--r--addons/web/static/src/scss/webclient_extra.scss46
-rw-r--r--addons/web/static/src/scss/webclient_layout.scss165
49 files changed, 6679 insertions, 0 deletions
diff --git a/addons/web/static/src/scss/animation.scss b/addons/web/static/src/scss/animation.scss
new file mode 100644
index 00000000000..6da0a1f9d64
--- /dev/null
+++ b/addons/web/static/src/scss/animation.scss
@@ -0,0 +1,162 @@
+/************** DEFINITION of ANIMATIONS **************/
+// 'marked' effects
+@keyframes markAnim {
+ 0% {
+ opacity: 0;
+ transform: scaleX(0.50) scaleY(0.50);
+ }
+ 30% {
+ opacity: 1;
+ transform: scaleX(1.00) scaleY(1.00);
+ }
+ 100% {
+ opacity: 0;
+ transform: scaleX(1.00) scaleY(1.00);
+ }
+}
+
+@-moz-keyframes markAnim {
+ 0% {
+ opacity: 0;
+ -moz-transform: scaleX(0.50) scaleY(0.50);
+ }
+ 30% {
+ opacity: 1;
+ -moz-transform: scaleX(1.00) scaleY(1.00);
+ }
+ 100% {
+ opacity: 0;
+ -moz-transform: scaleX(1.00) scaleY(1.00);
+ }
+}
+
+@-webkit-keyframes markAnim {
+ 0% {
+ opacity: 0;
+ -webkit-transform: scaleX(0.50) scaleY(0.50);
+ }
+ 30% {
+ opacity: 1;
+ -webkit-transform: scaleX(1.00) scaleY(1.00);
+ }
+ 100% {
+ opacity: 0;
+ -webkit-transform: scaleX(1.00) scaleY(1.00);
+ }
+}
+
+@-o-keyframes markAnim {
+ 0% {
+ opacity: 0;
+ -o-transform: scaleX(0.50) scaleY(0.50);
+ }
+ 30% {
+ opacity: 1;
+ -o-transform: scaleX(1.00) scaleY(1.00);
+ }
+ 100% {
+ opacity: 0;
+ -o-transform: scaleX(1.00) scaleY(1.00);
+ }
+}
+
+@-ms-keyframes markAnim {
+ 0% {
+ opacity: 0;
+ -ms-transform: scaleX(0.50) scaleY(0.50);
+ }
+ 30% {
+ opacity: 1;
+ -ms-transform: scaleX(1.00) scaleY(1.00);
+ }
+ 100% {
+ opacity: 0;
+ -ms-transform: scaleX(1.00) scaleY(1.00);
+ }
+}
+
+// 'bounce' effect
+@-webkit-keyframes bounceIn {
+ 0%, 20%, 40%, 60%, 80%, 100% {
+ -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+ transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+ }
+
+ 0% {
+ opacity: 0;
+ -webkit-transform: scale3d(.3, .3, .3);
+ transform: scale3d(.3, .3, .3);
+ }
+ 20% {
+ -webkit-transform: scale3d(1.1, 1.1, 1.1);
+ transform: scale3d(1.1, 1.1, 1.1);
+ }
+ 40% {
+ -webkit-transform: scale3d(.9, .9, .9);
+ transform: scale3d(.9, .9, .9);
+ }
+ 60% {
+ opacity: 1;
+ -webkit-transform: scale3d(1.03, 1.03, 1.03);
+ transform: scale3d(1.03, 1.03, 1.03);
+ }
+ 80% {
+ -webkit-transform: scale3d(.97, .97, .97);
+ transform: scale3d(.97, .97, .97);
+ }
+ 100% {
+ opacity: 1;
+ -webkit-transform: scale3d(1, 1, 1);
+ transform: scale3d(1, 1, 1);
+ }
+}
+
+@keyframes bounceIn {
+ 0%, 20%, 40%, 60%, 80%, 100% {
+ -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+ transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+ }
+ 0% {
+ opacity: 0;
+ -webkit-transform: scale3d(.3, .3, .3);
+ transform: scale3d(.3, .3, .3);
+ }
+ 20% {
+ -webkit-transform: scale3d(1.1, 1.1, 1.1);
+ transform: scale3d(1.1, 1.1, 1.1);
+ }
+ 40% {
+ -webkit-transform: scale3d(.9, .9, .9);
+ transform: scale3d(.9, .9, .9);
+ }
+ 60% {
+ opacity: 1;
+ -webkit-transform: scale3d(1.03, 1.03, 1.03);
+ transform: scale3d(1.03, 1.03, 1.03);
+ }
+ 80% {
+ -webkit-transform: scale3d(.97, .97, .97);
+ transform: scale3d(.97, .97, .97);
+ }
+ 100% {
+ opacity: 1;
+ -webkit-transform: scale3d(1, 1, 1);
+ transform: scale3d(1, 1, 1);
+ }
+}
+
+/************** MIXINS for ANIMATIONS **************/
+.o-display-marked(@content, @top, @left, @color) {
+ .o-position-absolute(@top: @top, @left: @left);
+ font-size: 300px;
+ font-family: "FontAwesome";
+ content: @content;
+ color: @color;
+ .o-transform-origin();
+ .o-animation(markAnim, 1s, ease-in-out, 0s, 1, normal, forwards);
+
+ @media (max-width: @screen-sm-max) {
+ left: 40%;
+ font-size: 30vw;
+ }
+}
diff --git a/addons/web/static/src/scss/base_settings.scss b/addons/web/static/src/scss/base_settings.scss
new file mode 100644
index 00000000000..426d8cb557c
--- /dev/null
+++ b/addons/web/static/src/scss/base_settings.scss
@@ -0,0 +1,235 @@
+// VARIABLES
+@o-base-settings-mobile-tabs-height: 40px;
+@o-base-settings-mobile-tabs-overflow-gap: 3%;
+
+// MIXINS
+.o-base-settings-horizontal-padding(@padding-base: @padding-small-vertical) {
+ padding: @padding-base @odoo-horizontal-padding;
+
+ @media (min-width: @screen-lg-min) {
+ padding-left: @odoo-horizontal-padding*2;;
+ }
+}
+
+// Use a very specif selector to overwrite generic form-view rules
+.o_form_view.o_form_nosheet.o_base_settings {
+ .o-flex-display();
+ .o-flex-flow(column, nowrap);
+ padding: 0px;
+}
+
+// BASE SETTINGS LAYOUT
+.o_base_settings {
+ height: 100%;
+
+ @media (max-width: @screen-xs-max) {
+ .o-flex-flow(column, nowrap);
+ }
+
+ .o_control_panel {
+ .o_panel {
+ .o-flex-display();
+ .o-flex-flow(row, wrap);
+ margin-bottom: @odoo-sheet-vpadding*0.5;
+ width: 100%;
+
+ .title, .o_setting_search {
+ .o-flex(1, 0, auto);
+ width: @screen-xs-min*0.5;
+ }
+
+ .o_setting_search {
+ position: relative;
+
+ .searchInput {
+ height: 28px;
+ padding: 0px;
+ border: 0px;
+ border-bottom: 1px solid @gray-lighter-darker;
+ border-color: @gray;
+ box-shadow: none;
+ font-weight: 500;
+ }
+
+ .searchIcon {
+ .o-position-absolute(4px, 0);
+ color: @gray;
+ }
+ }
+ }
+
+ .o_form_statusbar {
+ padding: 0;
+ margin: 0;
+ border: 0;
+
+ .btn-primary, .btn-link {
+ padding: @padding-small-vertical @padding-small-horizontal;
+ }
+
+ .btn-link {
+ .o-hover-text-color(@link-color, @link-hover-color);
+ }
+ }
+ }
+
+ .o_setting_container {
+ .o-flex-display();
+ .o-flex(1, 1, auto);
+
+ overflow: auto;
+
+ @media (max-width: @screen-xs-max) {
+ .o-flex-flow(column, nowrap);
+ }
+
+ .settings_tab {
+ .o-flex-display();
+ .o-flex(0, 0, auto);
+ .o-flex-flow(column, nowrap);
+ background: @gray-dark;
+ overflow: auto;
+ padding-top: @odoo-horizontal-padding*0.5;
+
+ @media (max-width: @screen-xs-max) {
+ .o-flex(0, 0, @o-base-settings-mobile-tabs-height);
+ .o-inline-flex-display();
+ position: relative;
+ overflow: hidden;
+ padding: 0;
+ }
+
+ .selected {
+ background-color: @gray-darker;
+ box-shadow: inset 3px 0 0 @odoo-brand-optional;
+
+ .app_name {
+ color: white;
+ }
+ }
+
+ .tab {
+ .o-flex-display();
+ padding: 0 @odoo-horizontal-padding*2 0 @odoo-horizontal-padding;
+ height: 40px;
+ color: @gray-lighter-darker;
+ font-size: 13px;
+ line-height: 40px;
+ cursor: pointer;
+
+ .icon {
+ width: 23px;
+ margin-right: 10px;
+ }
+
+ // Mobile Tabs
+ @media (max-width: @screen-xs-max) {
+ display: block;
+ .o-position-absolute(@left:100%);
+ .size(auto, @o-base-settings-mobile-tabs-height);
+ padding: @o-base-settings-mobile-tabs-height*0.25 @o-base-settings-mobile-tabs-height*0.4;
+ text-align: center;
+ font-size: 14px;
+ font-weight: 500;
+ line-height: inherit;
+ .o-transition(0.2s, all);
+ .o-transform(translate3d(0,0,0));
+
+ .app_name {
+ display: block;
+ white-space: nowrap;
+ }
+
+ &:after {
+ content: '';
+ background: @odoo-brand-optional;
+ opacity: 0;
+ .o-position-absolute(auto, 0, 0, 0);
+ .size(100%, 3px);
+ .o-transition(0.2s, all);
+ }
+
+ &.previous, &.before {
+ left: 0% - @o-base-settings-mobile-tabs-overflow-gap;
+ }
+
+ &.current {
+ left: 50%;
+ color: white;
+
+ // Reset default style for 'selected' tabs
+ box-shadow: none;
+ background: none;
+
+ &:after {
+ opacity: 1;
+ }
+ }
+
+ &.next, &.after {
+ left: 100% + @o-base-settings-mobile-tabs-overflow-gap;
+ }
+ }
+ }
+ }
+
+ .settings {
+ position: relative;
+ .o-flex(1, 1, 100%);
+ background-color: @odoo-view-background-color;
+ overflow: auto;
+
+ > .app_settings_block {
+ h2 {
+ margin-bottom: 0;
+ .o-base-settings-horizontal-padding();
+ background-color: @gray-lighter;
+ font-size: 15px;
+ font-weight: bold;
+
+ &:first-of-type {
+ // Necessary to overwrite mt32 class
+ margin-top: 10px!important;
+ }
+ }
+
+ .o_settings_container {
+ max-width: @screen-md-min; // Provide a maximum container size to ensure readability
+ .o-base-settings-horizontal-padding(0);
+ }
+ }
+
+ .settingSearchHeader {
+ .o-flex-display();
+ margin: 30px 0 10px;
+ .o-base-settings-horizontal-padding();
+ background-color: @gray-lighter;
+
+ .icon {
+ .square(25px);
+ margin-right: 10px;
+ }
+
+ .appName {
+ color: @headings-color;
+ font-size: 17px;
+ }
+ }
+
+ .notFound {
+ color : @text-muted;
+ text-align: center;
+ font-size: 25px;
+ padding-top: 50px;
+ }
+
+ .highlighter {
+ background: yellow;
+ }
+ }
+
+ .d-block {
+ display: block!important;
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/bootstrap_overridden.scss b/addons/web/static/src/scss/bootstrap_overridden.scss
new file mode 100644
index 00000000000..5bbe61ecdf6
--- /dev/null
+++ b/addons/web/static/src/scss/bootstrap_overridden.scss
@@ -0,0 +1,168 @@
+// ------------------------------------------------------------------
+// Bootstrap variables
+// ------------------------------------------------------------------
+
+//== Grid
+@grid-gutter-width: @odoo-horizontal-padding*2;
+
+//== Colors
+@brand-primary: @odoo-brand-primary;
+@gray-lighter: @odoo-color-silver;
+
+//== Titles
+@font-size-h1: @odoo-font-size-base + 13px;
+@font-size-h2: @odoo-font-size-base + 7px;
+@font-size-h3: @odoo-font-size-base + 3px;
+@font-size-h4: @odoo-font-size-base + 2px;
+@font-size-h5: @odoo-font-size-base + 1px;
+@font-size-h6: @odoo-font-size-base;
+
+//== Scaffolding
+@body-bg: @odoo-brand-secondary;
+@text-color: @odoo-main-text-color;
+@link-color: @odoo-brand-optional;
+@link-hover-decoration: none;
+
+//== Typography
+@font-family-sans-serif: "Lucida Grande", Helvetica, Verdana, Arial, sans-serif;
+@font-size-base: @odoo-font-size-base;
+@headings-font-weight: bold;
+
+//== Components
+@component-active-bg: @gray-lighter;
+@component-active-color: @odoo-brand-optional;
+
+//== Badges
+@badge-bg: @odoo-brand-optional;
+@badge-color: white;
+@badge-line-height: @line-height-base;
+@badge-font-weight: normal;
+
+//== Breadcrumbs
+@breadcrumb-active-color: #777777;
+@breadcrumb-bg: @odoo-control-panel-background-color;
+@breadcrumb-color: #777777;
+@breadcrumb-padding-horizontal: 0;
+@breadcrumb-padding-vertical: 0;
+
+//== Buttons
+@btn-default-bg: white;
+@btn-default-border: #cccccc;
+@btn-default-color: @odoo-main-text-color;
+@btn-primary-bg: @odoo-brand-optional;
+@btn-primary-border: @odoo-brand-optional;
+@btn-primary-color: white;
+
+//== Dropdowns
+@dropdown-bg: white;
+@dropdown-border: @gray-lighter-dark;
+@dropdown-divider-bg: @gray-lighter-dark;
+@dropdown-link-color: @odoo-main-text-color;
+@dropdown-link-hover-color: @gray-dark;
+@dropdown-link-hover-bg: @gray-lighter;
+@dropdown-link-active-color: @component-active-color;
+@dropdown-link-active-bg: @component-active-bg;
+@dropdown-link-disabled-color: @gray-light;
+@dropdown-header-color: @gray-light;
+
+//== Modals
+@modal-sm: 300px;
+@modal-md: 650px;
+@modal-lg: 980px;
+@modal-inner-padding: @odoo-horizontal-padding;
+@modal-title-padding: @odoo-horizontal-padding;
+
+// Change the z-index of the modal-backdrop elements to be equal to the
+// modal elements' ones. Bootstrap does not support multi-modals, and without
+// this rule all the modal-backdrops are below all the opened modals.
+// Indeed, bootstrap forces them to a lower z-index as the modal-backdrop
+// element (unique in their supported cases) might be put after the modal
+// element (if the modal is already in the DOM, hidden, then opened). This
+// cannot happen in odoo though as modals are not hidden but removed from
+// the DOM and are always put at the end of the body when opened.
+//
+// Note that the variable @zindex-modal-background may be renamed/removed in
+// newer versions of bootstrap.
+//
+// TODO the following code was disabled because it is saas-incompatible
+//
+// @zindex-modal-background: @zindex-modal;
+
+//== Navs
+@nav-link-padding: 10px 15px;
+@nav-pills-border-radius: 0;
+@nav-pills-active-link-hover-color: white;
+@nav-pills-active-link-hover-bg: @odoo-brand-optional;
+@nav-tabs-active-link-hover-bg: white;
+
+//== Navbar
+@navbar-height: @odoo-navbar-height - 2;
+@navbar-margin-bottom: 0;
+@navbar-inverse-bg: #222222;
+@navbar-inverse-link-color: #9d9d9d;
+@navbar-inverse-link-hover-bg: #222222;
+@navbar-inverse-toggle-hover-bg: #222222;
+@navbar-border-radius: 0;
+
+//== Tables
+@table-bg-accent: #efeff8; // FIXME: expose
+@table-bg-hover: darken(@table-bg-accent,5%);
+
+// ------------------------------------------------------------------
+// Bootstrap components rules (non exposed features variables)
+// ------------------------------------------------------------------
+
+//== Badges
+.badge {
+ margin: 1px 2px 1px 0;
+ padding-top: 0;
+ padding-bottom: 0;
+}
+
+//== Buttons
+// Mixin to define variations for btn-links and muted btn-links
+.o-btn-link-variant(@color, @color-active) {
+ text-transform: none;
+ .o-hover-text-color(@default-color: @color, @hover-color: @color-active);
+
+ &, &:hover, &:focus, &:active, &.active {
+ border-color: transparent;
+ background-color: transparent
+ }
+
+ &.text-muted, .text-muted {
+ .o-hover-opacity();
+ .o-hover-text-color(@default-color: @text-muted, @hover-color: @color-active);
+ }
+}
+.btn-icon {
+ .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);
+}
+.btn-link {
+ font-weight: @btn-font-weight;
+
+ &.btn-default {
+ .o-btn-link-variant(@text-color, @headings-color);
+ }
+ &.btn-success, &.text-success {
+ .o-btn-link-variant(@text-color, @brand-success);
+ }
+ &.btn-warning, &.text-warning {
+ .o-btn-link-variant(@text-color, @brand-warning);
+ }
+ &.btn-danger, &.text-danger {
+ .o-btn-link-variant(@text-color, @brand-danger);
+ }
+ &.btn-info, &.text-info {
+ .o-btn-link-variant(@text-color, darken(@brand-info, 20%));
+ }
+}
+
+//== Printing improvements
+@media print {
+ .table-responsive {
+ overflow-x: initial;
+ }
+}
+
+@icon-font-path: "/web/static/lib/bootstrap/fonts/";
diff --git a/addons/web/static/src/scss/control_panel.scss b/addons/web/static/src/scss/control_panel.scss
new file mode 100644
index 00000000000..325ed25b3ac
--- /dev/null
+++ b/addons/web/static/src/scss/control_panel.scss
@@ -0,0 +1,133 @@
+@breadcrumb-height: 30px;
+
+.o_control_panel {
+ .o-flex-display();
+ .o-flex-flow(row, wrap);
+ border-bottom: 1px solid darken(@odoo-control-panel-background-color, 20%);
+ .o-webclient-padding(@top: 10px, @bottom: 10px);
+ background-color: @odoo-control-panel-background-color;
+
+ > .breadcrumb {
+ width: 50%;
+ margin: 0px;
+ font-size: 18px;
+
+ > li {
+ .o-text-overflow(@max-width: 90%);
+
+ > a {
+ cursor: pointer;
+ }
+ }
+ }
+
+ &.o_breadcrumb_full > .breadcrumb {
+ width: 100%;
+ }
+
+ > .o_cp_searchview {
+ width: 50%;
+ min-height: @breadcrumb-height;
+ }
+
+ .btn.o_enable_searchview {
+ width: 10%;
+ margin-left: 2%;
+ padding: 0px;
+ }
+
+ > .o_cp_left {
+ .o-flex-display();
+ .o-justify-content(space-between);
+ width: 50%;
+ margin-top: 5px;
+
+ > .o_cp_sidebar {
+ padding-right: 10px;
+
+ .o_hidden_input_file {
+ position: relative;
+ input.o_input_file {
+ position: absolute;
+ top: 1px;
+ opacity: 0;
+ width: 100%;
+ height: 26px;
+ }
+ .o_form_binary_form span {
+ padding: 3px 25px;
+ color: @btn-default-color;
+ }
+ .o_form_binary_form:hover {
+ background-color: @table-bg-hover;
+ }
+ }
+ .o_sidebar_delete_attachment {
+ padding: 0px;
+ position: absolute;
+ top: 5px;
+ right: 10px;
+ }
+ }
+ }
+
+ > .o_cp_right {
+ .o-flex-display();
+ width: 50%;
+ margin-top: 5px;
+
+ > .o_cp_pager {
+ margin: auto 0 auto auto;
+ padding-left: 5px;
+ text-align: center;
+ .user-select(none);
+
+ > div {
+ .o-flex-display();
+ .o-align-items(center);
+ }
+
+ .o_pager_counter {
+ margin-right: 5px;
+ }
+ }
+
+ > .o_cp_switch_buttons > .btn:first-child {
+ margin-left: @odoo-horizontal-padding;
+ }
+ }
+}
+
+.o_x2m_control_panel {
+ .o-flex-display();
+ .o-flex-flow(row, wrap);
+
+ .o_cp_buttons {
+ .o-flex-display();
+ margin-right: auto;
+ > div {
+ margin-top: 5px;
+ }
+ }
+ .o_cp_pager {
+ .o-flex-display();
+ margin-left: auto;
+ }
+}
+
+// Pager input (to edit pager values)
+.o_pager_value > input {
+ display: inline-block;
+ width: 60px;
+ text-align: right;
+
+ &:focus {
+ outline: none;
+ }
+}
+
+@media print {
+ .o_control_panel {
+ display: none;
+ }
+}
diff --git a/addons/web/static/src/scss/data_export.scss b/addons/web/static/src/scss/data_export.scss
new file mode 100644
index 00000000000..01a1da80134
--- /dev/null
+++ b/addons/web/static/src/scss/data_export.scss
@@ -0,0 +1,109 @@
+.o_web_client .o_export {
+ .o-flex(1, 1, auto);
+ .o-flex-display();
+ .o-flex-flow(column, nowrap);
+ min-height: 0;
+
+ > p, > .row {
+ .o-flex(0, 0, auto);
+ }
+
+ label {
+ vertical-align: top;
+ font-weight: normal;
+ }
+
+ .o_import_compat, .o_export_format {
+ display: inline-block;
+
+ > div {
+ margin-left: 5px;
+ .o-inline-flex-display();
+ .o-align-items(center);
+
+ > label, > input {
+ margin: 0 0 0 5px;
+ }
+ }
+ }
+
+ .o_export_panel {
+ .o-flex(1, 1, auto);
+ position: relative;
+ min-height: 0;
+
+ > div {
+ height: 100%;
+ .o-flex-display();
+ .o-flex-flow(column, nowrap);
+ .o-justify-content(center);
+
+ &.o_left_panel { // Needed because of chrome
+ .o-position-absolute(@top: 0, @bottom: 0, @left: 0, @right: 57%);
+ }
+ &.o_center_panel { // Needed because of chrome
+ .o-position-absolute(@top: 0, @bottom: 0, @left: 43%, @right: 43%);
+ }
+ &.o_right_panel { // Needed because of chrome
+ .o-position-absolute(@top: 0, @bottom: 0, @left: 57%, @right: 0);
+ }
+
+ > h4, > div {
+ .o-flex(0, 0, auto);
+ }
+
+ > button {
+ .o-flex(0, 0, auto);
+ margin-top: 10px;
+ }
+
+ .o_left_field_panel, .o_fields_list {
+ border: 1px solid @odoo-brand-lightsecondary;
+ overflow: auto;
+ .o-flex(1, 1, auto);
+ min-height: 0;
+ }
+
+ .o_export_tree_item {
+ cursor: pointer;
+ position: relative;
+ padding-left: 20px;
+ .user-select(none);
+
+ &.o_selected > .o_tree_column {
+ background-color: @odoo-brand-primary;
+ color: white;
+ }
+
+ .o_expand_parent {
+ .o-position-absolute(@top: 4px, @left: 5px);
+ }
+ .o_tree_column {
+ display: block;
+
+ &.o_required {
+ border-bottom: 2px solid @odoo-main-text-color;
+ }
+ }
+
+ &:focus {
+ outline: none;
+ }
+ }
+
+ .o_save_list, .o_exported_lists {
+ .o-flex-display();
+ .o-align-items(baseline);
+
+ > label, > button {
+ margin: 0 0 5px;
+ .o-flex(0, 0, auto);
+ }
+ > input, > select {
+ width: 0;
+ .o-flex(1, 0, auto);
+ }
+ }
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/datepicker.scss b/addons/web/static/src/scss/datepicker.scss
new file mode 100644
index 00000000000..fdf3a585b57
--- /dev/null
+++ b/addons/web/static/src/scss/datepicker.scss
@@ -0,0 +1,78 @@
+@odoo-datepicker-week-color: #8f8f8f;
+@odoo-datepicker-week-bg-color: lighten(@odoo-datepicker-week-color, 30%);
+
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ margin: -1px;
+ padding: 0;
+ overflow: hidden;
+ clip: rect(0,0,0,0);
+ border: 0;
+}
+
+.o_datepicker {
+ position: relative;
+
+ .o_datepicker_input {
+ width: 100%;
+ cursor: pointer;
+ }
+
+ .o_datepicker_button {
+ .o-position-absolute(2px, 4px);
+ pointer-events: none; // let click events go through the underlying input
+ &:after {
+ .o-caret-down;
+ }
+ }
+}
+
+// Need to put datetimepicker widget above everything else
+// The '.dropdown-menu' part is needed to override default bootstrap rule as
+// this file is unfortunately placed in common assets.
+.bootstrap-datetimepicker-widget.dropdown-menu {
+ z-index: @zindex-modal + 1;
+}
+
+.datepicker {
+ .table-condensed {
+ > thead {
+ color: white;
+ background-color: @odoo-brand-primary;
+
+ > tr {
+ &:first-child {
+ th:hover {
+ color: white;
+ background-color: darken(@odoo-brand-primary, 10%);
+ }
+ }
+
+ &:last-child {
+ color: @odoo-datepicker-week-color;
+ background-color: @odoo-datepicker-week-bg-color;
+ }
+ > th {
+ border-radius: 0;
+ }
+ }
+ }
+
+ > tbody {
+ > tr {
+ > td {
+ &.active, .active {
+ background-color: @odoo-brand-optional;
+ border-radius: 100px;
+ }
+
+ &.today:before {
+ border-bottom-color: @odoo-brand-optional;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/debug_manager.scss b/addons/web/static/src/scss/debug_manager.scss
new file mode 100644
index 00000000000..74d20dda43a
--- /dev/null
+++ b/addons/web/static/src/scss/debug_manager.scss
@@ -0,0 +1,8 @@
+.modal {
+ .o_debug_manager {
+ position: relative;
+ list-style: none;
+ margin: 2px 10px 2px 0;
+ float: left;
+ }
+}
diff --git a/addons/web/static/src/scss/domain_selector.scss b/addons/web/static/src/scss/domain_selector.scss
new file mode 100644
index 00000000000..70d4c0bd0c8
--- /dev/null
+++ b/addons/web/static/src/scss/domain_selector.scss
@@ -0,0 +1,204 @@
+
+.o_domain_node {
+ @o-domain-selector-indent: 32px;
+ @o-domain-selector-panel-space: 60px;
+ @o-domain-selector-row-height: 35px; // should be greater than a "normal" row so that "header" parts are the same size of rows
+ @o-domain-animation-bar-height: 15px;
+
+ position: relative;
+
+ // Rows in a domain node (selector) have a minimum height and holds the control panel
+ .o_domain_selector_row {
+ .o-flex-display();
+ .o-align-items(center);
+ min-height: @o-domain-selector-row-height;
+
+ > * {
+ .o-flex(0, 0, auto);
+ }
+
+ > .o_domain_node_control_panel {
+ .o-position-absolute(@top: 0, @bottom: 0, @right: -@o-domain-selector-panel-space);
+
+ > button {
+ float: left;
+ width: @o-domain-selector-panel-space/2;
+ height: 100%;
+ padding: 0;
+ background-color: transparent;
+ font-size: 16px;
+ opacity: 0.2;
+ cursor: pointer;
+
+ &.o_domain_delete_node_button {
+ font-size: 12px;
+ padding-left: 5px;
+
+ &:hover {
+ color: @brand-danger;
+ }
+ }
+ }
+ }
+ }
+
+ // Rules specific to domain parts which contain sub-domain parts
+ &.o_domain_tree {
+ > .o_domain_tree_header {
+ position: relative;
+
+ .o_domain_tree_operator_caret::after {
+ .o-caret-down();
+ }
+ }
+
+ > .o_domain_node_children_container {
+ padding-left: @o-domain-selector-indent;
+ }
+
+ // Rules specific to domain root
+ &.o_domain_selector {
+ > .o_domain_tree_header {
+ min-height: 22px; // prevents "records button" to overflow 1-row domain
+ }
+
+ > .o_domain_node_children_container {
+ padding-left: 0;
+ }
+
+ &.o_edit_mode > .o_domain_node_children_container {
+ padding-right: @o-domain-selector-panel-space; // delete button is over the row
+ }
+
+ > .o_domain_debug_container {
+ display: block;
+ margin-top: 16px;
+ padding: 8px 10px 12px;
+ background: @gray-dark;
+ color: fade(white, 50%);
+ font-family: monospace;
+ font-weight: normal;
+
+ > input {
+ border: none;
+ padding-top: 8px;
+ background: transparent;
+ color: white;
+ }
+ }
+ }
+ }
+
+ // Rules specific to domain parts which do not contain sub-domain parts
+ &.o_domain_leaf {
+ &.o_read_mode {
+ .o-inline-flex-display();
+ margin-right: 4px;
+ }
+
+ > .o_domain_leaf_info {
+ background: @odoo-brand-lightsecondary;
+ border: 1px solid darken(@odoo-brand-lightsecondary, 10%);
+ padding: 2px 4px;
+
+ > .o_field_selector {
+ float: left;
+ margin-right: 4px;
+
+ > .o_field_selector_value > .o_field_selector_chain_part {
+ border: none;
+ font-weight: 700;
+ }
+ }
+ .o_domain_leaf_operator {
+ font-style: italic;
+ }
+ .o_domain_leaf_value {
+ font-weight: 700;
+ }
+ }
+
+ > .o_domain_leaf_edition {
+ .o-flex-display();
+ width: 100%;
+ padding: 4px (@o-domain-selector-panel-space/2) 4px 0;
+
+ > * {
+ .o-flex(1, 1, 15%); // operator select
+ width: auto;
+ background-color: white;
+
+ &:first-child { // field selector
+ .o-flex(0, 1, 55%);
+ }
+
+ &:last-child { // field value
+ .o-flex(1, 1, 25%);
+ }
+
+ + * {
+ margin-left: 4px;
+ }
+
+ input, select, .o_datepicker, .o_datepicker_input {
+ height: 100%;
+ }
+ }
+
+ .o_domain_leaf_value_tags {
+ .o-flex-display();
+
+ > * {
+ .o-flex(0, 0, auto);
+ }
+ > input {
+ .o-flex(1, 1, auto);
+ width: 0;
+ min-width: 50px;
+ }
+ .o_domain_leaf_value_remove_tag_button {
+ cursor: pointer;
+ }
+ }
+ }
+ }
+
+ // Animation effects
+ .o-transition(margin-bottom, .05s, ease, .05s);
+
+ &::after {
+ content: "";
+ .o-position-absolute(@left: 0, @right: 0, @top: 100%);
+ display: block;
+ height: @o-domain-animation-bar-height;
+ max-height: 0;
+ .o-linear-gradient(45deg, fade(@odoo-brand-optional, 40%), fade(@odoo-brand-optional, 10%));
+ .o-transition(max-height, .05s, ease, .05s);
+ }
+
+ &.o_hover_btns, &.o_hover_add_node {
+ .o_domain_node_control_panel > button {
+ opacity: 0.5;
+ &:hover {
+ opacity: 1.0;
+ }
+ }
+ }
+
+ &.o_hover_btns {
+ background: darken(white, 3%);
+ }
+
+ &.o_hover_add_node {
+ margin-bottom: @o-domain-animation-bar-height;
+ .o-transition(margin, .15s, ease, .5s);
+
+ &::after {
+ max-height: @o-domain-animation-bar-height;
+ .o-transition(max-height, .15s, ease, .5s);
+ }
+ &.o_hover_add_inset_node::after {
+ left: @o-domain-selector-indent;
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/dropdown.scss b/addons/web/static/src/scss/dropdown.scss
new file mode 100644
index 00000000000..6501b4cc52c
--- /dev/null
+++ b/addons/web/static/src/scss/dropdown.scss
@@ -0,0 +1,80 @@
+.li-a-padding {
+ padding: 3px @odoo-dropdown-hpadding;
+}
+
+.ui-autocomplete { // Copy style of bootstrap dropdown
+ background-image: none;
+ background-color: @dropdown-bg;
+ border: 1px solid @dropdown-border;
+ font-size: @font-size-base;
+ padding: 5px 0px;
+ box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.176);
+
+ .ui-menu-item {
+ padding: 0;
+ > a {
+ display: block;
+ color: @dropdown-link-color;
+
+ .li-a-padding
+ }
+
+ &.ui-state-focus {
+ background-image: none;
+ background-color: @odoo-brand-primary;
+ border: none;
+ font-weight: normal;
+ margin: 0;
+ }
+ &.o_m2o_dropdown_option {
+ padding-left: 20px;
+ > a {
+ color: @odoo-brand-primary;
+ }
+ }
+ }
+}
+
+.dropdown-menu {
+ box-shadow: 0 6px 12px -4px fade(black, 25%);
+
+ .o_inline_dropdown {
+ position: relative;
+
+ &> .dropdown-menu {
+ top: 0;
+ left: 100%;
+ }
+ &:hover > .dropdown-menu {
+ display: block;
+ }
+ }
+}
+
+.dropdown-menu-mixin {
+ .open .dropdown-menu > li {
+ position: relative; // to allow absolute positionning inside the li
+ > a {
+ &:focus, &:active, &:focus:active {
+ outline: none;
+ }
+
+ .li-a-padding;
+ }
+
+ &.dropdown-header {
+ .li-a-padding;
+ color: @odoo-main-text-color;
+
+ @media (max-width: @screen-xs-max) {
+ color: white;
+ text-decoration: underline;
+ }
+ }
+ }
+}
+
+.dropdown-menu-mixin();
+.navbar-nav {
+ .dropdown-menu-mixin();
+}
diff --git a/addons/web/static/src/scss/dropdown_extra.scss b/addons/web/static/src/scss/dropdown_extra.scss
new file mode 100644
index 00000000000..ec38e6d5292
--- /dev/null
+++ b/addons/web/static/src/scss/dropdown_extra.scss
@@ -0,0 +1,63 @@
+.ui-autocomplete .ui-menu-item {
+ &.ui-state-focus {
+ background-color: @odoo-brand-primary;
+ }
+ &.o_m2o_dropdown_option > a {
+ color: @odoo-brand-primary;
+ }
+ &.ui-state-focus > a,
+ &.ui-state-focus.o_m2o_dropdown_option > a {
+ color: white;
+ }
+}
+
+@tag-border: #afafb6;
+.oe_dropdown, .oe_dropdown_toggle {
+ position: relative;
+ cursor: pointer;
+}
+.oe_dropdown_toggle {
+ color: #2B2B2B;
+ font-weight: normal;
+}
+.oe_dropdown_menu {
+ display: none;
+ position: absolute;
+ z-index: 3;
+ margin: 0;
+ border: 1px solid @tag-border;
+ background: white;
+ padding: 4px 0;
+ min-width: 140px;
+ text-align: left;
+ box-shadow: 0 1px 4px rgba(0,0,0,0.3);
+ &.oe_opened {
+ display: block;
+ }
+ > li {
+ list-style-type: none;
+ float: none;
+ display: block;
+ position: relative;
+ margin: 0;
+ padding: 2px 8px;
+ &:hover {
+ .o-vertical-gradient(#f0f0fa, #eeeef6);
+ box-shadow: none;
+ }
+ > a {
+ white-space: nowrap;
+ display: block;
+ color: #4c4c4c;
+ text-decoration: none;
+ &:hover {
+ text-decoration: none;
+ }
+ }
+ }
+}
+
+// Buttons used as dropdown toggler
+.o_dropdown_toggler_btn {
+ .btn-default;
+}
diff --git a/addons/web/static/src/scss/fields.scss b/addons/web/static/src/scss/fields.scss
new file mode 100644
index 00000000000..ff6fe9eb20b
--- /dev/null
+++ b/addons/web/static/src/scss/fields.scss
@@ -0,0 +1,385 @@
+//
+// This file regroups all the rules which apply to field widgets wherever they
+// are in the DOM, in both community and enterprise versions.
+//
+
+// Invalid
+.o_field_invalid {
+ &.o_input, .o_input, &.o_form_label {
+ color: @brand-danger!important;
+ border-color: @brand-danger!important; // enterprise o_required_modifier rule overrides this without !important
+ }
+}
+
+// Empty
+.o_field_empty {
+ display: none!important;
+}
+
+// Numbers
+.o_field_number {
+ white-space: nowrap;
+}
+
+//------------------------------------------------------------------------------
+// Fields
+//------------------------------------------------------------------------------
+
+.o_field_widget {
+ // Default display and alignment of widget and internal <input/>
+ &, input.o_input {
+ display: inline-block;
+ text-align: inherit;
+ }
+
+ // Block fields
+ &.note-editor, &.oe_form_field_html, &.oe_form_field_html_text, &.oe_form_field_text, &.o_field_domain, &.o_graph_linechart, &.o_graph_barchart {
+ display: block;
+ }
+
+ // Flex fields (inline)
+ &.o_field_many2one, &.o_field_radio, &.o_field_many2manytags, &.o_field_percent_pie, &.o_field_monetary, &.o_field_binary_file {
+ @media (min-width: @screen-sm-min) {
+ .o-inline-flex-display();
+ }
+ > span, > button {
+ .o-flex(0, 0, auto);
+ }
+ }
+
+ // Dropdowns input (many2one, ...)
+ .o_input_dropdown {
+ .o-flex(1, 1, auto);
+ position: relative;
+ width: 100%;
+
+ > input {
+ height: 100%;
+ padding-right: 15px;
+ cursor: pointer;
+ }
+
+ .o_dropdown_button {
+ .o-position-absolute(0, 0);
+ pointer-events: none;
+ &:after {
+ .o-caret-down;
+ }
+ }
+ }
+
+ // Text
+ &.o_field_text, &.oe_form_field_text .oe_form_text_content {
+ width: 100%;
+ white-space: pre-wrap;
+ }
+
+ // Monetary
+ &.o_field_monetary {
+ &.o_input {
+ .o-align-items(baseline);
+
+ > input {
+ width: 100px;
+ .o-flex(1, 0, auto);
+ }
+ }
+ }
+
+ // Many2many tags
+ &.o_field_many2manytags {
+ .o-flex-flow(row, wrap);
+ .o-align-items(baseline);
+
+ > .o_field_widget {
+ .o-flex(1, 0, 100px);
+ position: initial;
+ max-width: 100%;
+ }
+
+ > .badge {
+ .o-flex(0, 0, auto);
+ border: 0;
+ font-size: 12px;
+ color: white;
+ cursor: pointer;
+
+ > .o_badge_text {
+ .o-text-overflow(inline-block);
+ max-width: 200px;
+ }
+
+ // o-kanban-colorpicker without customizing
+ // '&:first-child > a::before' (transparent red-crossed colorpick)
+ .o-tag-colorpicker() {
+ @o-tag-colorpicker-padding-right: @odoo-dropdown-hpadding - 2 * @o-kanban-inner-hmargin;
+
+ max-width: 100%;
+ padding: 3px @o-tag-colorpicker-padding-right 3px @odoo-dropdown-hpadding;
+
+ > li {
+ display: inline-block;
+ margin: @o-kanban-inner-hmargin @o-kanban-inner-hmargin 0 0;
+ border: 1px solid white;
+ box-shadow: 0 0 0 1px @gray-lighter-dark;
+
+ > a {
+ display: block;
+
+ &::after {
+ content: "";
+ display: block;
+ width: 20px;
+ height: 15px;
+ }
+ }
+
+ &:last-of-type {
+ box-shadow: 0 0 0 0px white; // remove grey border on hide in kanban
+ color: @odoo-main-text-color;
+ }
+ }
+ }
+
+ > .tagcolor_dropdown_menu {
+ min-width: 150px; // down from 160px of .dropdown-menu
+ margin-right: 0px; // cancel right margin of .dropdown-menu
+ }
+
+ > .o_colorpicker > ul {
+ .o-tag-colorpicker();
+ white-space: normal;
+ }
+
+ .o_delete {
+ cursor: pointer;
+ }
+ }
+
+ .o-tag-color(@size: 0) when (@size = 0) {
+ .o_tag_color_@{size} {
+ & {
+ background-color: white;
+ color: ~"@{odoo-color-@{size}}";
+ box-shadow: inset 0 0 0 2px ~"@{odoo-color-@{size}}";
+ }
+ &::after {
+ background-color: ~"@{odoo-color-@{size}}";
+ }
+ }
+ .o-tag-color(@size + 1);
+ }
+ .o-tag-color(@size: 0) when (@size > 0) and (@size < @odoo-nb-ui-color) {
+ .o_tag_color_@{size} {
+ &, &::after {
+ background-color: ~"@{odoo-color-@{size}}";
+ }
+ }
+ .o-tag-color(@size + 1);
+ }
+ .o-tag-color();
+ }
+
+ // Stars
+ &.o_priority {
+ display: inline-block;
+ padding: 0;
+ margin: 0;
+ vertical-align: baseline;
+ > .o_priority_star {
+ display: inline-block;
+ font-size: 1.35em;
+ &:hover, &:focus {
+ text-decoration: none;
+ outline: none;
+ }
+
+ + .o_priority_star {
+ padding-left: 5px;
+ }
+
+ &.fa-star-o {
+ color: @odoo-main-color-muted;
+ }
+ &.fa-star {
+ color: gold;
+ }
+ }
+ }
+
+ // Favorite
+ &.o_favorite {
+ i.fa {
+ font-size: 16px;
+ }
+ i.fa-star-o {
+ color: @odoo-main-color-muted;
+ &:hover {
+ color: gold;
+ }
+ }
+ i.fa-star {
+ color: gold;
+ }
+ }
+
+ // Specific success color for toggle_button widget
+ .fa.o_toggle_button_success {
+ color: @brand-success;
+ }
+
+ // Handle widget
+ &.o_row_handle {
+ cursor: ns-resize;
+ }
+
+ // Radio buttons
+ &.o_field_radio {
+ .o_radio_input {
+ outline: none;
+ }
+
+ .o_radio_item {
+ .o-flex(0, 0, auto);
+ .o-flex-display();
+ .o-align-items(center);
+
+ > input {
+ .o-flex(0, 0, auto);
+ margin: 0 @odoo-form-spacing-unit 0 0;
+ }
+ > label {
+ margin: 0;
+ }
+ }
+
+ &.o_horizontal {
+ .o_radio_item {
+ margin-right: @odoo-form-spacing-unit * 2;
+ }
+ }
+
+ &.o_vertical {
+ .o-flex-flow(column, nowrap);
+ .o_radio_item {
+ margin-bottom: @odoo-form-spacing-unit;
+ }
+ }
+ }
+
+ // Percent pie
+ &.o_field_percent_pie {
+ .o-align-items(center);
+
+ > .o_pie {
+ position: relative;
+ display: inline-block;
+ vertical-align: middle;
+ margin-right: 10px;
+ border-radius: 100%;
+ overflow: hidden;
+ background-color: @odoo-brand-optional;
+
+ &:after { // Outside pie border to go over border-radius irregularities
+ content: " ";
+ .o-position-absolute(0, 0);
+ width: 100%;
+ height: 100%;
+ border-radius: 100%;
+ }
+
+ .o_mask {
+ .o-position-absolute(0, 0);
+ .o-transform-origin(0);
+ width: 50%;
+ height: 100%;
+ background-color: @odoo-view-background-color;
+ &.o_full {
+ background-color: inherit;
+ }
+ }
+
+ .o_pie_value {
+ .o-flex-display();
+ .o-justify-content(center);
+ .o-align-items(center);
+
+ border-radius: 100%;
+
+ font-weight: 700;
+ color: @odoo-brand-primary;
+ }
+ }
+ }
+
+ // Ace editor
+ &.o_ace_view_editor {
+ width: 100%;
+ .ace-view-editor {
+ height: 300px;
+ padding: 0 1em;
+ }
+ }
+
+ // Image
+ &.o_field_image {
+ position: relative;
+
+ .o_form_image_controls {
+ .o-position-absolute(0, 0);
+ width: 100%;
+
+ color: white;
+ background-color: @odoo-brand-optional;
+ opacity: 0;
+ transition: opacity ease 400ms;
+
+ > .fa {
+ margin: 5px;
+ cursor: pointer;
+ }
+ }
+ @media (max-width: @screen-xs-min) {
+ .o_form_image_controls{
+ position: initial;
+ opacity: 1;
+ > .fa{
+ width: 50%;
+ padding: 6px;
+ margin: 0px;
+ text-align: center;
+ &.o_select_file_button{
+ background: @odoo-brand-optional;
+ }
+ &.o_clear_file_button{
+ background: @brand-danger;
+ }
+ }
+ }
+ }
+
+ &:hover .o_form_image_controls {
+ opacity: 0.8;
+ }
+ }
+
+ // Input loading/file
+ .o_form_binary_progress, .o_hidden_input_file .o_input_file {
+ display: none;
+ }
+
+ // Domain
+ &.o_field_domain {
+ > .o_field_domain_panel {
+ margin-top: 8px;
+ }
+ &.o_inline_mode.o_edit_mode {
+ position: relative;
+
+ > .o_field_domain_panel {
+ .o-position-absolute(0, 0);
+ margin-top: 0;
+ }
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/fields_extra.scss b/addons/web/static/src/scss/fields_extra.scss
new file mode 100644
index 00000000000..577cfacacb4
--- /dev/null
+++ b/addons/web/static/src/scss/fields_extra.scss
@@ -0,0 +1,59 @@
+//
+// This file regroups all the rules which apply to field widgets wherever they
+// are in the DOM, in the community version.
+//
+
+// Required
+.o_required_modifier {
+ &.o_input, .o_input {
+ background-color: #D2D2FF!important;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Fields
+//------------------------------------------------------------------------------
+
+.o_field_widget {
+ // Dropdowns input carret
+ .o_input_dropdown .o_dropdown_button {
+ .o-position-absolute(2px, 4px);
+ }
+
+ // Many2one
+ &.o_field_many2one .o_external_button {
+ padding: 0;
+ margin-left: 2px;
+ font-size: 19px;
+ color: #7C7BAD;
+ border: none;
+ &:hover {
+ background-color: transparent;
+ }
+ }
+
+ // Percent pie field
+ &.o_field_percent_pie {
+ @pie-dimension: 34px;
+ @pie-ring-width: 4px;
+
+ .o_pie {
+ width: @pie-dimension;
+ height: @pie-dimension;
+ margin-left: 5px;
+
+ &:after { // Outside pie border to go over border-radius irregularities
+ border: 1px solid @odoo-brand-primary;
+ }
+
+ .o_pie_value {
+ .o-position-absolute(@pie-ring-width, @pie-ring-width);
+ width: @pie-dimension - 2 * @pie-ring-width;
+ height: @pie-dimension - 2 * @pie-ring-width;
+ border: 1px solid white;
+ background-color: white;
+ font-size: 10px;
+ }
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/fonts.scss b/addons/web/static/src/scss/fonts.scss
new file mode 100644
index 00000000000..c6b19a2ba2f
--- /dev/null
+++ b/addons/web/static/src/scss/fonts.scss
@@ -0,0 +1,37 @@
+// ------------------------------------------------------------------
+// Lato
+// ------------------------------------------------------------------
+@lato-font-path: '../fonts/lato';
+
+.lato-font(@type, @weight, @style) {
+ @font-face {
+ font-family: 'Lato';
+ src: url('@{lato-font-path}/Lato-@{type}-webfont.eot');
+ src: url('@{lato-font-path}/Lato-@{type}-webfont.eot?#iefix') format('embedded-opentype'),
+ url('@{lato-font-path}/Lato-@{type}-webfont.woff') format('woff'),
+ url('@{lato-font-path}/Lato-@{type}-webfont.ttf') format('truetype'),
+ url('@{lato-font-path}/Lato-@{type}-webfont.svg#Lato') format('svg');
+ font-weight: @weight;
+ font-style: @style;
+ }
+
+ @font-face {
+ font-family: 'Lato-@{type}';
+ src: url('@{lato-font-path}/Lato-@{type}-webfont.eot');
+ src: url('@{lato-font-path}/Lato-@{type}-webfont.eot?#iefix') format('embedded-opentype'),
+ url('@{lato-font-path}/Lato-@{type}-webfont.woff') format('woff'),
+ url('@{lato-font-path}/Lato-@{type}-webfont.ttf') format('truetype'),
+ url('@{lato-font-path}/Lato-@{type}-webfont.svg#Roboto') format('svg');
+ }
+}
+
+.lato-font-pair(@type, @weight) {
+ .lato-font('@{type}', @weight, normal);
+ .lato-font('@{type}Ita', @weight, italic);
+}
+
+.lato-font-pair('Hai', 100);
+.lato-font-pair('Lig', 300);
+.lato-font-pair('Reg', 400);
+.lato-font-pair('Bol', 700);
+.lato-font-pair('Bla', 900);
diff --git a/addons/web/static/src/scss/form_view.scss b/addons/web/static/src/scss/form_view.scss
new file mode 100644
index 00000000000..1e477aac02d
--- /dev/null
+++ b/addons/web/static/src/scss/form_view.scss
@@ -0,0 +1,747 @@
+.o_form_view {
+ background-color: @odoo-view-background-color;
+
+ // Utility classes
+ .oe_form_box_info {
+ .bg-info;
+ .o-webclient-padding(@top: 5px, @bottom: 5px);
+ > p {
+ margin: auto;
+ }
+ }
+ .oe_text_center {
+ text-align: center;
+ }
+ .oe_grey {
+ opacity: 0.5;
+ }
+ .oe_inline {
+ width: auto!important;
+ @media (min-width: @screen-xs-min) {
+ &.o_inner_group {
+ width: 1px!important;
+ }
+ }
+ }
+ .oe_left {
+ .oe_inline;
+ float: left!important;
+ }
+ .oe_right {
+ .oe_inline;
+ float: right!important;
+ }
+
+ @media (min-width: @screen-xs-min) {
+ .o_row {
+ &, &.o_field_widget { // Some field may want to use o_row as root and these rules must prevalue
+ .o-flex-display();
+ width: auto!important;
+ }
+
+ .o-align-items(baseline);
+ min-width: 50px;
+ margin: 0 -@odoo-form-spacing-unit/2;
+
+ > div, > span, > button, > label, > a, > input { // > * did not add a level of priority to the rule
+ .o-flex(0, 0, auto);
+ width: auto!important;
+ margin-right: @odoo-form-spacing-unit/2;
+ margin-left: @odoo-form-spacing-unit/2;
+ }
+
+ > .o_row {
+ margin: 0;
+ }
+ > .btn {
+ padding-top: 0;
+ padding-bottom: 0;
+ }
+ > .o_field_boolean {
+ .o-align-self(center);
+ }
+ }
+ }
+
+ .o_row > div > .o_field_widget {
+ width: 100%;
+ }
+
+ // Readonly specific rules
+ &.o_form_readonly {
+ .oe_edit_only {
+ display: none!important;
+ }
+
+ .o_row, .o_row > div {
+ display: inline-block;
+ }
+
+ }
+
+ .o_form_uri {
+ display: inline-block;
+
+ color: @odoo-main-text-color;
+ &:first-line {
+ color: @link-color;
+ }
+ &:hover {
+ color: darken(@odoo-main-text-color, 1%); // hack required on chrome
+ &:first-line {
+ color: darken(@link-color, 15%);
+ }
+ }
+ }
+
+ // Editable specific rules
+ &.o_form_editable {
+ .oe_read_only {
+ display: none!important;
+ }
+
+ .oe_title {
+ max-width: @container-sm - (2 * @odoo-horizontal-padding);
+ }
+
+ @media (min-width: @screen-xs-min) {
+ .o_row {
+ > .o_field_widget, > div {
+ .o-flex(1, 1, auto);
+ width: 0!important; // 3rd flex argument does not work with input (must be auto and real width 0)
+
+ &.o_field_boolean, &.o_priority {
+ .o-flex(0, 0, auto);
+ width: auto!important;
+ }
+ }
+ }
+ }
+ }
+
+ // No sheet
+ &.o_form_nosheet {
+ display: block;
+ .o-webclient-padding(@top: @odoo-sheet-vpadding, @bottom: @odoo-sheet-vpadding);
+
+ .o_form_statusbar {
+ margin: -@odoo-sheet-vpadding -@odoo-horizontal-padding @odoo-sheet-vpadding -@odoo-horizontal-padding;
+ }
+ }
+
+ // Non-chatter rules
+ .o_form_sheet_bg {
+ position: relative;
+
+ > .o_form_sheet {
+ margin: @odoo-sheet-vpadding auto;
+ }
+ }
+
+ // Statusbar
+ .o_form_statusbar {
+ position: relative; // Needed for the "More" dropdown
+ .o-flex-display();
+ .o-justify-content(space-between);
+ padding-left: @odoo-horizontal-padding;
+ border-bottom: 1px solid @gray-lighter-darker;
+ background-color: @odoo-view-background-color;
+
+ > .o_statusbar_buttons, > .o_statusbar_status {
+ .o-flex-display();
+ .o-align-items(center);
+ .o-align-content(space-around);
+ }
+
+ > .o_field_widget {
+ .o-align-self(center);
+ margin-bottom: 0px;
+ }
+
+ > .o_statusbar_buttons {
+ .o-flex-flow(row, wrap);
+
+ > .btn {
+ @o-statusbar-buttons-vmargin: 4px;
+ min-height: @odoo-statusbar-height - 2 * @o-statusbar-buttons-vmargin;
+ margin: @o-statusbar-buttons-vmargin 3px @o-statusbar-buttons-vmargin 0;
+ padding-top: 2px;
+ padding-bottom: 2px;
+ }
+ }
+
+ > .o_statusbar_status {
+ margin-left: auto;
+ .o-flex-flow(row-reverse, wrap-reverse);
+ .o-align-self(stretch);
+ .o-align-items(stretch);
+ overflow-x: hidden; // to prevent horizontal scroll due to last arrow
+
+ > .o_arrow_button {
+ min-height: @odoo-statusbar-height;
+ font-size: 11px;
+ font-weight: bold;
+ position: relative;
+ padding-left: @odoo-statusbar-arrow-width*2;
+ color: @gray;
+ border-width: 0 0 0;
+ border-radius: 0;
+ .o-transition(all, 0.1s);
+
+ &:first-child {
+ padding-right: @odoo-horizontal-padding; // Compensate container padding
+ }
+ &:last-child {
+ padding-left: @odoo-horizontal-padding - 1;
+ border-left: 1px solid @gray-lighter-darker;
+ }
+
+ &:active {
+ box-shadow: none;
+ }
+
+ &.disabled {
+ opacity: 1.0;
+ color: @text-muted;
+ pointer-events: none;
+ border-left: 1px solid @gray-lighter-dark;
+ }
+
+ &:before, &:after {
+ content: " ";
+ display: block;
+ .o-position-absolute(0, -@odoo-statusbar-arrow-width + 1);
+
+ border-top: floor(@odoo-statusbar-height/2) solid transparent;
+ border-bottom: ceil(@odoo-statusbar-height/2) solid transparent;
+ border-right: none;
+ border-left: @odoo-statusbar-arrow-width solid @odoo-view-background-color;
+ .o-transition(border, 0.2s);
+ -moz-transform: scale(0.9999); // Smooth the triangle on firefox
+ }
+
+ &:not(.disabled) {
+ &:hover, &:active, &:focus {
+ color: @odoo-brand-optional;
+ background-color: @gray-lighter;
+
+ &:after {
+ border-left-color: @gray-lighter;
+ }
+ }
+ }
+
+ &:before {
+ right: -@odoo-statusbar-arrow-width;
+ border-left-color: @gray-lighter-dark;
+ }
+
+ &.btn-primary.disabled {
+ color: @odoo-brand-primary;
+ font-size: 11px;
+ background-color: @gray-lighter;
+ cursor: default;
+
+ &:after {
+ border-left-color: @gray-lighter;
+ }
+ }
+
+ .caret {
+ margin-top: -2px;
+ }
+ }
+
+ .o-status-more {
+ .o-position-absolute(100%, 0);
+ min-width: 100px;
+ > li > button {
+ width: 100%;
+ text-align: left;
+ }
+ }
+ }
+
+ // Touch device mode
+ > .o_statusbar_buttons > .btn-group, > .o_statusbar_status {
+ > .dropdown-toggle {
+ &:after {
+ .o-caret-down();
+ margin-left: @odoo-form-spacing-unit;
+ }
+ }
+
+ > .dropdown-menu {
+ padding: 5px 0 2px 0;
+ min-width: 100px;
+
+ > li > .btn {
+ min-width: 100%;
+ margin-bottom: 3px;
+ }
+ }
+ }
+ }
+
+ // Button box
+ .oe_button_box {
+ .oe_stat_button {
+ &:not(:hover) .o_stat_info > .o_hover {
+ display: none !important;
+ }
+ &:hover .o_stat_info > .o_not_hover {
+ display: none !important
+ }
+ }
+ }
+
+ // Title
+ .oe_title {
+ > h1, > h2, > h3 {
+ width: 100%; // Needed because inline-block when is a hx.o_row
+ margin-top: 0;
+ margin-bottom: 0;
+ line-height: inherit;
+ }
+ .o_priority > .o_priority_star {
+ font-size: inherit;
+ }
+ }
+
+ // Groups
+ .o_group {
+ display: inline-block;
+ width: 100%;
+ margin: 10px 0;
+
+ // o_group contains nested groups
+ .o-generate-groups(@odoo-form-group-cols);
+ .o-generate-groups(@n, @i: 1) when (@i =< @n) {
+ .o_group_col_@{i} {
+ display: inline-block;
+ width: floor(100% / 12 * @i);
+ vertical-align: top;
+ }
+ .o-generate-groups(@n, @i + 1);
+ }
+
+ &.o_inner_group {
+ display: inline-table;
+
+ > tbody > tr > td {
+ &.o_td_label {
+ width: 0%;
+ padding: 0 15px 0 0;
+ min-width: 150px;
+ }
+ vertical-align: top;
+
+ span, .o_field_boolean, .oe_avatar, .o_form_uri {
+ &.o_field_widget {
+ width: auto;
+ }
+ }
+ }
+ }
+
+ .o_form_label {
+ font-weight: normal;
+ }
+
+ .o_field_widget {
+ width: 100%;
+
+ > .btn {
+ .o-flex(0, 0, auto);
+ padding: 0 10px;
+ }
+ }
+
+ :not(.o_row) > .o_field_widget,
+ .o_row > .o_field_widget:last-child { // Note: this does not take care
+ // of an invisible last-child but
+ // it does not really matter
+ // Makes extra buttons (e.g. m2o external button) overflow on the
+ // right padding of the parent element
+ .o_input_dropdown {
+ .o-flex(1, 0, auto);
+ }
+ }
+
+ &.o_label_nowrap .o_form_label {
+ white-space: nowrap;
+ }
+
+ .o_td_label .o_form_label {
+ font-weight: bold;
+ margin-right: 0px;
+ }
+ }
+
+ // Separators
+ .o_horizontal_separator {
+ font-size: @font-size-h2;
+ margin: @odoo-form-spacing-unit 0;
+ &:empty {
+ height: @odoo-form-spacing-unit * 2;
+ }
+ }
+
+ // Notebooks
+ .o_notebook {
+ clear: both; // For the notebook not to have alongside floating elements
+ margin-top: @odoo-form-spacing-unit * 2;
+
+ .nav-tabs > .tab-pane {
+ min-height: 100px;
+ }
+ }
+
+ // Labels
+ .o_form_label {
+ margin: 0 @odoo-form-spacing-unit 0 0;
+ font-size: @font-size-base; // The label muse have the same size whatever their position
+ line-height: @line-height-base;
+ }
+
+ // Form fields
+ .o_field_widget {
+ margin-bottom: @odoo-form-spacing-unit;
+ }
+ .o_field_widget, .btn {
+ .o_field_widget {
+ margin-bottom: 0px;
+ }
+ }
+
+ // Translate icon
+ .o_field_translate {
+ padding: 0;
+ cursor: pointer;
+ width: 12px !important;
+ vertical-align: top;
+ &::before { // seems to be useful for some old browser
+ position: relative;
+ }
+ }
+
+ // Text field with oe_inline class
+ .o_field_text.oe_inline {
+ width: 100%!important;
+ @media (min-width: @screen-xs-min) {
+ width: 45%!important;
+ }
+ }
+
+ // One2Many, Many2Many outside of group
+ .o_field_widget {
+ &.o_field_one2many, &.o_field_many2many {
+ width: 100%;
+ > div {
+ width: 100%;
+ }
+ }
+ }
+
+ // Specific style classes
+ .o_group.o_inner_group.oe_subtotal_footer {
+ .oe_right;
+
+ > tbody > tr > td {
+ padding: 0;
+
+ &.o_td_label {
+ text-align: right;
+ }
+
+ .o_form_label {
+ padding-right: 20px;
+
+ min-width: 0;
+ white-space: nowrap;
+ &:after {
+ content: ":";
+ }
+ }
+
+ .o_field_widget {
+ text-align: right;
+ .o-justify-content(flex-end);
+ width: 100%;
+ }
+ }
+
+ > tbody > tr:first-child > td {
+ padding-top: 4px;
+ }
+
+ .oe_subtotal_footer_separator {
+ width: 100%;
+ text-align: right;
+ border-top: 1px solid @gray-lighter-dark;
+ font-weight: bold;
+ font-size: 1.3em;
+ }
+ }
+
+ .o_address_format {
+ width: 100%;
+ .o_address_street, .o_address_country {
+ .o-flex-display;
+ }
+
+ .o_address_city {
+ margin-right: 2%;
+ }
+ .o_address_state {
+ margin-right: 2%;
+ }
+ &.o_zip_city {
+ .o_address_zip {
+ margin-right: 2%;
+ }
+ .o_address_city {
+ margin-right: 0;
+ }
+ .o_address_state {
+ display: block;
+ margin-right: 0;
+ }
+ }
+ &.o_city_state {
+ .o_address_state {
+ margin-right: 0;
+ }
+ .o_address_zip {
+ display: block;
+ margin-right: 0;
+ }
+ }
+ > span.o_field_widget {
+ width: auto;
+ }
+ }
+ &.o_form_editable .o_address_format {
+ .o_address_city {
+ width: 38%;
+ }
+ div.o_address_state {
+ width: 33%;
+ }
+ input.o_address_zip {
+ width: 25%;
+ }
+ &.o_zip_city {
+ .o_address_zip {
+ width: 38%;
+ }
+ .o_address_city {
+ width: 60%;
+ }
+ .o_address_state {
+ width: 100%;
+ }
+ }
+ &.o_city_state {
+ .o_address_city {
+ width: 50%;
+ }
+ .o_address_state {
+ width: 48%;
+ }
+ .o_address_zip {
+ width: 100%;
+ }
+ }
+ }
+
+ // Boolean
+ .o_field_boolean {
+ margin: 0 @odoo-form-spacing-unit 0 0;
+ }
+
+ // Timezone widget warning
+ .o_tz_warning {
+ color: @brand-danger;
+ cursor: help;
+ position: absolute;
+ margin-left: -40px;
+ margin-top: 5px;
+ }
+
+ // One2Many Kanban views
+ .o_field_widget .o_kanban_view.o_kanban_ungrouped {
+ padding: 0;
+ .o_kanban_record {
+ box-shadow: none;
+ }
+ }
+
+ // One2Many List views
+ .o_field_widget .o_list_view {
+ margin-bottom: 10px;
+
+ > tfoot > tr > td {
+ padding: 3px;
+ color: @odoo-main-text-color;
+ }
+ }
+ &.o_form_readonly .o_field_widget .o_list_view .o_row_handle {
+ display: none; // Hide the handler in non-edit mode
+ }
+
+ // Attachments
+ .oe_attachment {
+ display: inline-block;
+ border: 1px solid @odoo-brand-lightsecondary;
+ margin: 0 @odoo-form-spacing-unit @odoo-form-spacing-unit 0;
+ padding: @odoo-form-spacing-unit;
+ }
+
+ &.oe_form_configuration {
+ .o_group .o_form_label {
+ white-space: nowrap;
+ }
+ h2 {
+ margin-top: 32px !important;
+ }
+ }
+}
+
+// Overriden style when form view in modal
+.modal .modal-dialog {
+ .o_form_view {
+ .o_form_sheet_bg {
+ padding: 0;
+
+ > * {
+ margin: 0;
+ }
+
+ > .o_form_sheet {
+ box-shadow: none;
+ width: 100%;
+ margin: 0 auto;
+ max-width: none;
+ }
+ }
+ .oe_chatter {
+ display: none;
+ }
+ }
+ &:not(.modal-lg) .o_form_view {
+ .o_group {
+ width: 100%;
+ }
+ }
+}
+
+@media print {
+ .oe_button_box, .o_form_statusbar {
+ display: none !important;
+ }
+}
+
+// Buttons in ControlPanel
+.o_control_panel .o_form_buttons_view > button:first-child {
+ float: left; // Unfortunately needed for the bounce effect
+ margin-right: 4px;
+}
+
+// Light labels (not in bold) for settings forms
+label.o_light_label, .o_light_label label {
+ font-weight: normal;
+}
+
+// XXS form view specific rules
+.form-break-table() {
+ display: block;
+ margin-bottom: @odoo-form-spacing-unit * 4;
+
+ > tbody {
+ display: block;
+
+ > tr {
+ .o-flex-display();
+ .o-flex-flow(row, wrap);
+
+ > td {
+ .o-flex(1, 0, auto);
+ display: block;
+ max-width: 100%;
+ padding: 0;
+
+ width: auto!important; // !important is required to override the width computed in JS
+ &.o_td_label {
+ width: 94%!important; // The label must be on its own line except if the form field is small enough (checkbox)
+ line-height: @odoo-label-font-size-factor;
+ }
+
+ .o_field_widget {
+ margin-bottom: @odoo-form-spacing-unit * 2;
+ &.o_field_boolean {
+ margin-right: 0;
+ }
+ }
+
+ .o_input_dropdown {
+ width: auto;
+ max-width: 100%;
+ }
+ }
+ }
+ }
+}
+.o_form_view.o_xxs_form_view {
+ .oe_title {
+ word-break: break-all;
+ }
+ .o_group {
+ &.o_inner_group {
+ .form-break-table();
+ }
+ }
+}
+
+// Settings form views
+.o_settings_container {
+ .o-flex-display();
+ .o-flex(0, 1, auto);
+ .o-flex-flow(row, wrap);
+ .o_setting_box:visible:nth-child(odd) {
+ clear: left;
+ }
+ .text-muted {
+ color: #aaaaaa;
+ }
+ .o_setting_box {
+ margin-bottom: 8px;
+ margin-top: 8px;
+ .o_setting_left_pane {
+ width: 24px;
+ float: left;
+ .o_enterprise_label {
+ position: absolute;
+ top: 0px;
+ right: 40px;
+ }
+ }
+ .o_setting_right_pane {
+ margin-left: 30px;
+ border-left: 1px solid #bbbbbb;
+ padding-left: 10px;
+ .o_input_dropdown > .o_input {
+ width: 100%;
+ }
+ .o_field_widget {
+ width: 50%;
+ }
+ button.btn-link {
+ padding: 0;
+ }
+ a.oe-link {
+ font-size: 12px;
+ }
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/form_view_extra.scss b/addons/web/static/src/scss/form_view_extra.scss
new file mode 100644
index 00000000000..95da6a2b35b
--- /dev/null
+++ b/addons/web/static/src/scss/form_view_extra.scss
@@ -0,0 +1,190 @@
+@sheet-max-width: 860px;
+@sheet-min-width: 650px;
+@sheet-padding: 16px;
+
+.o_form_view {
+ &.o_form_nosheet.oe_form_nomargin {
+ margin: 0;
+ }
+ .o_form_sheet_bg {
+ border-bottom: 1px solid #ddd;
+ background: url(/web/static/src/img/form_sheetbg.png);
+
+ > .o_form_sheet {
+ min-width: @sheet-min-width;
+ max-width: @sheet-max-width;
+ min-height: 330px;
+ padding: 16px;
+ border: 1px solid #c8c8d3;
+ box-shadow: 0 4px 20px rgba(0,0,0,0.15);
+ background: white;
+
+ .ui-tabs {
+ margin: 0 -16px;
+ }
+ .oe_notebook_page {
+ padding: 0 16px;
+ }
+ }
+ }
+
+ // Button box
+ .oe_button_box {
+ width: 400px;
+ text-align: right;
+ float: right;
+
+ &, & + .oe_avatar {
+ + .oe_title {
+ width: 400px;
+ }
+ }
+
+ .oe_stat_button {
+ text-align: left;
+ width: 132px !important;
+ height: 40px;
+ margin: 0px -1px -1px 0px;
+ padding: 0;
+ border-radius: 0;
+ border-color: #ccc;
+ background: white;
+ outline: none;
+
+ &:hover {
+ background-color: #e6e6e6;
+ }
+
+ .o_button_icon {
+ display: inline-block;
+ width: 37px;
+ padding: 0px 3px;
+ text-align: center;
+ vertical-align: middle;
+ color: #7C7BAD;
+ font-size: 24px;
+ }
+
+ // Some buttons only display text without using StatInfo template
+ .o_stat_info, > span { // contains the value and text
+ display: inline-block;
+ vertical-align: middle;
+ max-width: 70%;
+ line-height: 1.2;
+
+ .o_stat_value {
+ .o-text-overflow(block);
+ font-weight: 700;
+ color: @odoo-brand-primary;
+ }
+ .o_stat_text {
+ .o-text-overflow(block);
+ font-size: small;
+
+ .o_stat_value {
+ display: inline;
+ }
+ }
+ }
+ > span {
+ font-size: small;
+ white-space: normal; // text on several lines if needed
+ }
+
+ > div {
+ text-align: left;
+ padding: 0;
+ line-height: 120%;
+ vertical-align: middle;
+ }
+ }
+
+ &.o_full {
+ position: relative;
+ .o_button_more {
+ padding: 0 10px;
+ }
+ .o_dropdown_more {
+ .o-position-absolute(@top: 100%, @right: 0);
+ min-width: 0;
+ padding: 0px;
+ }
+ }
+ }
+
+ // Avatar
+ .oe_avatar {
+ float: left;
+ > img {
+ max-height: 90px;
+ max-width: 90px;
+ margin-bottom: 10px;
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
+ border: none;
+ }
+ + .oe_title {
+ padding-left: 95px;
+ margin-left: 5px;
+ }
+ }
+
+ // Groups
+ .o_group {
+ .o_td_label {
+ border-right: 1px solid #ddd;
+ }
+ .o_td_label + td {
+ padding: 2px 36px 2px 8px;
+ }
+ .o_field_widget.o_text_overflow {
+ width: 1px!important; // hack to make the table layout believe it is a small element (so that the table does not grow too much) ...
+ min-width: 100%; // ... but in fact it takes the whole table space
+ }
+ }
+
+ // Separators
+ .o_horizontal_separator {
+ color: @odoo-brand-optional;
+ font-weight: bold;
+ }
+
+ // Translate icon
+ .o_field_translate {
+ margin-left: -15px;
+ }
+
+ // Specific style classes
+ .o_group.o_inner_group.oe_subtotal_footer {
+ .oe_subtotal_footer_separator {
+ border-top: 1px solid #cacaca;
+ }
+ .o_td_label {
+ border-right: none;
+ }
+ }
+
+ // Chatter
+ .oe_chatter {
+ display: block;
+ min-width: @sheet-min-width + 2* @sheet-padding;
+ max-width: @sheet-max-width + 2* @sheet-padding;
+ margin: 0 auto;
+ padding: 16px 16px 48px;
+ }
+}
+
+// Overriden style when form view in modal
+.modal .modal-dialog {
+ .o_form_view {
+ .o_form_sheet_bg, .o_form_sheet {
+ border: none;
+ }
+ }
+}
+
+// XXS form view specific rules
+.o_form_view.o_xxs_form_view {
+ .o_group .o_td_label {
+ border: none;
+ }
+}
diff --git a/addons/web/static/src/scss/graph_view.scss b/addons/web/static/src/scss/graph_view.scss
new file mode 100644
index 00000000000..fc8fc323582
--- /dev/null
+++ b/addons/web/static/src/scss/graph_view.scss
@@ -0,0 +1,20 @@
+.o_graph {
+ .o_graph_svg_container {
+ height: 100%;
+ overflow: auto;
+ svg {
+ background-color: @odoo-view-background-color;
+ }
+ }
+}
+
+.nvtooltip thead {
+ background-color: transparent;
+}
+
+// ------------------------------------------------------------------
+// Control panel buttons
+// ------------------------------------------------------------------
+.o_graph_measures_list {
+ .o-selected-li;
+}
diff --git a/addons/web/static/src/scss/import_bootstrap.scss b/addons/web/static/src/scss/import_bootstrap.scss
new file mode 100644
index 00000000000..cbd46a7afcf
--- /dev/null
+++ b/addons/web/static/src/scss/import_bootstrap.scss
@@ -0,0 +1 @@
+@import "bootstrap";
diff --git a/addons/web/static/src/scss/kanban_column_progressbar.scss b/addons/web/static/src/scss/kanban_column_progressbar.scss
new file mode 100644
index 00000000000..f4cffd6c097
--- /dev/null
+++ b/addons/web/static/src/scss/kanban_column_progressbar.scss
@@ -0,0 +1,152 @@
+@o-kanban-counter-header-height: @o-kanban-header-title-height*0.6;
+
+.o-kanban-css-filter(@class, @accent-color) {
+ // Provide CSS reordering and highlight
+ &.o_kanban_group_show_@{class} {
+ @mix-soft: mix(@accent-color, @odoo-webclient-background-color, 5%);
+ @mix-full: mix(@accent-color, @odoo-webclient-background-color);
+
+ &, .o_kanban_header {
+ background-color: @mix-soft;
+ border-color: @mix-full;
+ }
+
+ .progress-bar.bg-@{class}-full {
+ border: 1px solid white;
+ }
+
+ .oe_kanban_card_@{class} {
+ order: 1;
+ margin-bottom: @o-kanban-inside-vgutter*0.5;
+
+ ~ .oe_kanban_card_@{class} {
+ margin-top: -@o-kanban-inside-vgutter*0.5 - 1px;
+ }
+
+ ~ .o_kanban_load_more {
+ margin-top: -@o-kanban-inside-vgutter*0.5;
+ }
+ }
+
+ .o_kanban_load_more {
+ order: 2;
+ padding: @o-kanban-inside-vgutter*0.5 0 @o-kanban-inside-vgutter;
+ }
+
+ .o_kanban_record:not(.oe_kanban_card_@{class}) {
+ order: 3;
+ .o-hover-opacity(0.5);
+ box-shadow: none;
+ }
+ }
+}
+
+// If columns has the progressbar, adapt the layout
+.o_kanban_view .o_kanban_group.o_kanban_has_progressbar {
+ > .o_kanban_header .o_kanban_header_title {
+ height: @o-kanban-counter-header-height;
+ margin-top: 5px;
+ }
+
+ &.o_kanban_no_records {
+ .o_kanban_counter {
+ opacity: 0.3;
+ }
+ }
+}
+
+.o_kanban_counter {
+ position: relative;
+ .o-flex-display();
+ .o-align-items(center);
+ .o-transition(opacity, 0.3s);
+ margin-bottom: @o-kanban-record-margin*2;
+
+ > .o_kanban_counter_progress {
+ width: 76%;
+ height: @font-size-small;
+ margin-bottom: 0;
+ background-color: @gray-lighter-dark;
+ box-shadow: none;
+
+ .progress-bar {
+ margin-bottom: 0;
+ box-shadow: none;
+ cursor: pointer;
+
+ // Be sure that a bar with data has a minimun width
+ &.o_bar_has_records {
+ min-width: 10px;
+ }
+ }
+
+ .o_kanban_counter_label {
+ font-size: 10px;
+ .user-select(none);
+ }
+ }
+
+ > .o_kanban_counter_side {
+ width: 21%;
+ margin-left: 3%;
+ color: @headings-color;
+ text-align: right;
+ white-space: nowrap;
+ .o-transform-origin(right, center);
+
+ &.o_kanban_grow {
+ .o-animation(grow, 1s, ease);
+ }
+
+ &.o_kanban_grow_huge {
+ .o-animation(grow_huge, 1s, ease);
+ }
+
+ // Target currency icon
+ > span {
+ margin-left: 2px;
+ }
+ }
+}
+.o_column_folded .o_kanban_counter {
+ display: none;
+}
+
+.o_kanban_view .o_kanban_group {
+ .o-kanban-css-filter(success, @brand-success);
+ .o-kanban-css-filter(warning, @brand-warning);
+ .o-kanban-css-filter(danger, @brand-danger);
+
+ &.o_kanban_group_show {
+ .o-flex-display();
+ .o-flex-flow(column, nowrap);
+
+ > * {
+ .o-flex(0, 0, auto);
+ }
+ }
+}
+
+@keyframes grow {
+ 0% {
+ transform: scale3d(1, 1, 1);
+ }
+ 30% {
+ transform: scale3d(1.1, 1.1, 1.1);
+ }
+ 100% {
+ transform: scale3d(1, 1, 1);
+ }
+}
+
+@keyframes grow_huge {
+ 0% {
+ transform: scale3d(1, 1, 1);
+ }
+ 30% {
+ transform: scale3d(1.3, 1.3, 1.3);
+ }
+ 100% {
+ transform: scale3d(1, 1, 1);
+ }
+}
diff --git a/addons/web/static/src/scss/kanban_dashboard.scss b/addons/web/static/src/scss/kanban_dashboard.scss
new file mode 100644
index 00000000000..83db9319166
--- /dev/null
+++ b/addons/web/static/src/scss/kanban_dashboard.scss
@@ -0,0 +1,243 @@
+// ------- Kanban dashboard variables -------
+
+// Since rows and containers are used inside cards, we're
+// forced to set the padding relative to the grid system.
+@o-kanban-dashboard-hpadding: @grid-gutter-width*0.5;
+@o-kanban-dashboard-vpadding: @grid-gutter-width*0.25;
+
+// Used to manage spacing in complex dropdown menu
+@o-kanban-dashboard-dropdown-complex-gap: 5px;
+
+// Emulate dropdown links
+.o-kanban-dashboard-dropdown-link(@link-padding-gap: @odoo-dropdown-hpadding) {
+ padding: 0;
+
+ > a {
+ margin: auto auto auto -@link-padding-gap;
+ padding: 3px @link-padding-gap;
+ color: @text-color;
+ display: block;
+
+ &:hover {
+ background-color: @gray-lighter-dark;
+ color: @headings-color;
+ }
+ }
+ &:last-child {
+ margin-bottom: 5px;
+ }
+}
+
+.o_kanban_view.o_kanban_dashboard {
+ // correctly display the no_content_helper in dashboards
+ .o-flex-flow(row, wrap);
+
+ .o_kanban_record {
+ position: relative;
+ .o-flex-display();
+ .o-flex-flow(column, nowrap);
+ .o-justify-content(space-between);
+ padding: @o-kanban-dashboard-vpadding @o-kanban-dashboard-hpadding;
+
+ @media (max-width: @screen-xs-max) {
+ margin-bottom: 10px;
+ }
+
+ &:focus, &:focus-within {
+ -webkit-box-shadow: 1px 1px 3px 0px rgba(0,0,0,1);
+ -moz-box-shadow: 1px 1px 3px 0px rgba(0,0,0,1);
+ box-shadow: 1px 1px 3px 0px rgba(0,0,0,1);
+ z-index: 1; // show the shadow on top of the previous & next cards in grouped mode
+ outline: none;
+ }
+
+ // ------- Generic layout adaptations -------
+ .container {
+ width: 100%;
+ }
+
+ // ------- Dropdown toggle & menu -------
+ @o-kanban-manage-toggle-height: 35px;
+
+ .o_kanban_manage_toggle_button {
+ .o-kanban-dropdown(@o-kanban-dashboard-hpadding);
+ height: @o-kanban-manage-toggle-height;
+ }
+
+ .o_kanban_card_manage_pane {
+ .dropdown-menu;
+ .o-kanban-dropdown-menu();
+
+ // Arbitrary value to place the dropdown-menu exactly below the
+ // dropdown-toggle (height is forced so that it works on Firefox)
+ top: @o-kanban-manage-toggle-height - 1;
+
+ > div:not(.o_no_padding_kanban_colorpicker) {
+ padding: 3px 0 3px 20px;
+ visibility: visible;
+ margin-bottom: 5px;
+ }
+
+ > .o_kanban_card_manage_section {
+ border-bottom: 1px solid @gray-lighter-dark;
+ margin-bottom: 10px;
+
+ > div {
+ .o-kanban-dashboard-dropdown-link();
+ }
+ }
+
+ // Dropdown menu with complex layout
+ &.container {
+ width: 95%;
+ max-width: 400px;
+
+ .row {
+ .o-flex-display();
+ .o-flex-flow(row, nowrap);
+ .o-justify-content(space-between);
+ margin-left: 0;
+ margin-right: 0;
+ padding-left: @o-kanban-dashboard-dropdown-complex-gap*2;
+ padding-right: @o-kanban-dashboard-dropdown-complex-gap*2;
+ }
+
+ div[class*="col-"] {
+ .o-flex(1, 1, percentage(100/3));
+ padding-left: @o-kanban-dashboard-dropdown-complex-gap;
+ padding-right: @o-kanban-dashboard-dropdown-complex-gap;
+
+ > .o_kanban_card_manage_title {
+ .h5;
+ font-weight: 500;
+ }
+ > div:not(.o_kanban_card_manage_title) {
+ .o-kanban-dashboard-dropdown-link(@link-padding-gap: @o-kanban-dashboard-dropdown-complex-gap);
+ }
+ }
+
+ .row.o_kanban_card_manage_settings {
+ border-top: 1px solid @gray-lighter-dark;
+ padding-top: @o-kanban-dashboard-dropdown-complex-gap*3;
+
+ .oe_kanban_colorpicker {
+ max-width: none;
+ padding: 0;
+ }
+
+ div[class*="col-"] + div[class*="col-"] {
+ border-left: 1px solid @gray-lighter-dark;
+ }
+
+ // Default options box
+ div.text-right {
+ text-align: left; // :/
+ .o-kanban-dashboard-dropdown-link(0);
+ > a {
+ margin-left: 40px;
+ padding-left: 20px;
+ }
+ }
+ }
+ }
+
+ }
+
+ &.o_dropdown_open {
+ .o_kanban_card_manage_pane {
+ display: block;
+ }
+ .o_kanban_manage_toggle_button {
+ .o-kanban-dropdown-open();
+ position: absolute;
+ }
+ }
+
+ // ------- Kanban Record Titles -------
+ // Uniform design across different HTML layouts
+
+ // Provide enough room for the dropdown-toggle
+ .o_primary {
+ padding-right: @o-kanban-dashboard-hpadding*2;
+ }
+
+ // Uniform titles
+ .o_kanban_card_header_title .o_primary,
+ .o_kanban_primary_left .o_primary > span:first-child,
+ .oe_kanban_content > .o_title > h3 {
+ .o-kanban-record-title(@font-size: 16px);
+ display: block;
+ }
+
+ // Identify subtitles without classes
+ .o_kanban_primary_left .o_primary > span:nth-child(2) > strong {
+ font-weight: 500;
+ font-size: @font-size-small;
+ color: @text-muted;
+ }
+
+ // Provide enough room to add an icon before the title
+ &.o_has_icon .o_primary {
+ padding-left: @o-kanban-record-margin*1.5;
+ }
+
+ // ------- Kanban Content -------
+ .o_kanban_card_content {
+ display: inline-block;
+ vertical-align: top;
+ min-height: 80px;
+ }
+
+ .o_kanban_card_header + .container.o_kanban_card_content {
+ .o-flex(1, 0, auto);
+ .o-flex-display();
+ .o-flex-flow(column, nowrap);
+ .o-justify-content(space-between);
+ margin-top: @o-kanban-dashboard-vpadding * 2;
+ padding-right: 0;
+ padding-left: 0;
+
+ &::before, &::after {
+ content: normal; // so that space-between works
+ }
+
+ a {
+ position: relative;
+ .o-text-overflow(inline-block);
+ }
+
+ .o_kanban_primary_bottom {
+ margin-top: @o-kanban-dashboard-vpadding;
+ margin-bottom: -@o-kanban-dashboard-vpadding;
+
+ &.bottom_block {
+ border-top: 1px solid @gray-lighter-dark;
+ background-color: @gray-lighter;
+ padding-top: @o-kanban-dashboard-vpadding;
+ padding-bottom: @o-kanban-dashboard-vpadding;
+ }
+ }
+ }
+
+ .o_dashboard_graph {
+ overflow: hidden;
+ margin: (@o-kanban-dashboard-vpadding * 2) -@o-kanban-dashboard-hpadding;
+ }
+ }
+
+ .o_favorite, .o_kanban_manage_toggle_button {
+ .o-position-absolute(0, 0);
+ padding: @o-kanban-record-margin;
+ }
+
+ .o_favorite {
+ top: 3px;
+ left: 0;
+ right: auto;
+ }
+
+ // Emphasize records' colors when necessary
+ &.o_emphasize_colors .o_kanban_record::after {
+ width: @o-kanban-color-border-width * 2;
+ }
+}
diff --git a/addons/web/static/src/scss/kanban_examples_dialog.scss b/addons/web/static/src/scss/kanban_examples_dialog.scss
new file mode 100644
index 00000000000..35a3d914b8e
--- /dev/null
+++ b/addons/web/static/src/scss/kanban_examples_dialog.scss
@@ -0,0 +1,71 @@
+.o_kanban_examples_dialog {
+ .o-flex-display();
+ padding: 0px;
+ background: @odoo-color-silver;
+
+ // sidebar
+ .o_kanban_examples_dialog_nav {
+ .o-flex(0, 0, auto);
+ border-right: 1px solid @gray-lighter-dark;
+ background: white;
+
+ > ul > li {
+ margin: 0;
+ border-bottom: 1px solid @gray-lighter-dark;
+
+ > a {
+ padding: 12px 15px;
+ color: @odoo-main-text-color;
+ border-left: 3px solid transparent;
+ &:focus {
+ outline: none;
+ }
+ }
+ &.active > a {
+ color: @headings-color;
+ border-left-color: @odoo-brand-optional;
+ font-weight: bold;
+ }
+ }
+ }
+
+ // content
+ .o_kanban_examples_dialog_content {
+ .o-flex(1, 1, 100%);
+
+ .o_kanban_examples_description {
+ padding: 16px 16px 0;
+ text-align: justify;
+ }
+ .o_kanban_examples {
+ .o-flex-display();
+ padding: 0 6px;
+
+ .o_kanban_examples_group {
+ .o-flex(1, 1, 100%);
+ margin: 10px;
+
+ .o_kanban_examples_ghost {
+ padding: 5px;
+ margin-top: -1px;
+ border: thin solid @gray-lighter-dark;
+ background-color: white;
+ .o_ghost_content {
+ height: 12px;
+ background: @gray-lighter-dark;
+ &.o_ghost_tag {
+ display: inline-block;
+ width: 40%;
+ margin-top: 10px;
+ }
+ }
+ .o_ghost_avatar {
+ height: 20px;
+ width: 20px;
+ margin-top: 6px;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/kanban_view.scss b/addons/web/static/src/scss/kanban_view.scss
new file mode 100644
index 00000000000..f9130469665
--- /dev/null
+++ b/addons/web/static/src/scss/kanban_view.scss
@@ -0,0 +1,648 @@
+@o-kanban-record-margin: @odoo-horizontal-padding/2;
+@o-kanban-group-padding: @odoo-horizontal-padding; // Cannot be higher than this
+
+@o-kanban-default-record-width: 300px;
+@o-kanban-small-record-width: 240px;
+
+@o-kanban-header-title-height: 50px;
+
+@o-kanban-image-width: 64px;
+@o-kanban-inside-vgutter: 8px;
+@o-kanban-inside-hgutter: 8px;
+@o-kanban-color-border-width: 3px;
+@o-kanban-inside-hgutter-mobile: @odoo-horizontal-padding;
+@o-kanban-inner-hmargin: 5px;
+@o-kanban-progressbar-height: 20px;
+
+// ------- Kanban grouped mixins -------
+.o-kanban-icon(@base-opacity: 0.5) {
+ display: block;
+ text-align: center;
+ color: @odoo-main-text-color;
+ font-size: @font-size-small;
+ cursor: pointer;
+ .o-hover-opacity(@base-opacity);
+}
+.o-kanban-tag-color(@size: 0) when (@size < @odoo-nb-ui-color) {
+ // Note: the 0 color is supposed to be invisible if there is a color field
+ // but it is used as a default color when there is no color field
+ &.o_tag_color_@{size} span {
+ background-color: ~"@{odoo-color-@{size}}";
+ }
+ .o-kanban-tag-color(@size + 1);
+}
+.o-kanban-record-color(@size: 1) when (@size < @odoo-nb-ui-color) {
+ // Note: the 0 color is not defined as it is the 'no color' for kanban
+ .oe_kanban_color_@{size}::after {
+ background-color: ~"@{odoo-color-@{size}}";
+ }
+ .o-kanban-record-color(@size + 1);
+}
+.o-kanban-slim-col() {
+ position: relative;
+ .o-flex(0, 0, auto);
+ margin: 0;
+ padding: 0 floor(@o-kanban-group-padding * 0.7);
+ cursor: pointer;
+}
+.o-kanban-header-title() {
+ .o-flex-display();
+ .o-align-items(center);
+ height: @o-kanban-header-title-height;
+ line-height: 2.2;
+ color: @headings-color;
+}
+.o-kanban-v-title() {
+ .o-position-absolute(@o-kanban-inside-vgutter * 2, @left: floor(-@o-kanban-inside-vgutter * 1.2));
+ .o-transform-origin(left, bottom, @z: 0);
+ .o-transform(rotate(90deg));
+ overflow: visible;
+ white-space: nowrap;
+ font-size: 15px;
+}
+
+// ------- Kanban records mixins -------
+.o-kanban-record-title(@font-size) {
+ color: @headings-color;
+ font-size: @font-size;
+ font-weight: 500;
+ margin-bottom: 0;
+ margin-top: 0;
+}
+.o-kanban-dropdown(@padding-base: @o-kanban-inside-vgutter) {
+ margin: -1px -1px auto auto; // compensate border
+ padding: @padding-base/2 @padding-base;
+ border: 1px solid transparent;
+ border-bottom: none;
+ vertical-align: top;
+ color: @text-color;
+
+ &:hover {
+ color: @headings-color;
+ }
+ &:focus, &:active, &:focus:active {
+ outline: none;
+ }
+}
+.o-kanban-dropdown-open() {
+ position: relative;
+ background: white;
+ border-color: @gray-lighter-darker;
+ z-index: @zindex-dropdown + 1;
+}
+.o-kanban-dropdown-menu() {
+ .o-position-absolute(@right: -1px);
+ margin-top: -1px;
+ border-color: @gray-lighter-darker;
+}
+.o-kanban-colorpicker() {
+ max-width: 150px;
+ padding: 3px (@odoo-dropdown-hpadding - @o-kanban-inner-hmargin) 3px @odoo-dropdown-hpadding;
+
+ > li {
+ display: inline-block;
+ margin: @o-kanban-inner-hmargin @o-kanban-inner-hmargin 0 0;
+ border: 1px solid white;
+ box-shadow: 0 0 0 1px @gray-lighter-dark;
+
+ > a {
+ display: block;
+
+ &::after {
+ content: "";
+ display: block;
+ width: 20px;
+ height: 15px;
+ }
+ }
+
+ // No Color
+ &:first-child > a {
+ position: relative;
+ &::before {
+ content: "";
+ .o-position-absolute(-2px, @left: 10px);
+ display: block;
+ width: 1px;
+ height: 20px;
+ .rotate(45deg);
+ background-color: red;
+ }
+ &::after {
+ background-color: white;
+ }
+ }
+ }
+}
+
+// ------- Kanban View Layout -------
+.o_kanban_view {
+ .o-flex-display();
+ .o-align-content(stretch);
+ overflow-x: visible;
+
+ @media (max-width: @screen-xs-max) {
+ padding: 0px!important;
+ overflow-x: auto;
+ }
+
+ .o_kanban_record, .o_kanban_quick_create {
+ padding: @o-kanban-inside-vgutter @o-kanban-inside-hgutter;
+ border: 1px solid @gray-lighter-dark;
+ background-color: white;
+
+ @media (max-width: @screen-xs-max) {
+ padding: @o-kanban-inside-vgutter @o-kanban-inside-hgutter-mobile;
+ }
+ &:focus, &:focus-within {
+ -webkit-box-shadow: 3px 3px 10px 0px rgba(0,0,0,1);
+ -moz-box-shadow: 3px 3px 10px 0px rgba(0,0,0,1);
+ box-shadow: 3px 3px 10px 0px rgba(0,0,0,1);
+ z-index: 1; // show the shadow on top of the previous & next cards in grouped mode
+ outline: none;
+ }
+ }
+
+ .o_kanban_quick_create {
+ box-shadow: 0 0 20px -10px;
+ margin: 0 @o-kanban-record-margin -1px @o-kanban-record-margin;
+ margin-bottom: 8px;
+
+ .o_form_view {
+ padding: 0;
+ .o_group.o_inner_group {
+ margin: 0;
+ }
+ }
+ }
+
+ .o_kanban_record {
+ position: relative;
+ display: inline-block; // Force the creation of a block formatting context to clear float items
+ border-color: @gray-lighter-darker;
+ min-width: 150px;
+ margin: 0 0 -1px;
+
+ // ------- Kanban Record, v11 Layout -------
+ // Records colours
+ &::after {
+ content: "";
+ .o-position-absolute(0, auto, 0, -1px);
+ width: @o-kanban-color-border-width;
+ }
+
+ // Inner Sections
+ .o_kanban_record_top, .o_kanban_record_body {
+ margin-bottom: @o-kanban-inner-hmargin;
+ }
+
+ .o_kanban_record_top, .o_kanban_record_bottom {
+ .o-flex-display();
+ }
+
+ .o_kanban_record_top {
+ .o-align-items(flex-start);
+
+ .o_dropdown_kanban {
+ // For v11 layout, reset positioning to default to properly use
+ // flex-box
+ position: relative;
+ top: auto;
+ right: auto;
+ }
+
+ .o_kanban_record_headings {
+ line-height: 1.2;
+ .o-flex(1, 1, auto);
+ // Ensure long word doesn't break out of container
+ word-wrap: break-word;
+ overflow: hidden;
+ }
+ }
+
+ .o_kanban_record_title {
+ .o-kanban-record-title (@font-size: 13px);
+ }
+
+ .o_kanban_record_subtitle {
+ display: block;
+ margin-top: @o-kanban-inner-hmargin*0.5;
+ }
+
+ .o_kanban_record_bottom {
+ .oe_kanban_bottom_left, .oe_kanban_bottom_right {
+ .o-flex-display();
+ .o-align-items(center);
+ height: 20px;
+ }
+ .oe_kanban_bottom_left {
+ .o-flex(1, 1, auto);
+
+ > * {
+ margin-right: 6px;
+ line-height: 1;
+ }
+
+ .o_priority_star {
+ margin-top: 1px;
+ font-size: 18px;
+ }
+ }
+ .oe_kanban_bottom_right{
+ .o-flex(0, 1, auto);
+
+ .oe_kanban_avatar {
+ width: 20px;
+ height: 20px;
+ margin-left: 6px;
+ }
+ }
+ .o_link_muted {
+ color: @text-color;
+ &:hover {
+ color: @brand-primary;
+ text-decoration: underline;
+ }
+ }
+ }
+ }
+
+ // ------- Compatibility of old (<= v10) Generic layouts -------
+
+ // Kanban Records - Uniform Design
+ // Provide a basic style for different kanban record layouts
+ // ---------------------------------------------------------
+ .oe_kanban_card, .o_kanban_record {
+ // ------- v11 Layout + generic layouts (~v10) -------
+ // Kanban Record - Dropdown
+ .o_dropdown_kanban {
+ .o-position-absolute(@o-kanban-inside-vgutter, @o-kanban-inside-hgutter);
+ visibility: hidden;
+ @media (max-width: @screen-xs-max) {
+ visibility: visible;
+ }
+
+ .dropdown-toggle {
+ .o-kanban-dropdown();
+ margin: (-@o-kanban-inside-vgutter - 1px) (-@o-kanban-inside-hgutter - 1px) 0 0;
+ }
+ &.open .dropdown-toggle {
+ .o-kanban-dropdown-open();
+ }
+ .dropdown-menu {
+ .o-kanban-dropdown-menu();
+ right: (-@o-kanban-inside-hgutter - 1);
+ }
+ }
+
+ &:hover .o_dropdown_kanban, .o_dropdown_kanban.open {
+ visibility: visible;
+ }
+
+ // Kanban Record - Dropdown colorpicker
+ .oe_kanban_colorpicker {
+ .o-kanban-colorpicker();
+ }
+
+ // Kanban Record - Inner elements
+ .o_field_many2manytags, .o_kanban_tags {
+ display: block;
+ margin-bottom: @o-kanban-inner-hmargin;
+ line-height: 1.2;
+
+ .o_tag {
+ display: inline-block;
+ margin-right: 4px;
+ font-size: 11px;
+ font-weight: 500;
+ background-color: transparent;
+ .o-kanban-tag-color();
+
+ span {
+ display: inline-block;
+ width: 6px;
+ height: 6px;
+ margin-right: 4px;
+ border-radius: 100%;
+ }
+ }
+ }
+
+ // Commonly used to place an image beside the text
+ // (e.g. Fleet, Employees, ...)
+ .o_kanban_image {
+ text-align: center;
+
+ img {
+ max-width: 100%;
+ }
+ }
+
+ .o_kanban_button {
+ margin-top: 15px;
+
+ > button, > a {
+ .o-position-absolute(@right: @o-kanban-record-margin, @bottom: @o-kanban-record-margin);
+ @media (max-width: @screen-xs-max) {
+ right: @o-kanban-inside-hgutter-mobile;
+ }
+ }
+ }
+
+ // Kanban Record - Utility classes
+ &.oe_kanban_global_click, &.oe_kanban_global_click_edit {
+ cursor: pointer;
+ }
+
+ &.ui-sortable-helper {
+ .o-transform(rotate(-3deg));
+ box-shadow: 0 5px 25px -10px black;
+ .transition(~"transform 0.6s, box-shadow 0.3s");
+ }
+
+ .o_attachment_image > img {
+ width: 100%;
+ height: auto;
+ margin-bottom: @o-kanban-inner-hmargin;
+ }
+
+ .o_progressbar {
+ .o-flex-display();
+ height: @o-kanban-progressbar-height;
+
+ .o_progressbar_title {
+ .o-flex(0, 0, auto);
+ }
+ .o_progress {
+ .o-flex(1, 1, auto);
+ margin-top: 3px;
+ }
+ .o_progressbar_value {
+ .o-flex(0, 0, auto);
+ width: auto;
+ height: 100%;
+ text-align: right;
+ }
+ input.o_progressbar_value {
+ width: 15%;
+ margin-left: 8px;
+ }
+ }
+
+ .o_kanban_image {
+ float: left;
+ width: @o-kanban-image-width;
+
+ + div {
+ padding-left: @o-kanban-image-width + @o-kanban-inside-hgutter;
+ @media (max-width: @screen-xs-max) {
+ padding-left: @o-kanban-image-width + @o-kanban-inside-hgutter-mobile;
+ }
+ }
+ }
+
+ .oe_kanban_details {
+ width: 100%;
+ ul {
+ margin-bottom: @o-kanban-inner-hmargin*0.5;;
+ padding-left: 0;
+ list-style: none;
+ font-size: @font-size-small;
+
+ li {
+ margin-bottom: 2px;
+ }
+ }
+ }
+
+ .o_kanban_footer {
+ .o-flex-display();
+ .o-justify-content(space-between);
+ .o-align-items(center);
+ > * {
+ .o-flex(0, 0, auto);
+ }
+ }
+
+ .oe_kanban_text_red {
+ color: #A61300;
+ font-weight: bold;
+ }
+
+ .o_text_bold {
+ font-weight: bold;
+ }
+
+ .o_text_block {
+ display: block;
+ }
+ }
+
+ // Kanban Grouped Layout
+ &.o_kanban_grouped {
+ min-height: 100%;
+ padding: 0;
+ background-color: @gray-lighter;
+
+ .o_kanban_record, .o_kanban_quick_create {
+ width: 100%;
+ margin-left: 0;
+ margin-right: 0;
+ }
+
+ &.o_kanban_small_column .o_kanban_group:not(.o_column_folded) {
+ width: @o-kanban-small-record-width + 2*@o-kanban-group-padding;
+ }
+ }
+
+ // Kanban Grouped Layout - Column default
+ .o_kanban_group {
+ .o-flex(0, 0, auto);
+ padding: 0 @o-kanban-group-padding @o-kanban-group-padding @o-kanban-group-padding;
+
+ .o_kanban_header > .o_kanban_header_title {
+ .o-kanban-header-title();
+
+ .o_column_title {
+ .o-flex(1, 1, auto);
+ .o-text-overflow();
+ font-size: 16px;
+ font-weight: 500;
+ }
+
+ .o_column_unfold {
+ display: none;
+ }
+
+ .o_kanban_quick_add i {
+ .o-kanban-icon;
+ margin-left: @o-kanban-inside-hgutter*2;
+ }
+
+ &:hover .o_kanban_config, .o_kanban_config.open {
+ visibility: visible;
+ margin-left: @o-kanban-inside-hgutter;
+ }
+
+ .o_kanban_config {
+ visibility: hidden;
+
+ i {
+ .o-kanban-icon;
+ }
+ }
+ }
+
+ .o_kanban_load_more {
+ padding: @o-kanban-record-margin 0;
+ box-shadow: inset 0 10px 13px -13px black;
+ text-align: center;
+ }
+
+ &.ui-sortable-helper {
+ box-shadow: 0 0 30px -10px black;
+ }
+
+ &:not(.o_column_folded) {
+ width: @o-kanban-default-record-width + 2*@o-kanban-group-padding;
+ }
+
+ &.o_kanban_dragged {
+ background-color: @odoo-main-text-color;
+
+ .o_kanban_record {
+ visibility: hidden;
+ }
+ }
+ }
+
+ &.ui-sortable .o_kanban_header_title {
+ cursor: move;
+ }
+
+ // Kanban Grouped Layout - Column Folded
+ .o_kanban_group.o_column_folded {
+ .o-kanban-slim-col();
+ background-color: @gray-lighter-dark;
+
+ & + .o_kanban_group.o_column_folded {
+ margin-left: 1px;
+ }
+
+ .o_kanban_header_title {
+ position: relative;
+ opacity: 0.5;
+
+ .o_column_title {
+ .o-kanban-v-title();
+ }
+ .o_column_unfold {
+ .o-kanban-icon(1);
+ }
+ }
+
+ > .o_kanban_record, .o_kanban_quick_add, .o_kanban_config, .o_kanban_load_more {
+ display: none!important;
+ }
+
+ &:hover, &.o_kanban_hover {
+ .o_kanban_header_title {
+ opacity: 1;
+ }
+ }
+ }
+
+ // Kanban Grouped Layout - "Create new column" column
+ .o_column_quick_create {
+ .o_quick_create_folded {
+ cursor: pointer;
+ padding: 12px 16px;
+ white-space: nowrap;
+ color: @text-muted;
+ opacity: 0.6;
+ &:hover {
+ opacity: 1;
+ }
+
+ .o_kanban_add_column {
+ display: inline-block;
+ padding: 10px 14px;
+ background-color: @odoo-color-silver-dark;
+ }
+ .o_kanban_title {
+ margin-left: 10px;
+ }
+ }
+
+ .o_quick_create_unfolded {
+ padding: @o-kanban-inside-vgutter @o-kanban-inside-hgutter;
+ width: @o-kanban-small-record-width;
+ height: 100%;
+ border: none;
+ box-shadow: 0 0 20px -10px;
+ background-color: @gray-lighter;
+
+ .o_kanban_header {
+ height: 50px;
+
+ .o_kanban_examples {
+ cursor: pointer;
+ }
+
+ input, input:focus, input:hover {
+ margin-top: 3px;
+ font-size: 16px;
+ background: transparent;
+ }
+
+ .o_kanban_add {
+ margin-left: 10px;
+ }
+ }
+
+ .o_kanban_muted_record {
+ background: @gray-lighter-dark;
+ height: 70px;
+ margin: 10px 0px;
+ }
+
+ }
+ }
+
+ // Kanban UN-grouped Layout
+ &.o_kanban_ungrouped {
+ .o-flex-flow(row, wrap);
+ .o-justify-content(flex-start);
+
+ padding: @o-kanban-record-margin (@odoo-horizontal-padding - @o-kanban-record-margin);
+
+ .o_kanban_record {
+ .o-flex(1, 1, auto);
+ width: @o-kanban-default-record-width;
+ margin: (@o-kanban-record-margin * 0.5) @o-kanban-record-margin;
+
+ @media (max-width: @screen-xs-max) {
+ margin: 0 0 -1px 0;
+ .o-flex(1, 0, 100%);
+ }
+
+ &.o_kanban_ghost {
+ height: 0;
+ min-height: 0!important; // to prevent view writers to override this height
+ visibility: hidden;
+ margin-top: 0;
+ margin-bottom: 0;
+ padding: 0;
+ }
+ }
+ }
+
+ &.o_kanban_mobile .o_kanban_record {
+ div.label {
+ .o-text-overflow();
+ }
+ }
+
+ // Records colours
+ .o-kanban-record-color();
+}
diff --git a/addons/web/static/src/scss/kanban_view_mobile.scss b/addons/web/static/src/scss/kanban_view_mobile.scss
new file mode 100644
index 00000000000..d09b6968925
--- /dev/null
+++ b/addons/web/static/src/scss/kanban_view_mobile.scss
@@ -0,0 +1,52 @@
+@o-kanban-mobile-tabs-height: 40px;
+
+@media (max-width: @screen-xs-max) {
+ .o_kanban_view.o_kanban_grouped {
+ display: block;
+ position: relative;
+ overflow: hidden;
+
+ .o_kanban_mobile_tabs {
+ height: @o-kanban-mobile-tabs-height;
+ position: relative;
+ background-color: #5E5E5E;
+
+ .o_kanban_mobile_tab {
+ .o-position-absolute(@left: 100%);
+ .o-transform(translateX(-50%));
+ height: @o-kanban-mobile-tabs-height;
+ padding: 10px;
+ font-size: 14px;
+ color: white;
+
+ &.o_current {
+ font-weight: bold;
+ border-bottom: 3px solid @odoo-brand-optional;
+ }
+ .o_column_title {
+ white-space: nowrap;
+ }
+ }
+ }
+
+ // [class] to get same specificity as elsewhere (kanban_view.less)
+ &[class] .o_kanban_group:not(.o_column_folded) {
+ .o-position-absolute(@top: @o-kanban-mobile-tabs-height, @left: 0, @bottom: 0);
+ overflow-x: scroll;
+ width: 100%;
+ padding: 0;
+ margin-left: 0; // override the margin-left: -1px of the desktop mode
+ border: none;
+
+ .o_kanban_header {
+ display: none;
+ }
+ .o_kanban_record, .o_kanban_quick_create {
+ border: none;
+ border-bottom: 1px solid lightgray;
+ padding: 10px 16px;
+ margin: 0;
+ }
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/layout_background.scss b/addons/web/static/src/scss/layout_background.scss
new file mode 100644
index 00000000000..6750705c35b
--- /dev/null
+++ b/addons/web/static/src/scss/layout_background.scss
@@ -0,0 +1,68 @@
+.o_background_footer, .o_background_header, .o_report_layout_background {
+ font-family: 'Lato';
+ color: @gray;
+}
+.o_background_header {
+ border-bottom: 1px solid @gray-lighter;
+ .company_address {
+ min-width: 300px;
+ }
+ img {
+ max-height: 96px;
+ max-width: 300px;
+ margin-right: 16px;
+ }
+ h3 {
+ color: @odoo-brand-primary;
+ font-weight: 700;
+ max-width: 300px;
+ }
+}
+.o_background_footer {
+ ul {
+ border-top: 1px solid @odoo-brand-primary;
+ border-bottom: 1px solid @odoo-brand-primary;
+ padding: 4px 0;
+ margin: 0 0 4px 0;
+ li {
+ color: @odoo-brand-primary;
+ }
+ }
+}
+.o_report_layout_background {
+ background-image: url(/base/static/img/bg_background_template.jpg);
+ background-size: cover;
+ background-position: bottom center;
+ background-repeat: no-repeat;
+ min-height: 900px;
+ thead tr th, h2 {
+ color: @odoo-brand-primary;
+ }
+ tbody {
+ color: @gray;
+ tr:nth-child(odd) {
+ background-color: rgba(184, 171, 180, 0.2);
+ }
+ tr td {
+ border-top: none;
+ }
+ }
+ /*Total table*/
+ .row > .col-xs-4 > table {
+ tr:nth-child(odd) {
+ background-color: transparent !important;
+ }
+ tr:first-child td {
+ /*we could get rid of this rule if .border-black td would be terminated in report.less*/
+ border-top: none !important;
+ }
+ tr:last-child td {
+ color: @odoo-brand-primary;
+ }
+ }
+ #total {
+ table tr:last-child td {
+ border-bottom: 1px solid black;
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/layout_boxed.scss b/addons/web/static/src/scss/layout_boxed.scss
new file mode 100644
index 00000000000..21fcf66efc5
--- /dev/null
+++ b/addons/web/static/src/scss/layout_boxed.scss
@@ -0,0 +1,73 @@
+.o_boxed_footer, .o_boxed_header, .o_report_layout_boxed {
+ font-family: 'Lato';
+ color: @gray;
+ font-size: 12px;
+}
+.o_boxed_header {
+ border-bottom: 1px solid @gray-lighter;
+ img {
+ max-height: 100px;
+ }
+ h4 {
+ color: @o-we-color-text-normal;
+ font-weight: 700;
+ text-transform: uppercase;
+ }
+}
+.o_boxed_footer {
+ white-space: nowrap;
+ border-top: 3px solid @gray;
+ ul {
+ margin: 4px 0;
+ }
+}
+.o_report_layout_boxed {
+ // This is not a general rule since the id is not used in all the reports,
+ // we should make a general structure for report body to use it everywhere
+ #informations {
+ border: 1px solid @gray;
+ padding-top: 10px;
+ margin: 0;
+ }
+ > h2 {
+ text-transform: uppercase;
+ }
+ table {
+ border: 1px solid @gray;
+ thead {
+ tr th {
+ border-bottom: 3px solid @gray !important;
+ text-transform: uppercase;
+ }
+ }
+ tbody {
+ color: @gray;
+ tr {
+ td {
+ border-top: none;
+ border-right: 1px solid @gray;
+ }
+ td:last-child {
+ background-color: @gray-lighter;
+ }
+ }
+ }
+ }
+ /*Total table*/
+ .row > .col-xs-4 > table {
+ td {
+ border-right: none;
+ }
+ tr:last-child td, tr:first-child td {
+ /*we could get rid of this rule if .border-black td would be terminated in report.less*/
+ border-top: none !important;
+ }
+ tr:first-child td {
+ background-color: transparent;
+ }
+ tr:last-child td {
+ background-color: @gray;
+ color: #fff;
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/layout_clean.scss b/addons/web/static/src/scss/layout_clean.scss
new file mode 100644
index 00000000000..869e1f4098f
--- /dev/null
+++ b/addons/web/static/src/scss/layout_clean.scss
@@ -0,0 +1,85 @@
+.o_clean_footer, .o_clean_header, .o_report_layout_clean {
+ font-family: 'Lato';
+ color: #000;
+}
+.o_clean_header {
+ img {
+ max-height: 90px;
+ max-width: 300px;
+ }
+}
+.o_clean_footer {
+ margin: 0 3px;
+ border-top: 3px solid @odoo-brand-primary;
+ h4 {
+ color: @odoo-brand-primary;
+ font-weight: bolder;
+ }
+ .pagenumber {
+ width: 35px;
+ height: 35px;
+ border: 3px solid @odoo-brand-primary;
+ background-color: @odoo-brand-optional;
+ color: white;
+ padding-top: 6px;
+ text-align: center;
+ }
+}
+.o_report_layout_clean {
+ h1, h2, h3 {
+ color: @odoo-brand-optional;
+ font-weight: bolder;
+ }
+ strong {
+ color: @odoo-brand-primary;
+ }
+ table {
+ thead {
+ color: @odoo-brand-primary;
+ tr th {
+ text-align: left !important;
+ border-top: 3px solid @odoo-brand-primary !important;
+ text-transform: uppercase;
+ }
+ tr th:last-child {
+ text-align: right !important;
+ }
+ tr th:first-child {
+ width: 48%;
+ }
+ }
+ tbody {
+ color: #000;
+ tr:first-child td {
+ border-top: none;
+ }
+ tr:last-child td {
+ border-bottom: 3px solid @odoo-brand-primary;
+ }
+ tr {
+ td {
+ padding: 15px 5px;
+ text-align: left !important;
+ }
+ td:last-child {
+ text-align: right !important;
+ }
+ }
+ }
+ }
+ /*Total table*/
+ .row > .col-xs-4 {
+ width: 43%;
+ position: relative;
+ top: -20px;
+ > table {
+ tr:last-child td {
+ border-top: 1px solid @gray-lighter !important;
+ }
+ tr:first-child td {
+ /*we could get rid of this rule if .border-black td would be terminated in report.less*/
+ border-top: none !important;
+ }
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/list_view.scss b/addons/web/static/src/scss/list_view.scss
new file mode 100644
index 00000000000..9106cf45a87
--- /dev/null
+++ b/addons/web/static/src/scss/list_view.scss
@@ -0,0 +1,243 @@
+@odoo-list-group-header-color: lighten(@odoo-brand-lightsecondary, 10%);
+
+.o_list_view {
+ position: relative;
+ cursor: pointer;
+ background-color: @odoo-view-background-color;
+ margin-bottom: 0px;
+
+ &.table {
+ td, th {
+ vertical-align: middle;
+ }
+ }
+
+ thead {
+ color: @odoo-main-text-color;
+ border-bottom: 1px solid #cacaca;
+ > tr > th {
+ border-left: 1px solid #dfdfdf;
+ &:not(.o_column_sortable):hover {
+ cursor: default;
+ }
+ }
+ }
+
+ tfoot {
+ cursor: default;
+ color: @odoo-list-footer-color;
+ background-color: @odoo-list-footer-bg-color;
+ font-weight: @odoo-list-footer-font-weight;
+ border-top: 2px solid #cacaca;
+ border-bottom: 1px solid #cacaca;
+ }
+
+ .o_column_sortable {
+ position: relative;
+ .user-select(none); // Prevent unwanted selection while sorting
+
+ &::after {
+ font-family: FontAwesome;
+ content: "\f0d7";
+ opacity: 0;
+ }
+ &:not(:empty)::after {
+ margin-left: 6px;
+ position: absolute;
+ }
+ &.o-sort-up {
+ cursor: n-resize;
+ &::after {
+ content: "\f0d7";
+ }
+ }
+ &.o-sort-down {
+ cursor: s-resize;
+ &::after {
+ content: "\f0d8";
+ }
+ }
+ &:hover::after {
+ opacity: 0.3;
+ }
+ &.o-sort-up, &.o-sort-down {
+ color: @headings-color;
+ &::after {
+ opacity: 1;
+ }
+ }
+ }
+
+ .o_list_record_selector, .o_list_record_remove, .o_handle_cell {
+ width: 1px; // to prevent the column to expand
+ }
+
+ .o_list_record_remove button {
+ padding: 0px;
+ background-style: none;
+ border-style: none;
+ height: 0px;
+ display: table-cell;
+ }
+
+ // Decoration of the row
+ .text-bf {
+ font-weight: bold;
+ }
+ .text-it {
+ font-style: italic;
+ }
+ .text-muted {
+ color: lighten(@text-muted, 10%);
+ }
+
+ // Grouped list views
+ tbody > tr.o_group_header {
+ height: 31px;
+
+ .o_group_name {
+ white-space: nowrap;
+ }
+ .o_group_pager {
+ cursor: text;
+ .user-select(none);
+ text-align: right;
+ padding-top: 0;
+ padding-bottom: 0;
+ .o_pager_previous, .o_pager_next {
+ background-color: @odoo-list-group-header-color;
+ &:hover {
+ background-color: darken(@odoo-list-group-header-color, 10%);
+ }
+ }
+ }
+ }
+ tbody + tbody {
+ border-top: none; // Override bootstrap for grouped list views
+ }
+
+ tbody {
+ tr:focus-within {
+ background-color: @odoo-form-lightsecondary;
+ }
+ tr{
+ .focussed {
+ background-color: @odoo-form-lightsecondary;
+ }
+ }
+ }
+
+
+ // Values styling
+ .o_list_number {
+ text-align: right;
+ white-space: nowrap;
+ }
+ .o_list_text {
+ white-space: pre-wrap;
+ }
+
+ .o_data_cell.o_invisible_modifier {
+ // Override display: none to keep table cells aligned. Note: cannot use
+ // 'initial' as it will force them to 'inline', not 'table-cell'.
+ display: table-cell!important;
+ }
+
+ //--------------------------------------------------------------------------
+ // Edition
+ //--------------------------------------------------------------------------
+ .o_data_row.o_selected_row > .o_data_cell:not(.o_readonly_modifier) {
+ position: relative;
+
+ // The in-edition elements will overflow other elements (the rows below,
+ // the content below the list view, ...). As those might be using
+ // position: relative, the in-edition elements have to define a z-index.
+ // Technically, creating a stacking context for a meaningful parent
+ // (maybe the .o_content) might be required for safety but we should
+ // consider this later if needed.
+ z-index: 1;
+
+ // The in-edition elements will overflow other elements (the rows below,
+ // the content below the list view, ...). As those might be using
+ // position: relative, the in-edition elements have to define a z-index.
+ // Technically, creating a stacking context for a meaningful parent
+ // (maybe the .o_content) might be required for safety but we should
+ // consider this later if needed.
+ z-index: 1;
+
+ // Field widgets override
+ > .o_field_widget {
+ .o-position-absolute(0, 0, auto, 0);
+ min-height: 100%;
+
+ &:not(.o_field_text) {
+ white-space: nowrap;
+ }
+
+ &.o_field_many2manytags > .badge {
+ &, > .o_badge_text {
+ white-space: normal;
+ max-width: 100%; // Fix a chrome bug where badge would not break on multiple lines
+ }
+ }
+ }
+ > .o_field_translate {
+ .o-position-absolute(0, 5px);
+ width: 16px; // to have some space on the right
+ }
+ .o_input {
+ padding: @table-condensed-cell-padding;
+ background-color: white;
+
+ .o_input {
+ padding: 0!important;
+ }
+ }
+ .o_input_dropdown {
+ min-height: 100%;
+ }
+ .o_field_monetary input {
+ width: 0;
+ }
+ .o_field_boolean {
+ position: relative!important;
+ }
+ .o_field_widget {
+ min-width: 0;
+ }
+ .o_input_dropdown, .o_datepicker {
+ > .o_input {
+ padding-right: 15px; // To prevent caret overlapping
+ }
+ > .o_dropdown_button, .o_datepicker_button {
+ .o-position-absolute(20%, 5px);
+ }
+ }
+ .o_field_widget > .o_external_button {
+ padding: 0;
+ background-color: inherit;
+ margin-left: 3px;
+ }
+ .o_row_handle {
+ visibility: hidden; // Hide sequence when editing
+ }
+ .o_field_boolean {
+ width: auto!important; // Override the width computed in JS (needed for Chrome)
+ }
+ }
+}
+
+// Buttons in ControlPanel
+.o_list_buttons {
+ .o_list_button_save, .o_list_button_discard {
+ display: none;
+ }
+ &.o-editing { // for list view editable
+ .o_list_button_add {
+ display: none
+ }
+ .o_list_button_save, .o_list_button_discard {
+ display: inline-block
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/list_view_extra.scss b/addons/web/static/src/scss/list_view_extra.scss
new file mode 100644
index 00000000000..9a9413c0dd7
--- /dev/null
+++ b/addons/web/static/src/scss/list_view_extra.scss
@@ -0,0 +1,10 @@
+
+.o_list_view {
+ thead {
+ background-color: #eee;
+ }
+
+ tbody > tr.o_group_header {
+ .o-vertical-gradient(#fcfcfc, #dedede);
+ }
+}
diff --git a/addons/web/static/src/scss/mimetypes.scss b/addons/web/static/src/scss/mimetypes.scss
new file mode 100644
index 00000000000..e4d2624dc6d
--- /dev/null
+++ b/addons/web/static/src/scss/mimetypes.scss
@@ -0,0 +1,70 @@
+.o_image {
+ .square(38px);
+ display: inline-block;
+ background-image: url('/web/static/src/img/mimetypes/unknown.svg');
+ background-size: contain;
+
+ &[data-mimetype^='image'] {
+ background-image: url('/web/static/src/img/mimetypes/image.svg');
+ }
+ &[data-mimetype^='audio'] {
+ background-image: url('/web/static/src/img/mimetypes/audio.svg');
+ }
+ &[data-mimetype^='text'], &[data-mimetype$='rtf'] {
+ background-image: url('/web/static/src/img/mimetypes/text.svg');
+ }
+ &[data-mimetype*='octet-stream'], &[data-mimetype*='download'], &[data-mimetype*='python'] {
+ background-image: url('/web/static/src/img/mimetypes/binary.svg');
+ }
+ &[data-mimetype^='video'], &[title$='.mp4'], &[title$='.avi'] {
+ background-image: url('/web/static/src/img/mimetypes/video.svg');
+ }
+ &[data-mimetype$='archive'], &[data-mimetype$='compressed'], &[data-mimetype*='zip'], &[data-mimetype$='tar'], &[data-mimetype*='package'] {
+ background-image: url('/web/static/src/img/mimetypes/archive.svg');
+ }
+ &[data-mimetype='application/pdf'] {
+ background-image: url('/web/static/src/img/mimetypes/pdf.svg');
+ }
+ &[data-mimetype^='text-master'], &[data-mimetype*='document'], &[data-mimetype*='msword'], &[data-mimetype*='wordprocessing'] {
+ background-image: url('/web/static/src/img/mimetypes/document.svg');
+ }
+ &[data-mimetype*='application/xml'], &[data-mimetype$='html'] {
+ background-image: url('/web/static/src/img/mimetypes/web_code.svg');
+ }
+ &[data-mimetype$='css'], &[data-mimetype$='less'], &[data-ext$='less'] {
+ background-image: url('/web/static/src/img/mimetypes/web_style.svg');
+ }
+ &[data-mimetype*='-image'], &[data-mimetype*='diskimage'], &[data-ext$='dmg'] {
+ background-image: url('/web/static/src/img/mimetypes/disk.svg');
+ }
+ &[data-mimetype$='csv'], &[data-mimetype*='vc'], &[data-mimetype*='excel'], &[data-mimetype$='numbers'], &[data-mimetype$='calc'], &[data-mimetype*='mods'], &[data-mimetype*='spreadsheet'] {
+ background-image: url('/web/static/src/img/mimetypes/spreadsheet.svg');
+ }
+ &[data-mimetype^='key'] {
+ background-image: url('/web/static/src/img/mimetypes/certificate.svg');
+ }
+ &[data-mimetype*='presentation'], &[data-mimetype*='keynote'], &[data-mimetype*='teacher'], &[data-mimetype*='slideshow'], &[data-mimetype*='powerpoint'] {
+ background-image: url('/web/static/src/img/mimetypes/presentation.svg');
+ }
+ &[data-mimetype*='cert'], &[data-mimetype*='rules'], &[data-mimetype*='pkcs'], &[data-mimetype$='stl'], &[data-mimetype$='crl'] {
+ background-image: url('/web/static/src/img/mimetypes/certificate.svg');
+ }
+ &[data-mimetype*='-font'], &[data-mimetype*='font-'], &[data-ext$='ttf'] {
+ background-image: url('/web/static/src/img/mimetypes/font.svg');
+ }
+ &[data-mimetype*='-dvi'] {
+ background-image: url('/web/static/src/img/mimetypes/print.svg');
+ }
+ &[data-mimetype*='script'], &[data-mimetype*='x-sh'], &[data-ext*='bat'], &[data-mimetype$='bat'], &[data-mimetype$='cgi'], &[data-mimetype$='-c'], &[data-mimetype*='java'], &[data-mimetype*='ruby'] {
+ background-image: url('/web/static/src/img/mimetypes/script.svg');
+ }
+ &[data-mimetype*='javascript'] {
+ background-image: url('/web/static/src/img/mimetypes/javascript.svg');
+ }
+ &[data-mimetype*='calendar'], &[data-mimetype$='ldif'] {
+ background-image: url('/web/static/src/img/mimetypes/calendar.svg');
+ }
+ &[data-mimetype$='postscript'], &[data-mimetype$='cdr'], &[data-mimetype$='xara'], &[data-mimetype$='cgm'], &[data-mimetype$='graphics'], &[data-mimetype$='draw'], &[data-mimetype*='svg'] {
+ background-image: url('/web/static/src/img/mimetypes/vector.svg');
+ }
+}
diff --git a/addons/web/static/src/scss/modal.scss b/addons/web/static/src/scss/modal.scss
new file mode 100644
index 00000000000..5b74583ee41
--- /dev/null
+++ b/addons/web/static/src/scss/modal.scss
@@ -0,0 +1,83 @@
+.modal.o_technical_modal {
+
+ .modal-content {
+ border-radius: 0;
+
+ .modal-header .o_subtitle {
+ margin-left: 10px;
+ }
+
+ .modal-body {
+ &.o_act_window {
+ padding: 0;
+ }
+
+ .o_modal_header {
+ .o-webclient-padding(@top: 10px, @bottom: 10px);
+ .clearfix();
+
+ .o_search_options {
+ display: inline-block;
+ }
+ .o_pager {
+ float: right;
+ }
+ }
+ }
+
+ .modal-footer {
+ text-align: left;
+ }
+ }
+
+
+ @media (min-width: @screen-sm-min) {
+ .modal-dialog {
+ height: 100%;
+ padding: 30px 0;
+ margin: 0 auto;
+
+ .modal-content {
+ max-height: 100%;
+ .o-flex-display();
+ .o-flex-flow(column, nowrap);
+
+ .modal-header, .modal-footer {
+ .o-flex(0, 0, auto);
+ }
+
+ .modal-body {
+ overflow: auto;
+ // fix iOS issue https://github.com/scottjehl/Device-Bugs/issues/8
+ -webkit-transform: translate3d(0, 0, 0);
+ min-height: 0;
+
+ &.o_dialog_error {
+ overflow: visible;
+ .o-flex-display();
+ .o-flex-flow(column, nowrap);
+
+ > .alert, > button {
+ .o-flex(0, 0, auto);
+ }
+
+ > .o_error_detail {
+ .o-flex(1, 1, auto);
+ min-height: 0;
+ overflow: auto;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+// Temporary fix for modals which are not instantiated thanks to the Dialog
+// JS classes (deprecated case) (see bootstrap_overridden.less) + Frontend.
+//
+// TODO the following code was disabled because it is saas-incompatible
+//
+// :not(body) > .modal {
+// z-index: @zindex-modal-background + 1;
+// }
diff --git a/addons/web/static/src/scss/model_field_selector.scss b/addons/web/static/src/scss/model_field_selector.scss
new file mode 100644
index 00000000000..aee5bd17867
--- /dev/null
+++ b/addons/web/static/src/scss/model_field_selector.scss
@@ -0,0 +1,130 @@
+
+.o_field_selector {
+ position: relative;
+
+ > .o_field_selector_value {
+ .o-flex-display();
+ .o-flex-flow(row, wrap);
+ .o-align-items(center);
+ height: 100%;
+ min-height: 20px; // needed when there is no value in it and used standalone
+ &:active, &:focus, &:active:focus {
+ outline: none;
+ }
+
+ > .o_field_selector_chain_part {
+ padding: 0px 1px;
+ border: 1px solid darken(@odoo-brand-lightsecondary, 10%);
+ background: @odoo-brand-lightsecondary;
+ margin-bottom: 1px;
+ }
+ > i {
+ .o-align-self(center);
+ margin: 0 2px;
+ font-size: 10px;
+ }
+ }
+ > .o_field_selector_controls {
+ .o-position-absolute(0, 0, 1px);
+ .o-flex-display();
+ .o-align-items(center);
+ cursor: pointer;
+ }
+
+ &.o_edit_mode {
+ > .o_field_selector_controls::after {
+ .o-caret-down();
+ }
+
+ > .o_field_selector_popover {
+ @o-field-selector-arrow-height: 7px;
+ .o-position-absolute(@top: 100%, @left: 0);
+ z-index: 1051;
+ width: 265px;
+ margin-top: @o-field-selector-arrow-height;
+ background: white;
+ box-shadow: 0 3px 10px rgba(0,0,0,.4);
+
+ &:focus {
+ outline: none;
+ }
+
+ .o_field_selector_popover_header {
+ color: white;
+ background: @brand-primary;
+ font-weight: bold;
+ padding: 5px 0 5px 0.4em;
+
+ .o_field_selector_title {
+ width: 100%;
+ .o-text-overflow();
+ padding: 0px 35px;
+ text-align: center;
+ }
+ .o_field_selector_popover_option {
+ .o-position-absolute(@top: 0);
+ padding: 7px 8px 8px 6px;
+
+ &.o_prev_page {
+ left: 0;
+ border-right: 1px solid darken(@brand-primary, 10%);
+ }
+ &.o_field_selector_close {
+ right: 0;
+ border-left: 1px solid darken(@brand-primary, 10%);
+ }
+ &:hover {
+ background: darken(@brand-primary, 10%);
+ }
+ }
+ &:before {
+ .o-position-absolute(@top: -@o-field-selector-arrow-height, @left: @o-field-selector-arrow-height);
+ content: "";
+ border-left: @o-field-selector-arrow-height solid rgba(0, 0, 0, 0);
+ border-right: @o-field-selector-arrow-height solid rgba(0, 0, 0, 0);
+ border-bottom: @o-field-selector-arrow-height solid @brand-primary;
+ }
+ }
+ .o_field_selector_popover_body {
+ .o_field_selector_page {
+ position: relative;
+ max-height: 320px;
+ overflow: auto;
+ margin: 0;
+ padding: 0;
+
+ > .o_field_selector_item {
+ list-style: none;
+ position: relative;
+ padding: 5px 0 5px 0.4em;
+ cursor: pointer;
+ font-family: Arial;
+ font-size: 13px;
+ color: #444;
+ border-bottom: 1px solid #eee;
+ &.active {
+ background: #f5f5f5;
+ }
+ .o_field_selector_item_title {
+ font-size: 12px;
+ }
+ .o_field_selector_relation_icon {
+ .o-position-absolute(@top: 0, @right: 0, @bottom: 0);
+ .o-flex-display();
+ .o-align-items(center);
+ padding: 10px;
+ }
+ }
+ }
+ }
+ .o_field_selector_popover_footer {
+ background: @brand-primary;
+ padding: 5px 0.4em;
+
+ > input {
+ width: 100%;
+ }
+ }
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/navbar.scss b/addons/web/static/src/scss/navbar.scss
new file mode 100644
index 00000000000..cf14f9a8615
--- /dev/null
+++ b/addons/web/static/src/scss/navbar.scss
@@ -0,0 +1,233 @@
+
+.o_main_navbar {
+ position: relative;
+ height: @odoo-navbar-height;
+ border-bottom: 1px solid @odoo-navbar-inverse-link-hover-bg;
+ background-color: @odoo-brand-primary;
+ color: white;
+
+ > a, > button {
+ float: left;
+ height: @odoo-navbar-height;
+ border: none;
+ padding: 0 @odoo-horizontal-padding - 4px 0 @odoo-horizontal-padding;
+ line-height: @odoo-navbar-height;
+ background-color: transparent;
+ text-align: center;
+ color: inherit;
+
+ font-size: 18px;
+ .user-select(none);
+
+ &:hover, &:focus {
+ background-color: @odoo-navbar-inverse-link-hover-bg;
+ color: inherit;
+ }
+ &:focus, &:active, &:focus:active {
+ outline: none;
+ }
+ }
+
+ > .o_menu_brand {
+ display: block;
+ float: left;
+ margin-right: 35px;
+ .user-select(none);
+ color: white;
+ font-size: 22px;
+ font-weight: 500;
+ line-height: @odoo-navbar-height;
+
+ @media (max-width: @screen-xs-max) {
+ float: none;
+ margin: 0;
+ border-bottom: 1px solid @odoo-navbar-inverse-link-hover-bg;
+ color: transparent;
+ }
+ }
+
+ > .o_menu_toggle {
+ margin-right: 5px;
+ }
+
+ > ul {
+ display: block;
+ float: left;
+ margin: 0;
+ padding: 0;
+ list-style: none;
+
+ > li {
+ position: relative;
+ display: block;
+ float: left;
+
+ > a {
+ display: block;
+ height: @odoo-navbar-height;
+ padding: 0 10px;
+ color: white;
+ line-height: @odoo-navbar-height;
+
+ &:hover {
+ background-color: @odoo-navbar-inverse-link-hover-bg;
+ }
+
+ &:focus, &:active, &:focus:active {
+ outline: none;
+ }
+ }
+
+ &.o_extra_menu_items {
+ > a {
+ width: @odoo-navbar-height;
+ text-align: center;
+ }
+ &.open > ul {
+ padding: 0;
+
+ > li {
+ > a {
+ background-color: @odoo-brand-primary;
+ color: white;
+ border-bottom: 1px solid @odoo-brand-lightsecondary;
+
+ &.dropdown-toggle {
+ background-color: lighten(@odoo-brand-primary, 15%);
+ pointer-events: none; // hack to prevent clicking on it because dropdown always opened
+ }
+ }
+ > ul { // remove dropdown-menu default style as it is nested in another one
+ position: static;
+ float: none;
+ display: block;
+ border: none;
+ box-shadow: none;
+ max-height: none;
+ }
+ }
+ }
+ }
+ }
+
+ &.o_menu_systray {
+ float: right;
+ .open .dropdown-menu {
+ left: auto;
+ right: 0;
+ }
+ }
+ }
+
+ .open .dropdown-menu {
+ max-height: 90vh; // the dropdown should not overstep the viewport
+ min-width: 100%;
+ overflow: auto;
+ margin-top: 0;
+
+ .o-menu-indentation(@index) when (@index < 6) {
+ > li.o_menu_header_lvl_@{index}, > li .o_menu_entry_lvl_@{index} {
+ padding-left: @odoo-dropdown-hpadding + (@index - 2)*12px;
+ }
+ .o-menu-indentation(@index + 1);
+ }
+ .o-menu-indentation(3);
+ }
+
+ .open .dropdown-toggle {
+ background-color: @odoo-navbar-inverse-link-hover-bg;
+ }
+ .o_user_menu {
+ margin-left: 6px;
+
+ > a {
+ padding-right: @odoo-horizontal-padding;
+ }
+
+ .oe_topbar_avatar {
+ height: 17px;
+ .o-transform(translateY(-2px));
+ }
+ }
+
+ @media (max-width: @screen-xs-max) {
+ .o-transition(height, 200ms, linear);
+
+ position: relative;
+ height: @odoo-navbar-height;
+ overflow: hidden;
+
+ > ul {
+ > li {
+ float: none;
+ .dropdown-backdrop {
+ display: none;
+ }
+
+ &.open .dropdown-menu {
+ max-height: none;
+ }
+ }
+
+ &.o_menu_sections {
+ width: 100%;
+
+ > li.open .dropdown-menu {
+ position: static;
+ float: none;
+ background-color: transparent;
+ box-shadow: none;
+ border: none;
+ overflow: visible;
+
+ > li > a {
+ background-color: transparent;
+ color: inherit;
+ }
+ }
+ }
+
+ &.o_menu_systray {
+ .o-position-absolute(0px, @odoo-navbar-height, auto, @odoo-navbar-height);
+ height: @odoo-navbar-height;
+ text-align: right;
+
+ > li {
+ display: inline-block;
+
+ &.open .dropdown-menu {
+ .o-position-absolute(@odoo-navbar-height, 0, 0, 0);
+ position: fixed;
+ width: auto;
+ }
+ }
+
+ .o_user_menu .oe_topbar_name {
+ display: none;
+ }
+ }
+ }
+ }
+}
+
+@media (max-width: @screen-xs-max) {
+ body.o_mobile_menu_opened {
+ overflow: hidden;
+ height: 100%;
+ height: 100vh;
+
+ .o_main_navbar {
+ height: 100%;
+ overflow: auto;
+ }
+ }
+}
+
+@media (max-width: @screen-xs-max) {
+ .o_switch_company_menu > .dropdown-menu {
+ padding-top: 0px;
+ li.bg-info {
+ padding: 10px;
+ }
+ }
+ }
diff --git a/addons/web/static/src/scss/pivot_view.scss b/addons/web/static/src/scss/pivot_view.scss
new file mode 100644
index 00000000000..d7dfdd45de5
--- /dev/null
+++ b/addons/web/static/src/scss/pivot_view.scss
@@ -0,0 +1,78 @@
+.o_pivot {
+ overflow: auto;
+
+ // Inform the user that he may click on a cell to be redirected to a list view of the
+ // items corresponding to the clicked cell
+ &.o_enable_linking {
+ .o_pivot_cell_value:hover {
+ color: @odoo-brand-optional;
+ cursor: pointer;
+ }
+ }
+
+ table {
+ background-color: @odoo-view-background-color;
+ width: auto; // bootstrap override
+
+ th {
+ font-weight: normal; // bootstrap override
+ background-color: lighten(@odoo-brand-secondary, 40%);
+ }
+
+ .o-pivot-header-cell() {
+ background-color: lighten(@odoo-brand-secondary, 40%);
+ cursor: pointer;
+ white-space: nowrap;
+ .user-select(none);
+ &:hover {
+ background-color: lighten(@odoo-brand-secondary, 30%);
+ }
+ }
+
+ .o_pivot_measure_row {
+ .o-pivot-header-cell;
+ }
+
+ .o_pivot_header_cell_closed {
+ .o-pivot-header-cell;
+ &::before {
+ font-family: FontAwesome;
+ content: "";
+ margin-right: 8px;
+ }
+ }
+
+ .o_pivot_header_cell_opened {
+ .o-pivot-header-cell;
+ &::before {
+ font-family: FontAwesome;
+ content: "";
+ margin-right: 8px;
+ }
+ }
+
+ .o_pivot_measure_row_sorted_asc::after {
+ .o-caret-down;
+ margin-left: 5px;
+ }
+
+ .o_pivot_measure_row_sorted_desc::after {
+ .o-caret-up;
+ margin-left: 5px;
+ }
+ }
+
+ .o_pivot_field_selection::after {
+ .o-caret-right;
+ position: absolute;
+ right: 6px;
+ top: 9px;
+ }
+}
+
+// ------------------------------------------------------------------
+// Control panel buttons
+// ------------------------------------------------------------------
+.o_pivot_measures_list {
+ .o-selected-li;
+} \ No newline at end of file
diff --git a/addons/web/static/src/scss/progress_bar.scss b/addons/web/static/src/scss/progress_bar.scss
new file mode 100644
index 00000000000..25a89d15ecf
--- /dev/null
+++ b/addons/web/static/src/scss/progress_bar.scss
@@ -0,0 +1,36 @@
+.o_progressbar {
+
+ > div {
+ display: inline-block;
+ }
+
+ .o_progressbar_title {
+ white-space: nowrap;
+ padding-right: 10px;
+ }
+
+ .o_progress {
+ width: 100px;
+ height: 15px;
+ vertical-align: middle;
+
+ border: 1px solid lighten(@odoo-brand-secondary, 25%);
+ overflow: hidden;
+
+ background-color: white;
+ &.o_progress_overflow {
+ background-color: @odoo-brand-secondary;
+ }
+
+ .o_progressbar_complete {
+ background-color: @odoo-brand-optional;
+ height: 100%;
+ }
+ }
+
+ .o_progressbar_value {
+ width: 100px;
+ white-space: nowrap;
+ padding-left: 10px;
+ }
+}
diff --git a/addons/web/static/src/scss/rainbow.scss b/addons/web/static/src/scss/rainbow.scss
new file mode 100644
index 00000000000..b86387b18ca
--- /dev/null
+++ b/addons/web/static/src/scss/rainbow.scss
@@ -0,0 +1,257 @@
+/************** rainbow *****************/
+
+// Variables
+@reward-size: 400px;
+@reward-size-mobile: 300px;
+@reward-text-color: #727880;
+@reward-base-time: 1.4s;
+
+// o_reward
+.o_reward {
+ will-change: transform;
+ z-index: @zindex-modal;
+ padding: 50px;
+ margin: -5% auto 0 -(@reward-size / 2);
+ @media (max-width: @screen-xs-max) {
+ margin: -5% auto 0 -(@reward-size-mobile / 2);
+ }
+ background-image: -webkit-radial-gradient(#EDEFF4 30%, transparent 70%, transparent);
+ background-image: -o-radial-gradient(#EDEFF4 30%, transparent 70%, transparent);
+ background-image: radial-gradient(#EDEFF4 30%, transparent 70%, transparent);
+
+ .o-animation(reward-fading, @reward-base-time * 0.5, ease-in-out, 0s, 1, normal, forwards);
+ .o-position-absolute(20%, auto, auto, 50%);
+ .size(@reward-size, @reward-size);
+ @media (max-width: @screen-xs-max) {
+ .size(@reward-size-mobile, @reward-size-mobile);
+ }
+
+ &.o_reward_fading {
+ display: block;
+ .o-animation(reward-fading-reverse, (@reward-base-time * 0.4), ease-in-out, 0s, 1, normal, forwards);
+
+ .o_reward_face_group {
+ .o-animation(reward-jump-reverse, (@reward-base-time * 0.4), ease-in-out, 0s, 1, normal, forwards);
+ }
+
+ .o_reward_rainbow {
+ path {
+ .o-animation(reward-rainbow-reverse, (@reward-base-time * 0.5), ease-out, 0s, 1, normal, forwards);
+ }
+ }
+
+ }
+
+ .o_reward_face, .o_reward_stars, .o_reward_shadow, .o_reward_thumbup {
+ margin: 0 auto;
+ }
+
+ .o_reward_rainbow {
+ path {
+ stroke-dasharray: 600;
+ stroke-dashoffset: 0;
+ fill: none;
+ stroke-linecap: round;
+ stroke-width: 21px;
+ .o-animation(reward-rainbow, (@reward-base-time ), ease-out, 0s, 1, normal, forwards);
+ }
+ }
+
+ .o_reward_face_group {
+ transform-origin: center;
+ .o-animation(reward-jump, @reward-base-time * 0.8, ease-in-out);
+ .o-position-absolute(6%, 0, 0, 0);
+ .size(100%, 60%);
+ }
+
+ .o_reward_face {
+ display: block;
+ top: 42%;
+ position: relative;
+ border-radius: 100%;
+ background: center center / contain no-repeat;
+ .o-animation(reward-float, @reward-base-time, ease-in-out, @reward-base-time, infinite, alternate);
+ .size(34%, 56.67%);
+ }
+
+ .o_reward_stars {
+ display: block;
+ .size(@reward-size * 0.75, @reward-size / 2);
+ @media (max-width: @screen-xs-max) {
+ .size(@reward-size-mobile * 0.75, @reward-size-mobile / 2);
+ }
+ .o-position-absolute(18%, 7%);
+
+ svg {
+ transform-origin: center center;
+ .o-position-absolute(28%, @left:3%);
+ .o-animation(reward-stars, @reward-base-time, ease-in-out, 0s, infinite, alternate-reverse);
+
+ &.star2, &.star4 {
+ .o-animation(reward-stars, (@reward-base-time*1.2), ease-in-out, 0s, infinite, alternate);
+ }
+
+ &.star2 {
+ left: 20%;
+ top: 2%;
+ }
+
+ &.star3 {
+ left: 49%;
+ top: 6%;
+ }
+
+ &.star4 {
+ left: 70%;
+ top: 27%;
+ }
+
+ }
+ }
+
+ .o_reward_thumbup {
+ width: 40px;
+ display: block;
+ .o-animation(reward-scale, @reward-base-time * 0.5, ease-in-out, 0s, infinite, alternate);
+ .o-position-absolute(63%, auto, auto, 65%);
+ }
+
+ .o_reward_msg_container {
+ will-change: transform;
+ padding-top: 11%;
+ width: 70%;
+ margin-left: 15%;
+
+ // Translate before animate
+ .o-transform(translateY(5px));
+
+ .o-animation(reward-float, @reward-base-time, ease-in-out, @reward-base-time, infinite, alternate-reverse);
+ .o-position-absolute(85%, auto, auto, 0%);
+
+ .o_reward_thumb_right {
+ height: 40px;
+ z-index: 1;
+ .o-position-absolute(0, auto, auto, 16%);
+ }
+
+ .o_reward_msg {
+ margin-left: 7%;
+ margin-top: -9.5%;
+ padding: 25px 15px 20px;
+ background: white;
+ border: 1px solid #ecf1ff;
+ border-top-width: 0;
+ display: inline-block;
+
+ // Reset margins for first and penultimate childs (the last one is shadow)
+ *:first-child {
+ margin-top: 0;
+ }
+ }
+
+ .o_reward_msg_content {
+ position: relative;
+ font-family: sans-serif;
+ text-align: left;
+ color: @reward-text-color;
+ }
+
+ .o_reward_shadow_container {
+ .o-transform(~"translateY(0px) rotateZ(0)");
+ .o-animation(reward-float, @reward-base-time, ease-in-out, @reward-base-time, infinite, alternate);
+ }
+
+ .o_reward_shadow {
+ .size(100%, 12px);
+ background-color: #e7eaf0;
+ border-radius: 100%;
+ .o-transform(~"scale(0.8) rotateZ(0)");
+ .o-animation(reward-scale, @reward-base-time, ease-in-out, @reward-base-time, infinite, alternate);
+ .o-position-absolute(auto, auto, -40px, 0);
+ }
+ }
+}
+
+@keyframes reward-fading {
+ 0% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
+}
+
+@keyframes reward-fading-reverse {
+ 100% {
+ opacity: 0;
+ }
+}
+
+@keyframes reward-jump {
+ 0% {
+ .o-transform(~"scale(0.5)");
+ }
+ 50% {
+ .o-transform(~"scale(1.05)");
+ }
+ to {
+ .o-transform(~"scale(1)");
+ }
+}
+
+@keyframes reward-jump-reverse {
+ 0% {
+ .o-transform(~"scale(1)");
+ }
+ 50% {
+ .o-transform(~"scale(1.05)");
+ }
+ to {
+ .o-transform(~"scale(0.5)");
+ }
+}
+
+@keyframes reward-rainbow {
+ 0% {
+ stroke-dashoffset: -500;
+ }
+ to {
+ stroke-dashoffset: 0;
+ }
+}
+
+@keyframes reward-rainbow-reverse {
+ to {
+ stroke-dashoffset: -500;
+ }
+}
+
+@keyframes reward-float {
+ from {
+ .o-transform(~"translateY(0px)");
+ }
+ to {
+ .o-transform(~"translateY(5px)");
+ }
+}
+
+@keyframes reward-stars {
+ from {
+ .o-transform(~"scale(0.3) rotate(0deg)");
+ }
+ 50% {
+ .o-transform(~"scale(1.0) rotate(20deg)");
+ }
+ to {
+ .o-transform(~"scale(0.3) rotate(80deg)");
+ }
+}
+
+@keyframes reward-scale {
+ from {
+ .o-transform(~"scale(0.8)");
+ }
+ to {
+ .o-transform(~"scale(1.0)");
+ }
+}
diff --git a/addons/web/static/src/scss/report.editor.scss b/addons/web/static/src/scss/report.editor.scss
new file mode 100644
index 00000000000..544787ff6b2
--- /dev/null
+++ b/addons/web/static/src/scss/report.editor.scss
@@ -0,0 +1,26 @@
+.o_editable {
+ &:not(:empty), &[data-oe-type] {
+ &[date-oe-model="ir.ui.view"] {
+ &, th, td {
+ &:hover {
+ -moz-box-shadow: #DDCC33 0 0 5px 2px inset;
+ -webkit-box-shadow: #DDCC33 0 0 5px 2px inset;
+ box-shadow: #DDCC33 0 0 5px 2px inset;
+ }
+ }
+ }
+ }
+}
+
+body.o_in_iframe {
+ margin-top: 40px!important;
+ div#web_editor-top-edit {
+ > form {
+ display: none;
+ }
+ }
+
+ .header, .footer {
+ display: none;
+ }
+}
diff --git a/addons/web/static/src/scss/report.scss b/addons/web/static/src/scss/report.scss
new file mode 100644
index 00000000000..f34a2393fbe
--- /dev/null
+++ b/addons/web/static/src/scss/report.scss
@@ -0,0 +1,35 @@
+html, body {
+ height: 100%;
+}
+
+body {
+ color: #000 !important;
+ word-wrap: break-word;
+}
+.border-black td {
+ border-top: 1px solid black !important;
+}
+
+/* See https://github.com/wkhtmltopdf/wkhtmltopdf/issues/1524 */
+.table-condensed {
+ > thead > tr > th {
+ border-bottom: none !important;
+ }
+ > tbody > tr {
+ page-break-inside: avoid !important;
+ border-top: none !important;
+ }
+}
+.zero_min_height {
+ min-height: 0px !important;
+}
+
+/* To avoid broken snippets in report rendering */
+.jumbotron, .panel, .carousel, section{
+ page-break-inside: avoid;
+}
+
+/* Wkhtmltopdf doesn't support very well the media-print CSS (depends on the version) */
+.hidden-print{
+ display: none;
+}
diff --git a/addons/web/static/src/scss/report_backend.scss b/addons/web/static/src/scss/report_backend.scss
new file mode 100644
index 00000000000..62252c2d9f7
--- /dev/null
+++ b/addons/web/static/src/scss/report_backend.scss
@@ -0,0 +1,14 @@
+.o_report_iframe {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ border: none;
+}
+
+.o_report_no_edit_mode, .o_edit_mode_available, .o_report_edit_mode {
+ display: inline-block;
+}
diff --git a/addons/web/static/src/scss/search_view.scss b/addons/web/static/src/scss/search_view.scss
new file mode 100644
index 00000000000..0261806631a
--- /dev/null
+++ b/addons/web/static/src/scss/search_view.scss
@@ -0,0 +1,220 @@
+.o-search-options-dropdown-custom-li() {
+ margin: 3px 25px;
+ width: auto;
+ max-width: 250px;
+}
+
+.o_searchview {
+ .o-flex-display();
+ .o-flex-flow(row, wrap);
+ .o-align-items(flex-end);
+ position: relative;
+ padding: 0 20px 1px 0;
+
+ .o_searchview_facet {
+ @o-searchview-facet-remove-width: 18px;
+
+ .o-flex(0, 0, auto);
+ max-width: 100%;
+ .o-flex-display();
+ position: relative;
+ margin: 1px 3px 0 0;
+
+ .o_searchview_facet_label {
+ .o-flex(0, 0, auto);
+ .o-text-overflow();
+ padding: 0 3px;
+ color: white;
+
+ .o-flex-display();
+ .o-align-items(center);
+ }
+
+ .o_facet_values {
+ padding: 0 @o-searchview-facet-remove-width 0 5px;
+ .o_facet_values_sep {
+ font-style: italic;
+ }
+ }
+ .o_facet_remove {
+ .o-flex(0, 0, auto);
+ .o-flex-display();
+ .o-justify-content(center);
+ .o-align-items(center);
+ .o-position-absolute(0, 0, 0);
+ width: @o-searchview-facet-remove-width;
+ cursor: pointer;
+ }
+ }
+
+ .o_searchview_input {
+ width: 100px;
+ .o-flex(1, 0, auto);
+ }
+
+ .o_searchview_more {
+ font-size: 16px;
+ cursor: pointer;
+ }
+
+ .o_searchview_autocomplete {
+ .o-position-absolute(100%, @left: auto);
+ width: 100%;
+
+ li {
+ padding-left: 25px;
+ position: relative;
+ &.o-indent {
+ padding-left: 50px;
+ }
+ a {
+ display: inline-block;
+ padding-left: 0px;
+ padding-right: 0px;
+ &:hover {
+ background-color: inherit;
+ }
+ &.o-expand, &.o-expanded { // caret
+ .o-position-absolute(@left: 6px);
+ padding: 3px;
+ }
+ &.o-expand:before {
+ .o-caret-right;
+ }
+ &.o-expanded:before {
+ .o-caret-down;
+ }
+ }
+ }
+ }
+}
+
+// Searchview and Sidebar dropdowns
+// FIXME: move me out of here
+.o_dropdown {
+ white-space: nowrap; // prevent the arrow from going under the dropdown when too little space
+ .dropdown-toggle:first-child {
+ // apply the padding to the first element so that when the `favorites` menu goes under
+ // the `filters` menu, they're still aligned
+ padding-right: 10px;
+ }
+
+ display: inline-block;
+ cursor: pointer;
+ .user-select(none); // Prevent text selection when toggling the dropdowns
+ > a { // dropdown togglers
+ color: @odoo-main-text-color;
+ &:hover {
+ text-decoration: none;
+ font-weight: bold;
+ color: darken(@odoo-main-text-color, 10%);
+ }
+ }
+ &.open > a {
+ font-weight: bold;
+ color: darken(@odoo-main-text-color, 10%);
+ }
+}
+
+// Searchview dropdowns
+.o_search_options {
+ // Open and closed carets in dropdowns
+ .o_closed_menu {
+ position: relative;
+ a:before {
+ .o-caret-right;
+ .o-position-absolute(@top: 50%, @left: 10px);
+ margin-top: (-@caret-width-base);
+ }
+ }
+ .o_open_menu {
+ position: relative;
+ a:before {
+ .o-caret-down;
+ .o-position-absolute(@top: 50%, @left: 10px);
+ margin-top: (-@caret-width-base);
+ }
+ }
+
+ // Filters
+ .o_filters_menu {
+ .o-selected-li;
+
+ max-height: ~"calc(100vh - 125px)";
+ overflow: auto;
+
+ .o_filter_condition {
+ .o-search-options-dropdown-custom-li;
+ margin-bottom: 8px;
+ .o_or_filter { // or between conditions
+ display: none; // hidden for the first condition
+ .o-position-absolute(@top: 7px, @left: -18px);
+ }
+ }
+ .o_filter_condition + .o_filter_condition {
+ .o_or_filter {
+ display: block; // displayed from second condition
+ }
+ }
+ .o_searchview_extended_prop_op {
+ margin: 3px 0px; // vertical gap between selects
+ }
+ .o_searchview_extended_prop_value { // date fields: datepicker position
+ .datepickerbutton {
+ .o-position-absolute(3px, -20px);
+ cursor: pointer;
+ }
+ }
+ .o_searchview_extended_delete_prop { // delete condition button position
+ .o-position-absolute(3px, -18px);
+ cursor: pointer;
+ }
+ .o_add_filter_menu { // apply and add buttons
+ display: none; // Needed by the webclient
+ .o-search-options-dropdown-custom-li;
+ }
+ }
+
+ // Group By
+ .o_group_by_menu {
+ .o-selected-li;
+
+ max-height: ~"calc(100vh - 125px)";
+ overflow: auto;
+
+ .divider {display: none;} // hide the divider by default (no group)
+ .o_add_group { // add button
+ display: none; // Needed by the webclient
+ .o-search-options-dropdown-custom-li;
+ }
+ }
+
+ // Favorites
+ .o_favorites_menu {
+ max-height: 75vh;
+ overflow-y: auto;
+ .o-selected-li;
+
+ max-height: ~"calc(100vh - 125px)";
+ overflow: auto;
+
+ .divider {display: none;} // hide the divider by default (no favorite)
+ .o-searchview-custom-private, .o-searchview-custom-public {
+ .o-remove-filter {
+ .o-position-absolute(50%, 12px);
+ margin-top: -6px;
+ cursor: pointer;
+ }
+ }
+ .o-searchview-custom-public a:after {
+ font-family: FontAwesome;
+ content: "\f0c0";
+ margin-left: 5px;
+ font-weight: normal;
+ }
+ .o_save_name { // save button
+ display: none; // hidden by default
+ .o-search-options-dropdown-custom-li;
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/search_view_extra.scss b/addons/web/static/src/scss/search_view_extra.scss
new file mode 100644
index 00000000000..9c263976e4d
--- /dev/null
+++ b/addons/web/static/src/scss/search_view_extra.scss
@@ -0,0 +1,43 @@
+.o_searchview {
+ background-color: white;
+ border: 1px solid #ccc;
+ border-radius: @border-radius-base;
+ padding: 1px 25px 3px 5px;
+
+ .o_searchview_facet {
+ border: 1px solid @gray-light;
+ background: lighten(@odoo-brand-primary, 35%);
+
+ .o_searchview_facet_label {
+ background-color: @gray-light;
+ }
+
+ .o_facet_remove {
+ color: @gray-light;
+ &:hover {
+ color: @gray;
+ }
+ }
+ }
+
+ .o_searchview_input {
+ border: none;
+ padding: 4px 0 0 0;
+ }
+ .o_searchview_more {
+ .o-position-absolute(@top: 6px, @right: 5px);
+ }
+ .o_searchview_autocomplete li.o-selection-focus {
+ background-color: @odoo-brand-primary;
+ > a {
+ color: white;
+ }
+ }
+}
+
+// Search options: inputs and selects style
+.o_search_options {
+ input[type="text"], select {
+ .form-control();
+ }
+}
diff --git a/addons/web/static/src/scss/tooltip.scss b/addons/web/static/src/scss/tooltip.scss
new file mode 100644
index 00000000000..e071bf04a40
--- /dev/null
+++ b/addons/web/static/src/scss/tooltip.scss
@@ -0,0 +1,59 @@
+
+.tooltip {
+ padding: 0;
+ margin: 0;
+ opacity: 1;
+
+ .tooltip-inner {
+ max-width: 300px; // fallback for browsers which do not support "vw" unit
+ max-width: 100vw;
+ background-color: @odoo-tooltip-background-color;
+ color: @odoo-tooltip-color;
+ border-radius: @border-radius-base;
+ box-shadow: 0px 0px 1px 1px @odoo-brand-secondary;
+
+ padding: 5px;
+
+ text-align: left;
+
+ .oe_tooltip_string {
+ background-color: @odoo-brand-primary;
+ color: white;
+ font-weight: bold;
+ padding: 5px;
+ }
+ .oe_tooltip_help {
+ white-space: pre-line;
+ padding: 5px 5px 0;
+ }
+ .oe_tooltip_technical {
+ padding: 0;
+ margin: 5px 0 5px 20px;
+ list-style-type: circle;
+
+ .oe_tooltip_technical_title {
+ font-weight: bold;
+ }
+ }
+ }
+
+ .tooltip-arrow {
+ -moz-transform: scale(0.9999);
+ }
+ &.top, &.top-left, &.top-right {
+ .tooltip-arrow {
+ border-top-color: @odoo-tooltip-arrow-color!important;
+ }
+ }
+ &.bottom, &.bottom-left, &.bottom-right {
+ .tooltip-arrow {
+ border-bottom-color: @odoo-tooltip-arrow-color!important;
+ }
+ }
+ &.left .tooltip-arrow {
+ border-left-color: @odoo-tooltip-arrow-color!important;
+ }
+ &.right .tooltip-arrow {
+ border-right-color: @odoo-tooltip-arrow-color!important;
+ }
+}
diff --git a/addons/web/static/src/scss/ui.scss b/addons/web/static/src/scss/ui.scss
new file mode 100644
index 00000000000..0a387331031
--- /dev/null
+++ b/addons/web/static/src/scss/ui.scss
@@ -0,0 +1,11 @@
+.o_hidden {
+ display: none!important;
+}
+
+.o_text_overflow {
+ .o-text-overflow();
+}
+
+.ui-autocomplete {
+ z-index: @zindex-modal + 1;
+}
diff --git a/addons/web/static/src/scss/ui_extra.scss b/addons/web/static/src/scss/ui_extra.scss
new file mode 100644
index 00000000000..0d97c09092e
--- /dev/null
+++ b/addons/web/static/src/scss/ui_extra.scss
@@ -0,0 +1,10 @@
+//------------------------------------------------------------------------------
+// Checkboxes
+//------------------------------------------------------------------------------
+div.o_checkbox {
+ display: inline-block;
+ vertical-align: sub;
+ > input + span {
+ display: none;
+ }
+}
diff --git a/addons/web/static/src/scss/utils.scss b/addons/web/static/src/scss/utils.scss
new file mode 100644
index 00000000000..e89da21b4f6
--- /dev/null
+++ b/addons/web/static/src/scss/utils.scss
@@ -0,0 +1,274 @@
+///
+/// This file regroups the odoo mixins. They are available in every asset bundle.
+///
+
+// ------------------------------------------------------------------
+// Padding
+// ------------------------------------------------------------------
+.o-webclient-padding(@top: 0px, @right: @odoo-horizontal-padding, @bottom: 0px, @left: @odoo-horizontal-padding) {
+ padding-top: @top;
+ padding-right: @right;
+ padding-bottom: @bottom;
+ padding-left: @left;
+}
+
+// ------------------------------------------------------------------
+// Caret
+// ------------------------------------------------------------------
+.utils-caret-boilerplate() {
+ content: "";
+ display: inline-block;
+ width: 0;
+ height: 0;
+ vertical-align: middle;
+}
+.o-caret-down(@caret-width: @caret-width-base) {
+ .utils-caret-boilerplate;
+ border-bottom: 0;
+ border-left: @caret-width solid transparent;
+ border-right: @caret-width solid transparent;
+ border-top: @caret-width solid;
+ -moz-transform: scale(0.9999); // Smooth the caret on firefox
+}
+.o-caret-up(@caret-width: @caret-width-base) {
+ .utils-caret-boilerplate;
+ border-bottom: @caret-width solid;
+ border-left: @caret-width solid transparent;
+ border-right: @caret-width solid transparent;
+ border-top: 0;
+ -moz-transform: scale(0.9999); // Smooth the caret on firefox
+}
+.o-caret-left(@caret-width: @caret-width-base) {
+ .utils-caret-boilerplate;
+ border-bottom: @caret-width solid transparent;
+ border-left: 0;
+ border-right: @caret-width solid;
+ border-top: @caret-width solid transparent;
+ -moz-transform: scale(0.9999); // Smooth the caret on firefox
+}
+.o-caret-right(@caret-width: @caret-width-base) {
+ .utils-caret-boilerplate;
+ border-bottom: @caret-width solid transparent;
+ border-left: @caret-width solid;
+ border-right: 0;
+ border-top: @caret-width solid transparent;
+ -moz-transform: scale(0.9999); // Smooth the caret on firefox
+}
+
+// ------------------------------------------------------------------
+// Vendor prefixes
+// ------------------------------------------------------------------
+// Flex
+.o-flex-display() {
+ display: -ms-flexbox;
+ display: -moz-box;
+ display: -webkit-box;
+ display: -webkit-flex;
+
+ display: flex;
+}
+.o-inline-flex-display() {
+ display: -ms-inline-flexbox;
+ display: -moz-inline-box;
+ display: -webkit-inline-box;
+ display: -webkit-inline-flex;
+
+ display: inline-flex;
+}
+.o-flex-flow(@direction, @wrap) {
+ -ms-flex-flow: @direction @wrap;
+ -moz-flex-flow: @direction @wrap;
+ -webkit-flex-flow: @direction @wrap;
+
+ flex-flow: @direction @wrap;
+}
+.o-flex(@grow, @schrink, @basis) {
+ -ms-flex: @grow @schrink @basis;
+ -moz-flex: @grow @schrink @basis;
+ -webkit-box-flex: @grow;
+ -webkit-flex: @grow @schrink @basis;
+
+ flex: @grow @schrink @basis;
+}
+.o-justify-content(@justify) {
+ -moz-justify-content: @justify;
+ -webkit-justify-content: @justify;
+
+ justify-content: @justify;
+}
+.o-align-content(@align) {
+ -webkit-align-content: @align;
+
+ align-content: @align;
+}
+.o-align-items(@align) {
+ -webkit-align-items: @align;
+
+ align-items: @align;
+}
+.o-align-self(@align) {
+ -webkit-align-self: @align;
+
+ align-self: @align;
+}
+
+// Background-size
+.o-background-size(@size) {
+ -webkit-background-size: @size;
+ -moz-background-size: @size;
+ -o-background-size: @size;
+ background-size: @size;
+}
+
+// ------------------------------------------------------------------
+// Dropdowns
+// ------------------------------------------------------------------
+.o-selected-li() {
+ li {
+ position: relative;
+ > a {
+ color: @odoo-main-text-color;
+ &:hover {
+ color: darken(@odoo-main-text-color, 10%);
+ }
+ }
+ &.selected {
+ > a {
+ color: darken(@odoo-main-text-color, 10%);
+ font-weight: bold;
+ &:before {
+ font-family: FontAwesome;
+ position: absolute;
+ left: 6px;
+ content: "\f00c";
+ }
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------
+// Select Appearance
+// ------------------------------------------------------------------
+.o-appearance(@value) {
+ -webkit-appearance: @value;
+ -moz-appearance: @value;
+ appearance: @value;
+}
+
+// ------------------------------------------------------------------
+// Transform
+// ------------------------------------------------------------------
+.o-transform-origin(@x: 50%, @y: 50%, @z: 0) {
+ -ms-transform-origin: @x @y @z;
+ -webkit-transform-origin: @x @y @z;
+ -moz-transform-origin: @x @y @z;
+ transform-origin: @x @y @z;
+}
+
+// ------------------------------------------------------------------
+// Animation
+// ------------------------------------------------------------------
+.o-animation(@name: none, @duration: 0s, @timing-function: ease, @delay: 0s, @iteration-count: 1, @direction: normal, @fill-mode: none, @play-state: running) {
+ -webkit-animation: @name @duration @timing-function @delay @iteration-count @direction @fill-mode @play-state;
+ -moz-animation: @name @duration @timing-function @delay @iteration-count @direction @fill-mode @play-state;
+ -o-animation: @name @duration @timing-function @delay @iteration-count @direction @fill-mode @play-state;
+ animation: @name @duration @timing-function @delay @iteration-count @direction @fill-mode @play-state;
+}
+
+// ------------------------------------------------------------------
+// Transition
+// ------------------------------------------------------------------
+.o-transition(@property: all, @duration: 0s, @timing-function: ease, @transition-delay: 0s) {
+ -webkit-transition: @property @duration @timing-function @transition-delay;
+ -moz-transition: @property @duration @timing-function @transition-delay;
+ -o-transition: @property @duration @timing-function @transition-delay;
+ transition: @property @duration @timing-function @transition-delay;
+}
+
+// ------------------------------------------------------------------
+// Columns
+// ------------------------------------------------------------------
+.o-columns(@width: auto, @col: auto) {
+ -webkit-columns: @width @col;
+ -moz-columns: @width @col;
+ columns: @width @col;
+}
+
+// ------------------------------------------------------------------
+// Position absolute
+// ------------------------------------------------------------------
+.o-position-absolute(@top: auto, @right: auto, @bottom: auto, @left: auto) {
+ position: absolute;
+ top: @top;
+ left: @left;
+ bottom: @bottom;
+ right: @right;
+}
+
+// ------------------------------------------------------------------
+// Text overflow
+// ------------------------------------------------------------------
+.o-text-overflow(@display: inline-block, @max-width: 100%) {
+ display: @display;
+ max-width: @max-width;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ vertical-align: top; // To update display context changed by overflow:hidden
+}
+
+// ------------------------------------------------------------------
+// Gradients
+// ------------------------------------------------------------------
+.o-linear-gradient(@deg: 45deg, @start-color: #555, @end-color: #333) {
+ background-repeat: repeat-x;
+ background-image: -webkit-linear-gradient(@deg, @start-color, @end-color);
+ background-image: -o-linear-gradient(@deg, @start-color, @end-color);
+ background-image: linear-gradient(@deg, @start-color, @end-color);
+}
+.o-vertical-gradient(@startColor: #555, @endColor: #333) {
+ background-color: mix(@startColor, @endColor);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(@startColor), to(@endColor));
+ background-image: -webkit-linear-gradient(top, @startColor, @endColor);
+ background-image: -moz-linear-gradient(top, @startColor, @endColor);
+ background-image: -ms-linear-gradient(top, @startColor, @endColor);
+ background-image: -o-linear-gradient(top, @startColor, @endColor);
+ background-image: linear-gradient(to bottom, @startColor, @endColor);
+}
+.o-skew-gradient(@startColor: #555, @endColor: #333) {
+ background-color: @endColor;
+ background: -moz-linear-gradient(135deg, @endColor, @startColor);
+ background: -o-linear-gradient(135deg, @startColor, @endColor);
+ background: -webkit-gradient(linear, left top, right bottom, from(@startColor), to(@endColor));
+ background: -ms-linear-gradient(top, @startColor, @endColor);
+}
+
+// ------------------------------------------------------------------
+// Transform
+// ------------------------------------------------------------------
+.o-transform(@transform) {
+ -webkit-transform: @transform;
+ -moz-transform: @transform;
+ -ms-transform: @transform;
+ -o-transform: @transform;
+ transform: @transform;
+}
+
+// ------------------------------------------------------------------
+// Hovering effects
+// ------------------------------------------------------------------
+.o-hover-opacity(@default-opacity: 0.5, @hover-opacity: 1) {
+ opacity: @default-opacity;
+
+ &:hover, &:focus, &.focus {
+ opacity: @hover-opacity;
+ }
+}
+.o-hover-text-color(@default-color: @text-color, @hover-color: @link-color) {
+ color: @default-color;
+
+ &:hover, &:focus, &.focus {
+ color: @hover-color;
+ }
+}
diff --git a/addons/web/static/src/scss/variables.scss b/addons/web/static/src/scss/variables.scss
new file mode 100644
index 00000000000..1b4d2f09468
--- /dev/null
+++ b/addons/web/static/src/scss/variables.scss
@@ -0,0 +1,92 @@
+///
+/// This file regroups the variables that style odoo components.
+/// They are available in every asset bundle.
+///
+
+// Font sizes
+@odoo-font-size-base: 13px;
+
+// Colors
+@odoo-brand-primary: #7c7bad;
+@odoo-brand-optional: #7c7bad;
+@odoo-brand-secondary: #f0eeee;
+@odoo-brand-lightsecondary: #e2e2e0;
+@odoo-color-silver: #F9F9F9;
+@odoo-color-silver-dark: #E5E5E5;
+@odoo-color-silver-darker: #d9d7d7;
+
+// Define @gray-lighter-dark as a minor bootstrap @gray-lighter variation used
+// for design purposes only (e.g. cards' borders). We avoid to overwrite the
+// default @gray-light because it is deeply used by bootstrap to define muted
+// elements.
+@gray-lighter-dark: @odoo-color-silver-dark;
+@gray-lighter-darker: @odoo-color-silver-darker;
+
+@odoo-color-pink: #875A7B; // Enterprise @odoo-brand-primary
+@odoo-main-color-muted: #a8a8a8;
+@odoo-main-text-color: #4c4c4c;
+
+@odoo-view-background-color: white;
+@odoo-shadow-color: #303030;
+
+@odoo-webclient-background-color: @odoo-color-silver;
+@odoo-control-panel-background-color: @odoo-color-silver;
+@odoo-form-lightsecondary: #ccc;
+
+@odoo-list-footer-color: @odoo-main-text-color;
+@odoo-list-footer-bg-color: #eee;
+@odoo-list-footer-font-weight: bold;
+
+@odoo-tooltip-background-color: black;
+@odoo-tooltip-color: white;
+@odoo-tooltip-arrow-color: black;
+@odoo-tooltip-text-color: #777777;
+@odoo-tooltip-title-text-color: #4c4c4c;
+
+// UI custom colors for tags, kanban records' colors, ...)
+@odoo-nb-ui-color: 12;
+@odoo-color-0: @gray-light;
+@odoo-color-1: #F06050;
+@odoo-color-2: #F4A460;
+@odoo-color-3: #F7CD1F;
+@odoo-color-4: #6CC1ED;
+@odoo-color-5: #814968;
+@odoo-color-6: #EB7E7F;
+@odoo-color-7: #2C8397;
+@odoo-color-8: #475577;
+@odoo-color-9: #D6145F;
+@odoo-color-10: #30C381;
+@odoo-color-11: #9365B8;
+
+// Layout
+@screen-xs-min: 475px;
+@screen-xxs-max: (@screen-xs-min - 1);
+
+@screen-xl-min: 1534px;
+@screen-lg-max: (@screen-xl-min - 1);
+
+@odoo-form-group-cols: 12;
+@odoo-form-spacing-unit: 5px;
+@odoo-horizontal-padding: 16px;
+@odoo-innergroup-rpadding: 45px;
+@odoo-dropdown-hpadding: 20px;
+
+@border-radius-base: 3px;
+
+@odoo-sheet-vpadding: 24px;
+
+// Needed for having no spacing between sheet and mail body in mass_mailing:
+// Different required cancel paddings between web and web_enterprise
+@odoo-sheet-cancel-tpadding: 0px;
+@odoo-sheet-cancel-hpadding: @odoo-horizontal-padding;
+@odoo-sheet-cancel-bpadding: @odoo-horizontal-padding;
+
+@odoo-avatar-size: 90px;
+
+@odoo-statusbar-height: 33px;
+@odoo-statusbar-arrow-width: @odoo-statusbar-height/3;
+@odoo-statusbar-disabled-bg: lighten(@odoo-brand-lightsecondary, 7%);
+
+@odoo-label-font-size-factor: 0.8;
+@odoo-navbar-height: 34px;
+@odoo-navbar-inverse-link-hover-bg: @navbar-inverse-link-active-bg;
diff --git a/addons/web/static/src/scss/views.scss b/addons/web/static/src/scss/views.scss
new file mode 100644
index 00000000000..0c7936fc570
--- /dev/null
+++ b/addons/web/static/src/scss/views.scss
@@ -0,0 +1,103 @@
+/**
+ * This file regroups the rules which apply on elements which are shared between
+ * all renderers. For field default rules, see the fields.less file.
+ */
+
+// Invisible modifier (can be inside the view, the button area, ...)
+.o_invisible_modifier {
+ display: none!important;
+}
+
+// Status
+// This should normally be put in fields.less but these classes are used outside
+// of `.o_field_widget` so it needs to be placed at an upper level.
+.o_status {
+ display: inline-block;
+ height: 12px;
+ width: 12px;
+ border-radius: 6px;
+ vertical-align: middle;
+
+ background-color: @gray-lighter-dark;
+
+ &.o_status_green {
+ background-color: @brand-success;
+ }
+ &.o_status_red {
+ background-color: @brand-danger;
+ }
+}
+
+.o_btn-link-as-button {
+ padding: 2px;
+ font-size:12px;
+
+ & > a {
+ margin-bottom: -4px !important;
+ margin-left: 3px;
+ }
+}
+
+// No content helper
+.o_view_nocontent {
+ .o-position-absolute(20%, 0, 0, 0);
+ pointer-events: none;
+ z-index: 1;
+
+ .o_nocontent_help {
+ pointer-events: auto;
+ max-width: 650px;
+ margin: auto;
+ padding: 15px;
+ z-index: 1000;
+ text-align: center;
+ color: @odoo-tooltip-text-color;
+ font-size: 115%;
+
+ > p:first-of-type {
+ margin-top: 0;
+ color: @odoo-tooltip-title-text-color;
+ font-weight: bold;
+ font-size: 125%;
+ }
+
+ a {
+ cursor: pointer;
+ }
+
+ .o-init-image() {
+ content: "";
+ display: block;
+ margin: auto;
+ background-size: cover;
+ }
+
+ .o_view_nocontent_smiling_face:before {
+ .o-init-image();
+ .size(120px, 140px);
+ background: transparent url(/web/static/src/img/smiling_face.svg) no-repeat center;
+ }
+
+ .o_view_nocontent_neutral_face:before {
+ .o-init-image();
+ .size(120px, 140px);
+ background: transparent url(/web/static/src/img/neutral_face.svg) no-repeat center;
+ }
+
+ .o_view_nocontent_empty_folder:before {
+ .o-init-image();
+ .size(120px, 80px);
+ margin-top: 30px;
+ margin-bottom: 30px;
+ background: transparent url(/web/static/src/img/empty_folder.svg) no-repeat center;
+ }
+
+ .o_empty_custom_dashboard {
+ min-height: 327px;
+ margin-left: -@grid-gutter-width/2;
+ margin-top: -@grid-gutter-width/2;
+ padding: 100px 0 0 137px;
+ background: transparent url(/web/static/src/img/graph_background.png) no-repeat 0 0;
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/web_calendar.scss b/addons/web/static/src/scss/web_calendar.scss
new file mode 100644
index 00000000000..5179552b3b6
--- /dev/null
+++ b/addons/web/static/src/scss/web_calendar.scss
@@ -0,0 +1,230 @@
+@nb-calendar-colors: 24;
+
+@keyframes backgroundfade {
+ from {background-color: fade(@odoo-brand-primary, 50%);}
+ to {background-color: #f5f5f5;}
+}
+
+.o_calendar_container {
+ height: 100%;
+ .o-webclient-padding(@top: @odoo-horizontal-padding/2, @bottom: @odoo-horizontal-padding/2);
+ .o-flex-display();
+
+ .calendar_color_loop(@index) when (@index < @nb-calendar-colors+1) {
+ .o_calendar_color_@{index} {
+ color: #0D0D0D;
+ background-color: spin(rgb(255, 192, 192), 360/(@nb-calendar-colors+1) * @index);
+ border-color: spin(rgb(255, 192, 192), 360/(@nb-calendar-colors+1) * @index);
+ opacity: 0.7;
+ &.o_event_hightlight {
+ font-weight: bold;
+ opacity: 0.9;
+ }
+ &:hover {
+ color: #666 !important;
+ }
+ }
+ .calendar_color_loop(@index + 1);
+ }
+ .calendar_color_loop(1);
+
+ .underline_color_loop(@index) when (@index < @nb-calendar-colors+1) {
+ .o_underline_color_@{index} {
+ border-bottom: 4px solid spin(rgba(255, 192, 192, 0.7), 360/(@nb-calendar-colors+1) * @index);
+ }
+ .underline_color_loop(@index + 1);
+ }
+ .underline_color_loop(1);
+
+ .o_calendar_view {
+ .o-flex(1, 1, auto);
+ min-width: 0;
+
+ .o_calendar_widget {
+ height: 100%;
+ background-color: @odoo-view-background-color;
+ * {
+ z-index: 0; // FIXME
+ }
+ .fc-week-number, .fc-widget-header {
+ background-color: lighten(@odoo-brand-secondary, 30%);
+ }
+ .o_avatar_square {
+ border-radius: 5px;
+ display: inline-block;
+ opacity: 1;
+ border: 1px solid #999;
+ }
+ .o_fields img, .o_avatar_square {
+ vertical-align: middle;
+ margin-left: 1px;
+ width: 18px;
+ height: 18px;
+ }
+ .o_field_type_char:first-child {
+ font-weight: bold;
+ }
+ .fc-view {
+ overflow-x: auto;
+ }
+ }
+ }
+
+ .o_calendar_sidebar_container {
+ .o-flex(0, 0, @odoo-horizontal-padding);
+ position: relative;
+
+ &.o_sidebar_hidden {
+ margin-right: -@odoo-horizontal-padding; // hack to display the toggler in the gutter
+ .o_calendar_sidebar_toggler {
+ padding: 4px;
+ color: darken(@odoo-webclient-background-color, 30%);
+ }
+ }
+
+ .o_calendar_sidebar_toggler {
+ .o-position-absolute(@top: 0, @right: 0);
+ cursor: pointer;
+ padding: 6px;
+ z-index: 1;
+ &:hover {
+ color: black;
+ }
+ }
+
+ .o_calendar_sidebar {
+ width: 250px;
+ margin-left: 8px;
+ background: @odoo-view-background-color;
+ }
+
+ .ui-datepicker {
+ width: 100%;
+ font-size: 8pt;
+ border-radius: 0;
+ border: none;
+ padding: 0;
+
+ .ui-widget-header {
+ .o-flex-display();
+ background: none;
+ background-color: lighten(@odoo-brand-secondary, 30%);
+ border-radius: 0;
+
+ .ui-datepicker-prev, .ui-datepicker-next {
+ .o-flex(0, 0, auto);
+ position: static;
+ cursor: pointer;
+ padding: 2px;
+ text-align: center;
+ color: @odoo-main-text-color;
+ &.ui-state-hover {
+ background: none;
+ border: none;
+ color: black;
+ }
+ .ui-icon {
+ display: none;
+ }
+ }
+ .ui-datepicker-prev {
+ order: 1;
+ &:after {
+ font-family: FontAwesome;
+ content: "";
+ }
+ }
+ .ui-datepicker-next {
+ order: 3;
+ &:before {
+ font-family: FontAwesome;
+ content: "";
+ }
+ }
+ .ui-datepicker-title {
+ .o-flex(0, 0, auto);
+ order: 2;
+ display: inline-block;
+ margin: 0 10px;
+ }
+ }
+ table {
+ td {
+ padding: 0 2px 2px 0;
+ background-color: @odoo-view-background-color;
+ a {
+ border: none;
+ background: none;
+ background-color: lighten(@odoo-brand-secondary, 40%);
+ text-align: center;
+ }
+ }
+ .ui-state-default {
+ color: @odoo-brand-primary;
+ &:hover {
+ background: none;
+ background-color: fade(@odoo-brand-primary, 50%);
+ border-color: @odoo-brand-primary;
+ color: @odoo-view-background-color;
+ };
+ }
+ .ui-state-active {
+ background: none;
+ background-color: @odoo-brand-primary;
+ color: @odoo-view-background-color;
+ }
+ .o_selected_range.o_color {
+ background: none;
+ background-color: @odoo-brand-primary;
+ animation: backgroundfade 3s forwards;
+ }
+ }
+ }
+ .o_calendar_filter {
+ padding: 8px;
+ border-top: 1px solid lightgray;
+ .o_field_many2one {
+ width: 100%;
+ }
+ }
+ }
+
+ .fc-time-grid-event.fc-short .fc-time:before {
+ content: '';
+ }
+}
+
+.modal {
+ .o_attendee_head {
+ width: 32px;
+ margin-right: 5px;
+ }
+}
+
+.o_dashboard {
+ .o_calendar_container .o_calendar_sidebar_container {
+ display: none;
+ }
+}
+
+// Mobile rules
+@media only screen and (max-width: 768px) {
+ .o_calendar_container {
+ padding: 0;
+ }
+}
+@media (max-width: @screen-xs-max) {
+ .o_control_panel {
+ .o_calendar_button_today {
+ float: right;
+ > .o_calendar_text {
+ margin-top: 3px;
+ }
+ }
+ }
+ .o_calendar_view {
+ .fc-day-header {
+ word-spacing: 1000px; // force line break in week mode
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/webclient.scss b/addons/web/static/src/scss/webclient.scss
new file mode 100644
index 00000000000..1de198d282b
--- /dev/null
+++ b/addons/web/static/src/scss/webclient.scss
@@ -0,0 +1,140 @@
+// ------------------------------------------------------------------
+// General
+// ------------------------------------------------------------------
+.o_web_client {
+ position: relative; // normally useless but required by bootstrap-datepicker
+ background-color: @odoo-webclient-background-color;
+}
+
+// ------------------------------------------------------------------
+// Misc. widgets
+// ------------------------------------------------------------------
+@notification-error-bg-color: #F16567;
+@notification-info-bg-color: #FCFBEA;
+.o_notification_manager {
+ width: 300px;
+ max-width: 100%;
+
+ .o-position-absolute(@navbar-height, 0px);
+ z-index: 1100; // Bootstrap modal z-index is 1050
+
+ .o_notification {
+ padding: 0;
+ margin: 5px 0 0 0;
+
+ opacity: 0;
+
+ background-color: @notification-info-bg-color;
+ box-shadow: 0px 0px 5px 1px @odoo-main-text-color;
+
+ position: relative;
+ .o_close {
+ .o-position-absolute(5px, 5px);
+ color: rgba(0, 0, 0, 0.3);
+ text-decoration: none;
+ }
+
+ .o_notification_title {
+ .o-flex-display();
+ .o-align-items(center);
+
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+ padding: 10px 10px 10px 20px;
+
+ font-weight: bold;
+
+ .o_icon {
+ display: inline-block;
+ margin-right: 20px;
+ color: rgba(0, 0, 0, 0.3);
+ }
+ }
+
+ .o_notification_content {
+ padding: 10px;
+ }
+
+ &.o_error {
+ color: white;
+ background-color: @notification-error-bg-color;
+ }
+ }
+}
+
+// Buttons
+.o_icon_button {
+ background-color: transparent;
+ border: 0;
+ padding: 0;
+ outline: none;
+}
+
+// Boolean Toggle widget
+div.o_boolean_toggle {
+ position: relative;
+ display: inline-block;
+ width: 32px !important;
+ height: 18px;
+
+ > input {
+ display: none;
+ }
+
+ .slider {
+ position: absolute;
+ cursor: pointer;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: #a0a0a0;
+ border-radius: 24px;
+
+ &:before {
+ position: absolute;
+ content: "";
+ height: 12px;
+ width: 12px;
+ left: 3px;
+ bottom: 3px;
+ background-color: white;
+ border-radius: 50%;
+ }
+ }
+
+ > input:checked + .slider {
+ background-color: @odoo-brand-optional;
+
+ &:before {
+ .translate(14px; 0px);
+ }
+ }
+}
+
+// Full bg colors (bootstrap extension)
+.bg-success-full {
+ background-color: @brand-success;
+}
+.bg-warning-full {
+ background-color: @brand-warning;
+}
+.bg-danger-full {
+ background-color: @brand-danger;
+}
+.bg-info-full {
+ background-color: @brand-info;
+}
+
+.o_web_accesskey_overlay {
+ font-family: @font-family-sans-serif;
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ left: 0;
+ top: 0;
+ background-color: rgba(0,0,0,.6);
+ color: #FFFFFF;
+ justify-content: center;
+ display: flex;
+ align-items: center;
+} \ No newline at end of file
diff --git a/addons/web/static/src/scss/webclient_extra.scss b/addons/web/static/src/scss/webclient_extra.scss
new file mode 100644
index 00000000000..82798437672
--- /dev/null
+++ b/addons/web/static/src/scss/webclient_extra.scss
@@ -0,0 +1,46 @@
+//------------------------------------------------------------------------------
+// Inputs and selects (note: put the o_input class to have the style)
+//------------------------------------------------------------------------------
+[type="text"], [type="password"], [type="number"], textarea, select {
+ width: 100%;
+ display: block;
+ outline: none;
+}
+.o_input {
+ border: 1px solid @odoo-form-lightsecondary;
+ border-radius: @border-radius-base;
+ padding: 2px 4px;
+ color: #1f1f1f;
+
+ .o_input {
+ border: none!important;
+ padding: 0;
+ }
+}
+select {
+ background: white;
+}
+
+//------------------------------------------------------------------------------
+// Loading
+//------------------------------------------------------------------------------
+.o_loading {
+ position: fixed;
+ top: 0;
+ right: 50%;
+ padding: 4px 12px;
+ background-color: @odoo-color-pink;
+ color: white;
+ text-align: center;
+ border-top: none;
+ border-bottom-right-radius: 8px;
+ border-bottom-left-radius: 8px;
+}
+
+//------------------------------------------------------------------------------
+// User menu in navbar
+//------------------------------------------------------------------------------
+#oe_main_menu_navbar .oe_user_menu_placeholder .o_user_menu .oe_topbar_name {
+ .o-text-overflow();
+ max-width: 150px;
+}
diff --git a/addons/web/static/src/scss/webclient_layout.scss b/addons/web/static/src/scss/webclient_layout.scss
new file mode 100644
index 00000000000..f876d8b3527
--- /dev/null
+++ b/addons/web/static/src/scss/webclient_layout.scss
@@ -0,0 +1,165 @@
+@odoo-submenu-width: 220px;
+
+.o_web_client {
+ .o-flex-display();
+ .o-flex-flow(column, nowrap);
+ overflow: hidden;
+
+ &.o_fullscreen {
+ #oe_main_menu_navbar {
+ display: none;
+ }
+ .o_main .o_sub_menu {
+ display: none;
+ }
+ }
+
+
+ .navbar {
+ .o-flex(0, 0, auto);
+
+ li > a {
+ padding: 4px 8px;
+ margin-top: 2px;
+ font-size: 13px;
+ }
+
+ .oe_topbar_avatar {
+ max-height: 18px;
+ width: 18px;
+ }
+ }
+
+ > .o_main {
+ .o-flex(1, 1, auto);
+ .o-flex-display();
+ min-height: 0; // Allow flex to shrink this element as much as it wants
+ height: 100%;
+
+ .o_sub_menu {
+ .o-flex(0, 0, @odoo-submenu-width);
+ .o-flex-display();
+ .o-flex-flow(column, nowrap);
+ border-right: 1px solid darken(@odoo-control-panel-background-color, 20%);
+ background-color: @odoo-control-panel-background-color;
+
+ .o_sub_menu_logo {
+ .o-flex(0, 0, auto);
+ text-align: center;
+ position: relative;
+
+ > img {
+ margin: 14px 0;
+ }
+
+ .oe_logo_edit {
+ position: absolute;
+ top: 1px;
+ width: 100%;
+ padding: 4px;
+ margin: 14px 0;
+ display: none;
+ color: #eee;
+ background: rgba(37,37,37,0.9);
+ }
+ &:hover .oe_logo_edit_admin {
+ display: block;
+ }
+ }
+
+ .o_sub_menu_content {
+ .o-flex(1, 1, auto);
+ height:100%;
+ overflow-y: auto;
+
+ .oe_secondary_menu_section {
+ font-weight: bold;
+ margin-left: 8px;
+ color: @odoo-brand-optional;
+ }
+ .oe_secondary_submenu {
+ margin: 3px 0px 10px;
+ line-height: 1.1em;
+ >li:not(.active) > a {
+ color: @odoo-main-text-color;
+ }
+ > li > a {
+ padding: 4px 4px 4px 18px;
+ > .badge {
+ margin-top: -1px;
+ }
+ }
+ .oe_secondary_submenu {
+ > li > a {
+ padding-left: 30px;
+ }
+ .oe_secondary_submenu > li > a {
+ padding-left: 42px;
+ }
+ }
+ .oe_menu_text {
+ .o-text-overflow();
+ max-width: 85%;
+ margin-top: 1px;
+ }
+ .oe_menu_toggler:before {
+ display: inline-block;
+ width: 0;
+ height: 0;
+ content: "&darr";
+ opacity: 0.5;
+ text-indent: -99999px;
+ vertical-align: top;
+ margin-left: -12px;
+ margin-top: 4px;
+ margin-right: 4px;
+ border-top: 4px solid transparent;
+ border-bottom: 4px solid transparent;
+ border-left: 4px solid #4c4c4c;
+ }
+ .oe_menu_opened:before {
+ margin-top: 6px;
+ margin-left: -16px;
+ margin-right: 4px;
+ border-left: 4px solid transparent;
+ border-right: 4px solid transparent;
+ border-top: 4px solid #4c4c4c;
+ }
+ }
+ }
+
+ .o_sub_menu_footer {
+ .o-flex(0, 0, auto);
+ text-align: center;
+
+ > a {
+ font-weight: bold;
+ > span {
+ color: @odoo-color-pink;
+ }
+ }
+ }
+ }
+
+ .o_main_content {
+ .o-flex(1, 1, auto);
+ .o-flex-display();
+ .o-flex-flow(column, nowrap);
+
+ .o_control_panel {
+ .o-flex(0, 0, auto);
+ }
+ .o_content {
+ .o-flex(1, 1, auto);
+ height: 100%;
+ overflow: auto;
+ position: relative;
+
+ > .o_view_controller {
+ .o-position-absolute(0, 0, 0, 0); // Get the 100% height of its flex parent
+ height: 100%;
+ }
+ }
+ }
+ }
+}