[IMP] scss: update, improve preexisting content

Add a new content focused on SCSS and user-interface.

- SCSS coding guidelines: regroup information already available (eg [1])
  or based on "oral tradition".
  The aim is not to establish new rules, ~99% of the current codebase
  is already compliant.

- SCSS inheritance: explain how SCSS assets management works in odoo.
  For example, people still find confusing that overrides are defined
  *before* the variable to customize.

- SCSS optimization tips: suggestions to lean SCSS code. Based on SCSS
  optimization task's know-how [2].

- CSS variables: explain how this feature is commonly used in odoo to
  adapt layout & design without raw CSS overrides.

- UI Icons: Add link to fontAwesome4 library . Replace the picture of
  odoo icons with the actual font (90kb image VS 15Kb font)

[1] https://github.com/odoo/odoo/wiki/SCSS-coding-guidelines
[2] https://www.odoo.com/web#id=2704984&menu_id=4720&cids=1&model=project.task&view_type=form

task-3090800

closes odoo/documentation#3327

X-original-commit: 2ca32b40bc
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
This commit is contained in:
stefanorigano (SRI)
2022-10-27 08:19:25 +00:00
committed by Antoine Vandevenne (anv)
parent 8a30786495
commit 9571a32131
17 changed files with 1094 additions and 17 deletions

View File

@@ -921,8 +921,8 @@ Symbols and Conventions
.. _contributing/development/js_guidelines:
Javascript and CSS
==================
Javascript
==========
Static files organization
--------------------------
@@ -969,14 +969,373 @@ More precise JS guidelines are detailed in the `github wiki <https://github.com
You may also have a look at existing API in Javascript by looking Javascript
References.
CSS coding guidelines
.. _contributing/coding_guidelines/scss:
CSS and SCSS
============
.. _contributing/coding_guidelines/scss/formatting:
Syntax and Formatting
---------------------
- Prefix all your classes with *o_<module_name>* where *module_name* is the
technical name of the module ('sale', 'im_chat', ...) or the main route
reserved by the module (for website module mainly, i.e. : 'o_forum' for
*website_forum* module). The only exception for this rule is the
webclient: it simply uses *o_* prefix.
- Avoid using *id* tag
- Use Bootstrap native classes
- Use underscore lowercase notation to name class
.. tabs::
.. code-tab:: html SCSS
.o_foo, .o_foo_bar, .o_baz {
height: $o-statusbar-height;
.o_qux {
height: $o-statusbar-height * 0.5;
}
}
.o_corge {
background: $o-list-footer-bg-color;
}
.. code-tab:: css CSS
.o_foo, .o_foo_bar, .o_baz {
height: 32px;
}
.o_foo .o_quux, .o_foo_bar .o_quux, .o_baz .o_qux {
height: 16px;
}
.o_corge {
background: #EAEAEA;
}
- four (4) space indents, no tabs;
- columns of max. 80 characters wide;
- opening brace (`{`): empty space after the last selector;
- closing brace (`}`): on its own new line;
- one line for each declaration;
- meaningful use of whitespace.
.. spoiler:: Suggested Stylelint settings
.. code-block:: html
"stylelint.config": {
"rules": {
// https://stylelint.io/user-guide/rules
// Avoid errors
"block-no-empty": true,
"shorthand-property-no-redundant-values": true,
"declaration-block-no-shorthand-property-overrides": true,
// Stylistic conventions
"indentation": 4,
"function-comma-space-after": "always",
"function-parentheses-space-inside": "never",
"function-whitespace-after": "always",
"unit-case": "lower",
"value-list-comma-space-after": "always-single-line",
"declaration-bang-space-after": "never",
"declaration-bang-space-before": "always",
"declaration-colon-space-after": "always",
"declaration-colon-space-before": "never",
"block-closing-brace-empty-line-before": "never",
"block-opening-brace-space-before": "always",
"selector-attribute-brackets-space-inside": "never",
"selector-list-comma-space-after": "always-single-line",
"selector-list-comma-space-before": "never-single-line",
}
},
.. _contributing/coding_guidelines/scss/properties_order:
Properties order
----------------
Order properties from the "outside" in, starting from `position` and ending with decorative rules
(`font`, `filter`, etc.).
:ref:`Scoped SCSS variables <contributing/coding_guidelines/scss/scoped_scss_variables>` and
:ref:`CSS variables <contributing/coding_guidelines/scss/css_variables>` must be placed at the very
top, followed by an empty line separating them from other declarations.
.. code-block:: html
.o_element {
$-inner-gap: $border-width + $legend-margin-bottom;
--element-margin: 1rem;
--element-size: 3rem;
@include o-position-absolute(1rem);
display: block;
margin: var(--element-margin);
width: calc(var(--element-size) + #{$-inner-gap});
border: 0;
padding: 1rem;
background: blue;
font-size: 1rem;
filter: blur(2px);
}
.. _contributing/coding_guidelines/scss/naming_conventions:
Naming Conventions
------------------
Naming conventions in CSS are incredibly useful in making your code more strict, transparent and
informative.
| Avoid `id` selectors, and prefix your classes with `o_<module_name>`, where `<module_name>` is the
technical name of the module (`sale`, `im_chat`, ...) or the main route reserved by the module
(for website modules mainly, i.e. : `o_forum` for the `website_forum` module).
| The only exception for this rule is the webclient: it simply uses the `o_` prefix.
Avoid creating hyper-specific classes and variable names. When naming nested elements, opt for the
"Grandchild" approach.
.. rst-class:: bg-light
.. example::
.. container:: alert alert-danger
Don't
.. code-block:: html
<div class=“o_element_wrapper”>
<div class=“o_element_wrapper_entries”>
<span class=“o_element_wrapper_entries_entry”>
<a class=“o_element_wrapper_entries_entry_link”>Entry</a>
</span>
</div>
</div>
.. container:: alert alert-success
Do
.. code-block:: html
<div class=“o_element_wrapper”>
<div class=“o_element_entries”>
<span class=“o_element_entry”>
<a class=“o_element_link”>Entry</a>
</span>
</div>
</div>
Besides being more compact, this approach eases maintenance because it limits the need of renaming
when changes occur at the DOM.
.. _contributing/coding_guidelines/scss/scss_variables:
SCSS Variables
~~~~~~~~~~~~~~
Our standard convention is `$o-[root]-[element]-[property]-[modifier]`, with:
* `$o-`
The prefix.
* `[root]`
Either the component **or** the module name (components take priority).
* `[element]`
An optional identifier for inner elements.
* `[property]`
The property/behavior defined by the variable.
* `[modifier]`
An optional modifier.
.. example::
.. code-block:: scss
$o-block-color: value;
$o-block-title-color: value;
$o-block-title-color-hover: value;
.. _contributing/coding_guidelines/scss/scoped_scss_variables:
SCSS Variables (scoped)
~~~~~~~~~~~~~~~~~~~~~~~
These variables are declared within blocks and are not accessible from the outside.
Our standard convention is `$-[variable name]`.
.. example::
.. code-block:: html
.o_element {
$-inner-gap: compute-something;
margin-right: $-inner-gap;
.o_element_child {
margin-right: $-inner-gap * 0.5;
}
}
.. seealso::
`Variables scope on the SASS Documentation
<https://sass-lang.com/documentation/variables#scope>`_
.. _contributing/coding_guidelines/scss/mixins:
SCSS Mixins and Functions
~~~~~~~~~~~~~~~~~~~~~~~~~
Our standard convention is `o-[name]`. Use descriptive names. When naming functions, use verbs in
the imperative form (e.g.: `get`, `make`, `apply`...).
Name optional arguments in the :ref:`scoped variables form
<contributing/coding_guidelines/scss/scoped_scss_variables>`, so `$-[argument]`.
.. example::
.. code-block:: html
@mixin o-avatar($-size: 1.5em, $-radius: 100%) {
width: $-size;
height: $-size;
border-radius: $-radius;
}
@function o-invert-color($-color, $-amount: 100%) {
$-inverse: change-color($-color, $-hue: hue($-color) + 180);
@return mix($-inverse, $-color, $-amount);
}
.. seealso::
- `Mixins on the SASS Documentation <https://sass-lang.com/documentation/at-rules/mixin>`_
- `Functions on the SASS Documentation <https://sass-lang.com/documentation/at-rules/function>`_
.. _contributing/coding_guidelines/scss/css_variables:
CSS Variables
~~~~~~~~~~~~~
In Odoo, the use of CSS variables is strictly DOM-related. Use them to **contextually** adapt the
design and layout.
Our standard convention is BEM, so `--[root]__[element]-[property]--[modifier]`, with:
* `[root]`
Either the component **or** the module name (components take priority).
* `[element]`
An optional identifier for inner elements.
* `[property]`
The property/behavior defined by the variable.
* `[modifier]`
An optional modifier.
.. example::
.. code-block:: scss
.o_kanban_record {
--KanbanRecord-width: value;
--KanbanRecord__picture-border: value;
--KanbanRecord__picture-border--active: value;
}
// Adapt the component when rendered in another context.
.o_form_view {
--KanbanRecord-width: another-value;
--KanbanRecord__picture-border: another-value;
--KanbanRecord__picture-border--active: another-value;
}
.. _contributing/coding_guidelines/scss/variables_use:
Use of CSS Variables
--------------------
In Odoo, the use of CSS variables is strictly DOM-related, meaning that are used to **contextually**
adapt the design and layout rather than to manage the global design-system. These are typically used
when a component's properties can vary in specific contexts or in other circumstances.
We define these properties inside the component's main block, providing default fallbacks.
.. example::
.. code-block:: scss
:caption: :file:`my_component.scss`
.o_MyComponent {
color: var(--MyComponent-color, #313131);
}
.. code-block:: scss
:caption: :file:`my_dashboard.scss`
.o_MyDashboard {
// Adapt the component in this context only
--MyComponent-color: #017e84;
}
.. seealso::
`CSS variables on MDN web docs
<https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties>`_
.. _contributing/coding_guidelines/scss/css_scss_variables_use:
CSS and SCSS Variables
~~~~~~~~~~~~~~~~~~~~~~
Despite being apparently similar, `CSS` and `SCSS` variables behave very differently. The main
difference is that, while `SCSS` variables are **imperative** and compiled away, `CSS` variables are
**declarative** and included in the final output.
.. seealso::
`CSS/SCSS variables difference on the SASS Documentation
<https://sass-lang.com/documentation/variables#:~:text=CSS%20variables%20are%20included%20in,use%20will%20stay%20the%20same>`_
In Odoo, we take the best of both worlds: using the `SCSS` variables to define the design-system
while opting for the `CSS` ones when it comes to contextual adaptations.
The implementation of the previous example should be improved by adding SCSS variables in order to
gain control at the top-level and ensure consistency with other components.
.. example::
.. code-block:: scss
:caption: :file:`secondary_variables.scss`
$o-component-color: $o-main-text-color;
$o-dashboard-color: $o-info;
// [...]
.. code-block:: text
:caption: :file:`component.scss`
.o_component {
color: var(--MyComponent-color, #{$o-component-color});
}
.. code-block:: text
:caption: :file:`dashboard.scss`
.o_dashboard {
--MyComponent-color: #{$o-dashboard-color};
}
.. _contributing/coding_guidelines/scss/root:
The `:root` pseudo-class
~~~~~~~~~~~~~~~~~~~~~~~~
Defining CSS variables on the `:root` pseudo-class is a technique we normally **don't use** in
Odoo's UI. The practice is commonly used to access and modify CSS variables globally. We perform
this using SCSS instead.
Exceptions to this rule should be fairly apparent, such as templates shared across bundles that
require a certain level of contextual awareness in order to be rendered properly.