# Styling and Theming Visual SDK Web Components

The Theme Engine generates _style modules_ that allow SDK developers to only load the styling that is needed. The style modules are created for both the convergence components and the contributed components.

The style modules are plain Javascript modules that load the necessary styling for a single component. If the component depends on sub-components, their style modules will be included automatically. The Javascript module loader loads each requested module once, regardless of how many times it is requested.


## Using Style Modules

The style modules can be used in at least three ways:

- A single hardcoded theme for the entire application. (This is probably the most common usage.)
- Import styling for several themes and dynamically switch between them, including using different themes for different parts of the document. (Example: The ThingWorx Mashupbuilder or the Theme Designer.)
- Import the theming rules and dynamically change the theming. This option allows you to create a Theme Editor. (Example: The ThingWorx Composer.)

You should pick one of these options. Select the preferred usage behavior by including the corresponding controller:

### Single Hardcoded Theme

~~~js
import 'tw-styling/styling/auto.js';
~~~

The `auto.js` file mounts the imported styling under the header element.

Note: when using `auto.js`, you should only include the styling for a single theme. If you include several themes, only one of them will be used, arbitrarily. The rest of the themes will consume RAM and download time for no gain.

### Multiple Hardcoded Themes

~~~js
import {themeNames, applyTheme} from 'tw-styling/styling/apply-styling.js';
~~~

`themeNames` is an array of the available theme names. Example:

~~~js
const themeNames = [
    'base-theme',
    'composer-theme',
    'legacy-styles-theme',
    'ptc-new-theme',
    'ptc-convergence-theme'
];
~~~

`applyTheme` is a function:

~~~js
function applyTheme(themeName, element);
~~~

The argument `themeName` specifies the theme you want to use. If _falsy_, the styling is removed.

The argument `element` specifies the element where the styling should be applied. By default the styling is assigned to _document.head_.

Note that if you want to restrict the styling to a sub-part of the document, that part must be placed inside a `ptcs-style-context` element.


### Multiple Dynamic Themes

~~~js
import {applyTheme} from 'tw-styling/styling/apply-theming.js';
~~~

`applyTheme` is a function:

~~~js
function applyTheme(themeProperties, element);
~~~

The argument `themeProperties` specifies the theme properties. By default all properties have the values of the Base Theme. The Base Theme can therefore be applied as:

~~~js
applyTheme({});
~~~

This changes the base color of the theme to a pinkish color:

~~~js
applyTheme({'global-color-core-primary': '#F094c8'});
~~~

If themeProperties is _falsy_, the styling is removed.


The styling properties of the existing themes are available as:

`import {themeProps} from 'tw-styling/styling/`_theme-name_`/theme-props.js’;`

Example:

~~~js
import {applyTheme} from 'tw-styling/styling/apply-theming.js';

// Import theme properties for ptcs-new-theme
import {themeProps} from 'tw-styling/styling/ptc-new-theme/theme-props.js';

// Use ptc-new-theme
applyTheme(themeProps);
~~~

When you use dynamic themes, you should only include style modules from the `themable` folder. Example:

~~~js
import 'tw-styling/styling/themable/ptcs-button.su.js';
~~~

Any style modules outside of `themable` will be ignored (a waste of time and space).


The argument `element` (of `applyTheme`) specifies the element where the styling should be applied. By default the styling is assigned to _document.head_. Note that if you want to restrict the styling to a sub-part of the document, that part must be placed inside a `ptcs-style-context` element.



## Technical Background (a brief overview of internal details)

Each style module is a javascript module. The following code imports the Base Theme styling needed to style buttons, and nothing else:

~~~js
import 'tw-styling/styling/base-theme/ptcs-button.su.js';
~~~

When the module is loaded it sends the styling to the current controller.

### Variants

Components can use _variants_. With the styles modules, the developer can load the styling for only the variant(s) being used. There are for instance (currently) 6 official variants for buttons. If only the _primary_ variant of the button is used, it is enough to only load the primary styling. Therefore, the button theming is (currently) distributed into these style modules:

- ptcs-button.danger.su.js
- ptcs-button.primary.su.js
- ptcs-button.secondary.su.js
- ptcs-button.small.su.js
- ptcs-button.tertiary.su.js
- ptcs-button.transparent.su.js

The styling for all variants is included when loading the styling for the _whole_ button (ptcs-button.su.js). The button style component hence looks like this:

~~~js
// ptcs-button.su.js
import './ptcs-button.danger.su.js';
import './ptcs-button.primary.su.js';
import './ptcs-button.secondary.su.js';
import './ptcs-button.small.su.js';
import './ptcs-button.tertiary.su.js';
import './ptcs-button.transparent.su.js';
~~~

Note that the Javascript module loader makes sure that a module is only included once. If the developer includes both `ptcs-button.su.js` and `ptcs-button.danger.su.js`, the danger styling will only be loaded once.

If a component doesn’t have multiple variants, the main module contains the styling directly.

### Dependencies

Most components use sub-components. For example, buttons use labels, icons, and tooltips. If the button styling is imported, the icon, label and tooltip styling must also be imported. (This only works if the meta information in the `wc-meta` folder properly registers the dependent sub-components.)

For example, the primary styling for the button needs to include:

~~~js
// ptcs-button.primary.su.js
import './ptcs-icon.su.js';
import './ptcs-label.label.su.js';
import './ptcs-tooltip-overlay.su.js';
~~~

