Custom Themes

In map.apps 4, a new way of layout-theme compilation is introduced. It provides a modern live compiling which makes it unnecessary to process resources manually each time a file is changed. In addition, the app’s theme configuration is simplified. Therefore some slight changes are necessary to get a map.apps 3.x theme running in a map.apps 4.x build. The following guide explains the steps needed in detail. This guide has a technical scope and does not cover the design perspective.

In general there are three use-cases for customizing map.apps themes:

  • theme-bundle - customizing colors and adding styles for custom bundles

  • theme-extension - custom theme that ships the styles for custom bundles only matching to another theme from another bundle

  • multi-theme-extension - custom theme bundle that ships multiple themes for custom bundles matching to multiple other themes - not supported yet

Prerequisites

To complete this guide, you only need your map.apps 3.x project with one or more custom themes (based on map.apps remote sample project) and the latest mapapps-4-developers project .

Step 1: Copy theme from remote project to mapapps-4-developers

Locate the main folder of map.apps remote sample project (the folder where the pom.xml is located) which is called [RemoteProjectMain] and the main folder of the mapapps-4-developers which is called [mapapps-4-developers] on your hard drive.

Typically, the structure of a bundle providing one or more themes in map.apps 3.x looks like the following:

theme3

It is best practice to split up each theme (myTheme-A and myTheme-B in the preceding sample) in a separate bundle. To do so, create a new folder called theme-a/styles under [mapapps-4-developers]/src/main/js/bundles. Copy the contents of [RemoteProjectMain]/src/main/js/bundles/sample_themes/mytheme-A to the theme-a/styles folder you have created.

Remove the file theme-a/sytles/mytheme-a.less. With map.apps 4 this file is generated automatically after Step 5. It is called styles.less now. This file represents the main entry point for CSS. When removing, check the file carefully for any customizations.

Next, replace the content of [mapapps-4-developers]/src/main/js/bundles/theme-a/manifest.json with the following content:

manifest.json
{
    "name": "theme-a",
    "version": "0.0.1",
    "main": "",
    "layer": "",
    "i18n": [],
    "startLevel": 1,
    "bundle": true,
    "dependencies": {
        "font-mapapps": "^4.7.1"
    },
    "cssThemes": [{
        "name": "a",
        "files": ["font-mapapps:/fonts/fonts.css", "styles/styles.css"]
    }]
}

The dependency font-mapapps is needed to ensure that all fonts, especially the one providing mapapps Iconfont, are loaded, because they are provided in a separate bundle in map.apps 4. By looking at the manifest you can notice that a theme is no longer different from other functional map.apps bundles. The 'cssThemes' block states that there is a theme provided, called a which loads all files listed inside the files array. It is crucial that this name matches the variable @themeName inside the themeSettings.less file.

Inside [mapapps-4-developers]src\main\js\bundles\theme-a\styles\themeSettings.less replace the line

themeSettings.less
@import "../common/crossBrowserSettings.less";

with

themeSettings.less
@import "../../theme-common/styles/crossBrowserSettings.less";

The map.apps 4 theme should now look similar to the following image:

theme4

Step 2: Adjust Gulpfile

In contrast to map.apps 3.x, in map.apps 4.x the whole theme compile configuration is done in [mapapps-4-developers]/gulpfile.js which is simpler than editing the pom.xml. The theme has to be added inside the themes and themeChangeTargets array:

gulpfile.js
...

mapapps.registerTasks({
    /* A detailed description of available setting is available at https://www.npmjs.com/package/ct-mapapps-gulp-js */
    /* a list of themes inside this project */
    themes: ['theme-a'],
    /* state that the custom theme is depending on map.apps everlasting theme that provides the base styles */
    hasBaseThemes: true,
    /* state that vuetify components are supported and therefore vuetify core styles are needed */
    hasVuetify: true,
    themeChangeTargets: {
        "vuetify": [
            "theme-a"
        ]
    }
});

...

Step 3: Add missing less variables

themeSettings.less
/*
* map.apps 4 - new Props
*
*/
@ct-header-logo-background-color: @dialog-titlebar-background-color;
@ct-base-font-size: 15px;

@ct-button-border-width: 2px;
@button-focused-border-color: (#fff - @container-background-color);

//shadow levels.
Higher levels simulate that the object is raised:
.shadow-0(){box-shadow: none;}
.shadow-1(){box-shadow: rgba(0, 0, 0, .12) 0 1px 6px, rgba(0, 0, 0, .12) 0 1px 4px;}
.shadow-2(){box-shadow: rgba(0, 0, 0, .16) 0 3px 10px, rgba(0, 0, 0, .22) 0 3px 10px;}
.shadow-3(){box-shadow: rgba(0, 0, 0, .19) 0 10px 30px, rgba(0, 0, 0, .22) 0 6px 10px;}
.shadow-4(){box-shadow: rgba(0, 0, 0, .25) 0 14px 45px, rgba(0, 0, 0, .22) 0 10px 18px;}
.shadow-5(){box-shadow: rgba(0, 0, 0, .3) 0 19px 60px, rgba(0, 0, 0, .22) 0 15px 20px;}

Step 4: App Configuration

Make sure that there is no extra configuration of the bundle called themes inside the app configuration file app.json. Add the bundle providing your theme (theme-a in this case) to the app and remove the themes' bundle configuration if necessary

Step 5: Start the development server

Start the development server as usual by clicking TerminalRun TaskRun in VS Code.
If all steps before were done correctly, the app should now run and use the theme. If not, see the next section.

Possible errors while or after starting the development server

Errors can appear during startup of the development server (Step 5) or while accessing the app using your theme.

During development server startup

The console log says something similar to:
[INFO] [17:25:34] Error in plugin "gulp-less"
[INFO] Message:
[INFO]     variable @container-background-color is undefined in file C:\themeMigration\mapapps-4-developers\target\webapp\js\bundles\theme-a\styles\themeSettings.less line no. 12
[INFO] Details:
[INFO]     type: Name
[INFO]     filename: C:\themeMigration\mapapps-4-developers\target\webapp\js\bundles\theme-a\styles\themeSettings.less

The third row gives already a good hint that a less variable is missing from step 3

The console log says something similar to:
[INFO] [17:29:24] Error: ENOENT: no such file or directory, open 'C:\themeMigration\mapapps-4-developers\target\webapp\js\bundles\theme-a\styles\themeSettings.less'

This is in most cases a erroneous configuration inside gulpfile.js. Make sure that the values added to themes array and themeChangeTargets correspond to your theme’s main folder name.

During app launch or while viewing the app in a browser

The app launches but the browser’s console states an 404 error similar to the following:

404

Chances are good that there is an error in the theme bundle’s manifest.json file. Ensure that the theme’s main CSS file style.css is listed inside the files array:

manifest.json
"cssThemes": [{
    "name": "a",
    "files": ["font-mapapps:/fonts/fonts.css", "styles/styles.css"]
}]
The app launches without errors but theme is not applied to app

In most cases this happens due to a mismatch between the theme bundle’s manifest.json file and the property @themeName. Ensure @themeName matches the name defined inside the cssThemes array of manifest.json file.

Step 5 (optional): Import styles for custom developed bundles

If you have created LESS/CSS files for custom bundles in the past, these files need to be imported, too. By default only map.apps default bundles and styles are loaded with the theme.

From [mapapps-4-developers]/target/webapp/js/bundles/theme-custom/styles/ copy the file styles.less to your theme at [mapapps-4-developers]/src/webapp/js/bundles/theme-custom/styles/. Now add the CSS @import statements for custom bundles/styles. Ideally they are imported right after the map.apps bundles.

Step 6 (advanced): Renaming of CSS classes

In map.apps 4 most of the CSS classnames are named after BEM Methodology . If you have defined a lot of overwrites directly by adding new CSS rules to map.apps classes, check the following table and adjust the custom rules accordingly.

old classname new classname

General

.header

.ct-application-header

.logo

.ct-application-header__logo

.appTitle

.ct-application-header__app-title

.footer

.ct-application-footer

.footer_left

.ct-application-footer__container-left

.footer_right

.ct-application-footer__container-right

OmniSearch

.ctOmniSearchUI

.ct-omnisearch

.ctOmniSearchInput

.ct-omnisearch__input-field

.ctOmniSearchLoading

.ct-omnisearch__loading

.ctOmniSearchReset

.ct-omnisearch__reset

.ctOmniSearchSettings

.ct-omnisearch__settings-button

.ctSettingsVisible

.ct-omnisearch__settings-button—​settings-visible

.ctOmniSearchSettingsPopup

.ct-omnisearch__settingsPopup

.ctOmniSearchSettings

.ct-omnisearch__settings

.ctOmniSearchDropDown

.ct-omnisearch__result-list

DataView

.ctDataViewToolBar

.ct-data-view__toolbar

.toolbar

.ct-data-view__tools

.ctPager

.ct-data-view__pager

.ctScopedFilter

.ct-data-view__filter

.ctDataViewViewPane

.ct-data-view__view-pane

Notifier

.ctNotifier

.ct-notifier

.ctNotifierStickyContent

.ct-notifier—​sticky

.ctNotifierMessage

.ct-notifier__content

.ctNotifier .Warning .ctNotifierIcon:before

ct-notifier__icon—​warning

Banner

.ctBanner

.ct-banner

.ctBanner a

.ct-banner__link

.ctBanner span

.ct-banner__text

.ctBanner img

.ct-banner__image

Map

.ctMapLoadingInfo

.map__loading-info

.ctMapLoadingInfo.ctLoading

.map__loading-info—​is-loading