Skip to content
esr360 edited this page May 17, 2019 · 13 revisions

One of the most powerful features of Synergy is the ability to create themes. Themes are used to create distinctly separate UI's using a combination of modules and custom configuration, without modifying any source code.

Single Theme/Globals Object

Even if your project doesn't have multiple "themes" per se, it's likely you may still require the ability to share common properties between your modules (for things like colors and font-sizes). Synergy still views this collection of properties as a theme. And even if you do utilise multiple themes, you may still wish to have a single foundation theme on which further themes should be based off. This is so you can have a common set of properties shared by all themes, without having to duplicate them.

This "foundation" can exist as either a JSON file, a JavaScript object or a JavaScript function that returns an object. You can still have multiple themes where each theme contains all required values and not have a sigle foundation theme. The object/function should be passed to Synergy.theme() as the globals argument if you use multiple themes, or the theme argument if you don't.

Creating a Theme

Synergy recommends keeping your themes inside a themes directory that exists alongside the modules directory.

|-- modules
|   |-- Accordion
|   |   ...
|-- themes
|   |-- myTheme.json
|   |   ...

As a theme should contain no logic and just raw values, it's recommended to use a JSON file for your theme, though you can also use standard JavaScript if you require more flexibility.

themes/myTheme.json
  • Your theme should contain a name property representing the name of your theme
{
    "name": "myTheme",
    "colors": {
        "primary": "#005DFF",
        ...
    }
    ...
}

You can also keep your theme's properties under a top-level theme key:

{
    "theme": {
        "name": "myTheme",
        "colors": {
            "primary": "#005DFF",
            ...
        }
        ...
    }
}
modules/Accordion/configuration.js

Learn more about Module Configuration

  • The Accordion configuration should have a name property, e.g. accordion, which is the name used when rendering the module (the named used to reference the module internally can be different from the name used when rendering the module to the DOM, which is the purpose of the name property in a module's configuration)
  • If a theme/globals object exists it can be supplied as an argument to the configuration function and utilised in the configuration
export default theme => ({
    'name': 'accordion',
    'color': 'blue',

    panel: {
        'color': theme.colors.primary
    }
    ...
})

Accessing Globals/Self From Within Theme

You may find yourself wanting to use properties in your theme that are defined in the theme or the globals object...

themes/myTheme.json

Learn more about including configuration for modules within themes

{
    "theme": {
        "name": "myTheme",
        "colors": {
            "primary": "#005DFF",
            ...
        },
        "modules": {
            "Accordion": {
                "color": "I want to use the `primary` color here..."
            }
        },
        ...
    }
}

...this is achievable by converting your theme into a JavaScript function and passing a theme parameter, and then converting the value to a function which returns the value:

themes/myTheme.js
export default theme => ({
    "colors": {
        "brand": {
            "primary": "#005DFF",
            ...
        }
    },
    "modules": {
        "Accordion": {
            "color": () => theme.colors.brand.primary
        }
    },
    ...

theme will also contain values merged from the globals argument passed to Synergy.theme().

Overriding Modules

You can override a module's default configuration by creating a modules object within the theme object.

  • Pass the name of your module (the name used in the module's interface) as a property of the modules object
{
    "theme": {
        "name": "myTheme",
        "colors": {
            "primary": "#005DFF",
        },
        "modules": {
            // Theme-level Accordion properties
            "Accordion": {
                "color": "red"
                ...
            }
        },
        ...
    }
}

...the values used above will override the values in the original modules/Accordion/configuration.js file.

Using a Theme

View a minimal working example of a Synergy theme

Several things need to occur for a theme to work, which can be handled automatically with the Synergy.theme() method.

  • Create a new config object for your module, merging the default and custom/theme values
    • Synergy.config() can used for deeply merging a module's default configuration with custom configuration
  • Assign the new config object to the config property of Accordion and subsequently assign Accordion to window
import Accordion from './modules/Accordion/Accordion.jsx';
import theme from './themes/myTheme.json';

const AccordionConfig = Synergy.config(Accordion.defaults(theme), theme.modules.Accordion);

window.Accordion = Object.assign(Accordion, {
    config: AccordionConfig
});

Now when you create a module using <Module> and pass Accordion to the name prop, it will retreive the configuration from window.Accordion.config.

Synergy.theme()

The above tasks can be acted upon all of your modules at once by using the Synergy.theme() method.

Synergy.theme(modules, theme, globals, trump)
  • It's recommended to export all of your modules in a single file so they can be imported all at once
import modules from './modules';
import theme from './themes/myTheme.json';

Synergy.theme(modules, theme);

Parameters

Parameter Type Description
modules Object Object containing your Synergy modules (object of exported React components)
theme (Function|Object) Your project's theme
[globals] Object [optional] A `globals` object which will be merged with `theme`
[trump] Object An object of configuration properties to take precedence over all themes (project-level configuration)
globals Parameter

Synergy.theme() accepts a third parameter to act as a globals object. The globals value will be merged with the theme object and assigned to window.ui, and subsequently made available to your modules (for example within module styles). This is useful is you want to have a base set of values where your theme only changes certain values, rather than being responsible for for every thematic/cosmetic value (in which case different themes may duplicate many properties).

This object is also useful for storing common tools/utilities and helper functions for your modules.

import modules from './modules/index.js';

const globals = {
    colors: {
        primary: 'red',
        secondary: 'blue'
    },
    sizes: {
        small: '10px',
        large: '18px'
    },
    someUtility: element => {
        ...
    }
    ...
}

const theme = {
    colors: {
        primary: 'green',
        tertiary: 'orange'
    }
}

Synergy.theme(modules, theme, globals);

Now within some module's styles.js file you can access the newly created merged object by passing a third parameter to the styles function.

Learn more about module styles

export default (element, config, theme) => ({
    'color': theme.someUtility(element) ? theme.colors.primary : theme.colors.tertiary,
    'border-color': ui.colors.secondary,
    'font-size': ui.sizes.small
})
Clone this wiki locally