Configuring and Loading Theme Style Sheets in vSphere Client Remote Plug-Ins

After you compile the output style sheets for your plug-in user interface, you write front-end code to load the style sheets that cause your plug-in to conform to the style selected in the vSphere Client.
  • Refactor the input style sheets for the plug-in so that they isolate theme-dependent colors and styles in separate style sheets as CSS variables.
  • Configure theme-dependent icons in the plug-in manifest file.
  • Build output style sheets into a base style sheet and a style sheet for each theme.
  1. Load and configure polyfill libraries to provide CSS variable support in Internet Explorer 11.
    If you use
    css-vars-ponyfill
    , consider whether to configure options to create a MutationObserver and whether to remove CSS rulesets and declarations that do not reference a CSS custom property value. For more information about configuring
    css-vars-ponyfill
    , see https://github.com/jhildenbiddle/css-vars-ponyfill/tree/v1.17.1#optionswatch and https://github.com/jhildenbiddle/css-vars-ponyfill/tree/v1.17.1#optionsonlyvars.
    The vSphere Client SDK includes a remote plug-in sample that uses
    css-vars-ponyfill
    . The following example is borrowed from the file
    html-client-sdk/samples/remote-plugin-sample/src/main/ui/src/index.html
    .
    <script type="text/javascript" src="scripts/css-vars-ponyfill.js"></script> // Initialize CSS vars to configure polyfill. cssVars({ watch: true, onlyVars: true });
    The following example is borrowed from the file
    html-client-sdk/samples/remote-plugin-sample/src/main/ui/.angular-cli.json
    .
    "assets": [ "assets", { "glob": "css-vars-ponyfill.js", "input": "../node_modules/css-vars-ponyfill/dist/", "output": "scripts/ }, … ]
  2. Load the base style sheet initially.
    The following example is borrowed from
    html-client-sdk/samples/remote-plugin-sample//src/main/ui/src/index.html
    .
    <link rel="stylesheet" type="text/css" href="styles.bundle.css">
  3. Load and initialize the vSphere Client JavaScript API.
    <script type="text/javascript" src="/api/ui/htmlClientSdk.js"></script> <script type="text/javascript"> htmlClientSdk.initialize(init_plugin_view()); </script>
    For examples in the SDK, see
    html-client-sdk/samples/remote-plugin-sample//src/main/ui/src/index.html
    and
    html-client-sdk/samples/remote-plugin-sample//src/main/ui/src/app/app.component.ts
    .
  4. Load the style sheet for the current theme initially and whenever the style changes.
    The following example is adapted from
    html-client-sdk/samples/remote-plugin-sample/src/main/ui/src/app/app.component.ts
    .
    if (this.globalService.htmlClientSdk.app.getTheme && this.globalService.htmlClientSdk.event.onThemeChanged) { this.loadTheme(true, this.globalService.htmlClientSdk.app.getTheme()); this.globalService.htmlClientSdk.event.onThemeChanged( this.loadTheme.bind(this, false)); } else { this.loadTheme(true, { name: 'light' }); } private loadTheme(firstLoad: boolean, theme: any): void { let themeName: string = theme.name; let supportedThemeNames: string[] = ['light', 'dark']; if (supportedThemeNames.indexOf(themeName) === -1) { themeName = supportedThemeNames[0]; } let styleSheetLinkElement = (<HTMLLinkElement> document.getElementById('theme-stylesheet-link')); let themeCssUrl = `theme-${themeName}.bundle.css`; if (firstLoad) { let initialThemeLoadCompleteListener = (event: Event) => { this.initialThemeLoadComplete = true; styleSheetLinkElement.removeEventListener('load', initialThemeLoadCompleteListener); styleSheetLinkElement.removeEventListener('error', initialThemeLoadCompleteListener); }; styleSheetLinkElement.addEventListener('load', initialThemeLoadCompleteListener); styleSheetLinkElement.addEventListener('error', initialThemeLoadCompleteListener); } styleSheetLinkElement.setAttribute("href", themeCssUrl); document.documentElement.setAttribute("data-theme", themeName); }