Blog: Introducing UI Theme Detection for Lightning Experience

Apr 13, 2016

by William Yeh and John Belo, Salesforce Partner Program

With Winter ‘16, Salesforce introduced Lightning Experience. To provide a more streamlined user experience, you can now use Lightning Components and the Lightning Design System, as well as Visualforce. Using these tools you can create components that are reusable across applications and devices. These new options created an opportunity for customers and partners alike to revisit their applications to use this exciting new technology.

Back in December, our ISV Technical Enablement team launched a series of webinars around transitioning applications to Lightning. If you’re interested in developing Lightning Ready applications, watch the webinar recordings here.

However, with the initial launch of Lightning Experience developers had no way to build pages and components that dynamically react to the UI theme that the user is currently using.

Great news! With the Spring ‘16 release, Salesforce provides an easy and robust way for developers to detect the user’s UI theme.

UI Theme Detection in Spring '16

UI Theme Detection can be done in one of two ways:
  • Accessing global variables:
    • $User.UITheme – Returns the theme that is supposed to be used.
    • $User.UIThemeDisplayed – Returns the theme that is actually being used.
  • Calling Apex utility methods:
    • UserInfo.UITheme() – Returns the theme that is supposed to be used
    • UserInfo.UIThemeDisplayed() – Returns the theme that is actually being used

Why does Salesforce provide both the UITheme and UIThemeDisplayed methods? If users with Lightning Experience permissions are using an unsupported browser, they may experience Salesforce rendered in Salesforce Classic. If this happens, UITheme and UIThemeDisplayed return different values.

The string value stored in these variables or returned by these methods is one of the following:

  • Theme1—Obsolete Salesforce theme
  • Theme2—Salesforce Classic 2005 user interface theme
  • Theme3—Salesforce Classic 2010 user interface theme
  • Theme4d—Modern “Lightning Experience” Salesforce theme
  • Theme4t—Salesforce1 mobile Salesforce theme
  • PortalDefault—Salesforce Customer Portal theme
  • Webstore—Salesforce AppExchange theme
Detecting UI Theme Using Global Variables

Visualforce pages can use global variables to determine the UI theme in use without resorting to Apex. Look at the following Visualforce page.
<apex:page>
<apex:stylesheet value="{!URLFOR($Resource.slds, 'assets/styles/salesforce-lightning-design-system-vf.css')}" />
    <apex:outputPanel rendered="{!$User.UIThemeDisplayed == 'Theme3'}">
        <apex:pageBlock title="Visualforce (Using standard Visualforce Components)" mode="detail">
            <apex:outputLabel value="UI Theme Detection using Global Variables: {!$User.UIThemeDisplayed}"/>
        </apex:pageBlock>
    </apex:outputPanel>
    <apex:outputPanel rendered="{!$User.UIThemeDisplayed == 'Theme4d'}">
       <div class="slds">
    <div class="slds-card slds-card--empty">
  <div class="slds-card__header slds-grid grid--flex-spread">
    <h2 class="slds-text-heading--small slds-truncate">Visualforce (Using HTML + SLDS)</h2>
  </div>
  <div class="slds-card__body slds-p-horizontal--small">
    <h3 class="slds-text-heading--small slds-p-top--large slds-p-bottom--large">UI Theme Detection using Global Variables: {!$User.UIThemeDisplayed}</h3>
  </div>
</div>
    </div>
    </apex:outputPanel>
</apex:page>

Using the global variable $User.UIThemeDisplayed, it detects which UI theme is being used. Based on the theme detected it dynamically renders a page that is adapted to either Salesforce Classic 2010 (using Visualforce Components) or Lightning Experience (using HTML + Lightning Design System). We could add other conditions (or a default condition) to capture additional scenarios.

Visualforce page rendered in Salesforce Classic:

User-added image

Visualforce page rendered in Lightning Experience:

User-added image

Detecting UI Theme Using Apex Utility Methods

You can’t determine the user’s UI theme directly within a Lightning Component because it only has access to a limited set of global values. You must implement an Apex server-side controller to provide this information.

We provide three pieces of sample code that demonstrate how you get the UI theme information you need into a component responsible for rendering UI. The basic flow is:

  1. Component invokes client-side controller.
  2. Client-side controller invokes Apex server-side controller.
  3. Apex server-side controller determines theme information.
  4. Apex server-side controller returns theme information to client-side controller.
  5. Client-side controller sets values for component.
  6. Client-side controller returns control to component.
  7. Component uses theme information to render correct output.
Client-side Controller
({
    doInit : function(component, event) {
        var action = component.get("c.getUIThemeDescription");
        action.setCallback(this, function(a) {
            component.set("v.Name", a.getReturnValue());
            if(a.getReturnValue()=='Salesforce Classic'){
                component.set("v.Desc", "Lightning Components can be rendered in Salesforce Classic using Lightning Components for Visualforce");
component.set("v.isLEX",false);
            }else if(a.getReturnValue()=='Lightning Experience'){
                component.set("v.Desc", "Lightning Components can be rendered natively within Lightning Experience or, alternatively, within a Visualforce Page or within a Lightning Application.");
component.set("v.isLEX",true);
            }else if(a.getReturnValue()=='Salesforce1 Mobile'){
                component.set("v.Desc", "Salesforce1 Mobile natively supports Lightning Components");
component.set("v.isLEX",false);
            }
        });
        $A.enqueueAction(action);
    }
})

Server-side Apex Controller
public with sharing class UIThemeController {
    @AuraEnabled
    public static String getUIThemeDescription() {
        String themedesc;
        String theme = UserInfo.getUiThemeDisplayed();
        if(theme=='Theme3' || theme=='Theme2'){
            themedesc='Salesforce Classic';
        }else if(theme=='Theme4d'){
            themedesc='Lightning Experience';
        }else if(theme=='Theme4t'){
            themedesc='Salesforce1 Mobile';
        }
        return themedesc;
    }
}

Lightning Component
<aura:component implements="flexipage:availableForAllPageTypes" controller="UIThemeController" access="global">
<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
<aura:attribute name="Name" type="String" />
<aura:attribute name="isLEX" type="Boolean" />
<aura:attribute name="Desc" type="String" />
    <div class="slds">
    <div class="slds-card slds-card--empty">
  <div class="slds-card__header slds-grid grid--flex-spread">
    <h2 class="slds-text-heading--small slds-truncate">Lightning Component</h2>
  </div>
  <div class="slds-card__body slds-p-horizontal--small">
    <h3 class="slds-text-heading--small slds-p-top--large slds-p-bottom--large">Detected Theme: {!v.Name}</h3>
    <h2 class="slds-text-heading--small slds-p-top--large slds-p-bottom--large">{!v.Desc}</h2>
<aura:if isTrue="{!v.isLEX}">
<p>This text is only displayed in Lightning Experience</p>
<aura:set attribute="else">
     <p>This text is only displayed outside of Lightning Experience</p>
    </aura:set>
</aura:if>
  </div>
</div>
    </div>
</aura:component>

If you want to try out the code yourself in Salesforce Classic, see Lightning Components for Visualforce.

Lightning Component Rendered in Salesforce Classic:

User-added image

Lightning Component Rendered in Lightning Experience:

User-added image

Recommendations and Best Practices


Use the following recommendations and best practices for using UI Theme Detection in both Lightning Components and Visualforce.

Lightning Components

We recommend that you use Lightning Components as much as possible as you build out new UI. You can use Lightning Components within Salesforce Classic by using the steps outlined here. You can also use Lightning Components natively in Salesforce1 Mobile and Lightning Experience.

Here are some use cases for UI Theme detection in Lightning Components:

  • Display a simplified user interface in Salesforce1 Mobile, while using additional available screen real estate in the Desktop
  • Use SLDS within Lightning Experience and use a custom CSS within Salesforce Classic
  • Load different sets of child components for Salesforce Classic and Lightning Experience

Imagine you have a progress bar designed for Lightning Experience and another progress bar designed for Salesforce Classic. Putting your UI Theme detection at the facet level allows the facet to determine which of these lower-level components to invoke.

Visualforce

With the updated UI Theme Detection in Spring ‘16, you can now build Visualforce pages that dynamically adapt to Salesforce Classic, Lightning Experience, or Salesforce1 Mobile. 

So why use UI Theme Detection for Visualforce pages now? The main advantage is that UI Theme Detection provides additional options:

  • You can build pages that fully use the Lightning Design System and the various design tokens we are continuously pushing to SLDS
  • You can use an extended version of the Lightning Design System that better reflects your brand
  • You can use your own custom design system

If you plan to use the SLDS, we recommend keeping all the same html element IDs. Once the Lightning Design System is available on platform, your UI can access those tags automatically with the latest SLDS.

If you are investing in UI Theme detection using Visualforce, consider taking this opportunity to componentise your page using Lightning Components. Using Lightning Components now will ease the transition into this new technology as your application matures.

Summary

We continue to invest in making Lightning Experience and Salesforce1 Mobile the best they can be. With these changes to UITheme and UITThemeDisplayed, you can make your applications more dynamic and responsive to the various UI themes we are providing to customers. We look forward to seeing many more applications that use these exciting technologies!