Skip to content
Edmund edited this page Oct 6, 2017 · 2 revisions

Themes are used to create distinctly separate UI's using a combination of modules and custom configuration.

By default themes exist in the src/themes directory. As each theme can be comprised of multiple files, it is neccessery to create a separate directory for each theme.

|-- src
|   |-- themes
|   |   |-- One-Nexus
|   |   |   |-- config.json
|   |   |   |-- One-Nexus.js
|   |   |   |-- One-Nexus.scss

Pass the js and scss files to their respective compilers and they will generate your project's UI using the configuration from the json file. If using the provided Grunt tasks, you can run grunt theme to do this.

One-Nexus.js

The theme's JavaScript file must first import the app ('src/app.js'):

import * as app from '../../app';

Next, the theme's configuration is imported:

import * as app from '../../app';
import config from './config.json';

Finally, the configuration is exposed to the entire app:

import * as app from '../../app';
import config from './config.json';

app.theme = config.app;

Modules from the app can now be included:

import * as app from '../../app';
import config from './config.json';

app.theme = config.app;

app.accordion();
app.carousel();
app.modal();
...

One-Nexus.scss

Like with the corresponding JavaScript file, the theme's Sass file must first import the app ('src/_app.scss'):

@import '../../app';

And again, the theme's configuration is imported:

@import '../../app';
@import './config.json';

Modules from the app can now be included:

@import '../../app';
@import './config.json';

@include accordions;
@include carousels;
@include modals;

config.json

This file is used to store custom configuration for any modules that are included, overwriting the default value. To use a module's default configuration entirely, you do not need to add it to this object.

The below values should be considered pseudo values and may not reflect real module options

{
    "app": {
        "accordions": {
            "title": {
                "color": "red",
                "active": {
                    "color": "#454545"
                }
            },
            "keepOpenModifier": "keepOpen"
        },
        "carousels": {
            "nav-buttons": {
                "enabled": "true"
            }
        },
        "billboard": {
            "fullscreen": {
                "enabled": true,
                "min-height": "500px"
            },
            "overlay": {
                "enabled": false
            }
        }
    }
}

How Configuration Works

Each module can have any number of configuration options. All values for a module are accessible in the module's corresponding scss and js files, even options which may seemingly only suit one of these technologies. It makes things eaiser keeping all of the module's configuration in one place, and it helps with keeping things modular.

However, it is entirely possible to use modules in a way which don't have shared configuration in the form of JSON, where the corresponding scss and js files have their own config options. Rather than having a common app JSON file (and separate JSON files for each module), config would be passed to modules when including them, like so:

One-Nexus.js
import * as app from '../../app';

app.accordion({
    keepOpenModifier: 'keepOpen'
});
app.carousel();
...
One-Nexus.scss
@import '../../app';

@include accordions((
    'title': (
        'color': red,
        'active': (
            'color': #454545
        )
    )
));
@include carousels;
...

Understanding that configuration can be passed to modules in this way opens up the explanation as to how modules will use any custom configuration that exists in config.json.

When a module is called without any options passed to it, it will search for the global app object. In Sass, this object is created by Sass-JSON-Vars when config.json is imported (@import './config.json'), and accessible by the $app variable (the variable name is determined by the first key in the JSON object, which in the case for One-Nexus is app). Having access to this variable allows it to be searched for configuration. Specifically, this is handled by the custom function:

@function custom($module) {
    @return if(variable-exists('app') and map-get($app, $module), map-get($app, $module), ())
}

So this means when calling a module, custom configuration (if it exists in config.json) can be passed to it like so:

@import '../../app';
@import './config.json'; // config now accessible globally by `$app` variable

@include accordions(custom('accordions'));

And to avoid the need for doing this with every module, custom(MODULE_NAME) is passed as a default parameter when defining modules, as seen in the Accordions example:

@mixin accordions($custom: custom('accordions')) {
    ...
}

And it works exactly the same way for the corresponding JavaScript. The configuration object is created after importing config.json:

import * as app from '../../app';
import config from './config.json';

app.theme = config.app; // `app.theme` now exposes the same information as `$app` in the Sass

Again, One-Nexus provides a custom JS function (accessed by app.custom) which can be used to search app.theme for any existing custom configuration. This means when calling a module, custom configuration (if it exists in config.json) can be passed to it like so:

import * as app from '../../app';
import config from './config.json';

app.theme = config.app;

app.accordion(app.custom('accordions'));

And again just like with the corresponding Sass, to avoid the need for doing this with every module, app.custom(MODULE_NAME) is built into the module definition.

Clone this wiki locally