@andrew.budaiev
Thanks again for sharing your custom themes with us to help improve theme migration. The final 8.3.0 release will include these improvements. In order to get your valid themes to work, you and others may need to make some small adjustments to theme import paths. Specifically, make sure themes importing from other themes point to the actual file within that imported theme’s directory. For example, change @import “./light.css"
to @import "../light/index.css"
, just like we’ve done with our derived themes. It’s easiest to do this before the migration, but is still just as easy to do after migration. Check out the new theming readme below. Included is a section on migrating to 8.3 (last section).
A Guide to Theming in Perspective
Overview
Theming in Perspective allows designers to customize the look-and-feel (not layout) of their Perspective projects at a broad level. A projects active theme is defined in a project's session properties. Where applicable, any styles applied using Perspective Style Classes or inline styles within the Designer should still override anything inherited from a theme. It is possible to work around this rule, but that is not something we would recommend. Theming is considered an advanced feature of Perspective. As such, we operate under the assumption that anyone altering these files has some knowledge of CSS. By making use of CSS variables, imports, and descriptive class selectors, you will find that we have provided features and structure to help alleviate some of the frustrations inherent to managing large amounts of CSS.
Available Themes
As of writing this, the following themes have been made available to you, by us. They are bundled with Perspective.
light
(base theme)
light-warm
light-cool
dark
dark-warm
dark-cool
Creation and Modification
Themes can be created and modified using either Ignition's OpenAPI HTTP specification (recommended), or directly in the config file system, in the core resource collection. Any modifications done directly in the file system will require a rescan of the file system. There is a button in the Gateway Web UI's projects page (.../system/projects) that can be used to trigger a rescan.
Structure
A valid theme has the following structure:
```
- custom-theme
|- index.css // theme entry configurable in config.json
|- config.json // theme configuration file
|- resource.json // internal resources file
```
Within the config.json
are two important properties, "entrypoint" and isPrivate
. By default the entrypoint of your theme, which we use for processing, is index.css
. The "isPrivate" property let's us know if the theme should be listed as an available theme. By default, this is true
. Setting this to false
is particularly useful if your "theme" is shared between multiple themes that are listed as available themes.
Before getting started, we recommend that you familiarize yourself with the structure of one of our provided themes.
** IMPORTANT **
Both the light
and dark
themes are owned and maintained by Inductive Automation. This means that they can't be altered. However, the derived themes (light-cool
, dark-cool
, etc.) can be modified freely.
Features
CSS Variables
CSS variables have a central role in theme authoring. We recommend leveraging this built in feature of CSS to aid in modular theme development and ease frustrations of long term maintenance. We use CSS variables throughout our theme stylesheets, so whenever there may be a need to change something like a color, it only needs to be changed in a single file.
Declaring variables:
--corporateColor: #FF5D00;
Using variables:
background-color: var(--corporateColor);
Variables can also be used in the Designer's property editor as the value of a components style property. Assuming that the variable exists, of course. Simply specify the variables name as the style property value:
backgroundColor: --corporateColor
Descriptive CSS Classes
Component authors specify unique CSS class selectors that give you direct access to the styling of particular elements. Each class selector is unique enough to prevent clashing and descriptive enough to minimize any guessing surrounding its dedicated purpose. We follow a standard naming convention called ABEM (Atomic Block Element Modifier).
Convention in a nutshell:
atomicPrefix_blockName__elementName--modifierName
In use:
ia_cylindricalTankComponent__liquid--animation
Keep in mind that these unique classes give you direct access to specific elements. You can find a list of available selectors, and their defined rules, in their respective files. If you can not find the selector you need, then it is likely not defined. You may either request it or use one of the many other ways to style elements in Perspective.
CSS Imports
Imports provide the ability to develop or author themes in a modular fashion. They also make overriding easy (see section on overriding themes). There are two rules that we expect you to follow when using imports.
-
Imports should be declared at the top of each CSS file.
-
Each import statement must begin with the CSS at-rule @import
, specify the relative path to the file to import, and terminate with a semicolon. Imports that do not meet this criteria may be ignored. You may use single or double quotes surrounding the import path. For example:
```
@import "../button.css";
@import './variables.css';
```
Overriding or Adapting Themes
Overriding or adapting themes is easy by leveraging the "C" in CSS (Cascading Style Sheet). Simply add your own CSS import pointing to your own custom style sheet containing the rulesets that you want to override or adapt AFTER any existing imports. For example, to override something declared in one of our bundled themes light-cool
, add your own import in the light-cool/index.css
entry file like so:
light-cool.css
@import "./light/index.css"
@import "./custom/overrides.css"
We do not attempt to rewrite this file on startup unless it does not exist.
Creating Custom Themes
To create your own custom theme, either use Ignition's HTTP OpenAPI (recommended) or create the necessary structure on the filesystem (refer to the structure section above). Use one of the bundled themes as an example. Any derivative themes (light-cool
, dark
, dark-warm
, etc.) will serve as ideal examples for most use cases. We recommend looking at these. The derivative themes simply extend the base theme (light
), but overrides the values of some of the CSS variables that define fundamental colors.
The most important items to remember when authoring your own theme are:
- Ensure that the structure is correct and that an entry file has been defined in the theme resource's
config.json
.
- Order matters. Duplicate rules that come after existing rules will override or supplement depending on declared properties between the two.
- The
light
theme is the base theme, and all themes should extend from this. If any of the rules defined in the provided base theme (light
) are missing from your custom theme, either from not being declared or not being imported, the result of these missing properties will be reflected in your project (for example, a button missing a border). When creating your own custom themes, make sure that rulesets declared in the base theme (light
) exist in your custom theme at all times, unless of course you've accommodated for this in some other way.
- Our updated base themes
light
and dark
can be copied into the core
resources folder by submitting a POST HTTP request {gateway_url}/data/perspective/api/v1/themes/copy-base-themes
. This is to make referencing our base themes easier. The API token used in this request must have write permissions. Any modifications to these copied base themes are ignored.
Migrating to 8.3
In 8.1, theme authorship relied soley on the filesystem. In 8.3, with the new config overhaul and resource collection model, we have had to slightly change the existing theme structure to conform to this new model. The old entry point files that existed at the root of the themes folder (i.e., themes/light.css
, themes/custom-theme.css
, etc.) have been removed. They are no longer used to determine the available themes. Instead, each respective theme gets a config.json
. Within this config file is an isPrivate
property that when set to true will prevent this theme from being listed as an available theme. This is useful in instances where you may have a common or shared set of theme resources that other themes might import or extend. Also within this config is the entrypoint
property that lets us know where to start processing your theme. This is generally an index.css
file that exists within your theme folder (i.e., themes/custom/index.css
). By default it is index.css
, but you may change this if you’d like.
If you followed the structure and format we used for our bundled themes (light, dark, light-cool, dark-warm, etc.), then your themes should migrate successfully. If not, you will likely need to update some of your imports, and in some situations create a new theme. For example, if your old custom-theme.css
entry file had an import like @import “./light.css”
, you will need to add @import “../light/index.css”
to your theme's entrypoint file (custom-theme/index.css
). Like we mentioned, we have gotten rid of the old entry files. All external imports or declarations that you might have had in that old entry file, will need to be moved into the new entrypoint file for your theme. Luckily, you can find all of those original migrated files in the .migrated-themes-TIMESTAMP
directory within data/modules/com.inductiveautomation.perspective
. You can reference the old files to help resolve your imports and move to this new structure.
In circumstances where you may have had an old entry file (i.e., themes/test-theme.css
), but no peer directory of the same name (i.e., themes/test-theme
), you will find that we have created one for you as part of the migration process. Within this migrated directory will be an index.css
entrypoint. You will need to update this index.css
to include any imports you might have included in the old entry file. We did not attempt to resolve, modify, or move, any imports during the migration.