Getting Started with a Custom User Panel Theme

Tags: 337 views 0

How custom themes for the Atomia User Panel are structured and configured.

Overview

The Atomia User Panel user interface has many customization possibilties: from simple branding and translation changes to things like changing JavaScript behaviors. A collection of UI customizations is called a theme, which is simply a folder containing custom CSS and related assets, JavaScript, ASP.NET views, and translation files. This section outlines the general structure of a custom theme.

Before you begin

These things will be needed when working with a custom theme (depending on task):

  • Text editor of choice
  • Node.js
  • An installation of the Atomia User Panel for testing
  • Basic knowledge of Sass
  • Basic knowledge of Knockout.js

Theme structure

The basic folder structure of a custom theme matches very closely to what a normal ASP.NET MVC application structure looks like:

Theme folder structure

Image: Theme folder structure.

App_Data/Transformation Files

Contains setting changes to e.g. activate the custom theme. Can also contain setting changes not related to theming.

App_GlobalResources/ExampleTheme

Globally available translation overrides.

Themes/ExampleTheme/Content

Style sheets and related assets like fonts and images. See Custom Branding and UI Design.

Themes/ExampleTheme/Scripts

JavaScript. See Custom JavaScript.

Themes/ExampleTheme/Views/-SectionName-

View files and local translation overrides (in App_LocalResources) for each section of the application. See Custom Views.

Theme fallbacks and activation

The Atomia User Panel custom themes work on a model with inheritance and fallback to default features if something has not been customized. This mechanism works mainly via view resolution. See Custom Views for more on this.

When you have your own custom theme folder it is time to actually activate the theme. This is done in the App_Data/appConfig.config file. The themesList section controls which themes are available, what their inheritance is like, and which one is active by default.

  • Any theme that is added to the list is available to be activated.
  • The theme where the isActive attribute is true is the theme that is active by default when the Atomia User Panel is accessed by a user.
<?xml version="1.0" encoding="utf-8"?>
<appConfig xmlns="Atomia.Web.Base.Configs" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
 <themesList>
   <theme isActive="false" xdt:Transform="SetAttributes(isActive)" /> <!-- disables all themes -->
    <theme isActive="true" name="Custom" parentTheme="NewDefault" xdt:Transform="Insert" /> <!-- activates our Custom theme -->
  </themesList>
</appConfig>
  • The parentTheme attribute decides what theme serves as fallback for the custom theme. It should be set to NewDefault unless there is a very specific reason not to do that.

In addition to setting the isActive attribute to decide which theme is active by default it is possible to dynamically activate any of the available themes in the themesList by appending ?theme=ThemeName to the URL when accessing a page in the Atomia User Panel.

Important!

There are currently two fallback themes from Atomia that get installed with the Atomia User Panel: NewDefault and Default. NewDefault is the current, actively developed theme. Any new custom theme should be based on this. Default is a legacy theme that is provided for backward compatibility with older custom themes. It will in the not too distant future stop receiving updates and not be installed with the Atomia User Panel.

Useful tip

If you are having some issues in the UI with a custom theme active it can be useful to see if the problem persists or disappears when the NewDefault theme is active. The easisest way to do this is to switch to the NewDefault theme via the ?theme=NewDefault query string. For quick switching to NewDefault (or with modification any other theme) you can save this snippet as a browser bookmarklet:

javascript:void((function(){var loc = location.href.replace("?theme=Default", "").replace("?theme=NewDefault", "");location.href = loc+"?theme=NewDefault";})());

Was this helpful?