-
Notifications
You must be signed in to change notification settings - Fork 10
Themes
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.
A theme is a JavaScript/JSON object that should contain things like:
- Reusable colors
- Reusable font-sizes, font-styles etc.
- Style patterns (vertical-rhythm, positioning etc.)
Themes can exist either as JSON or JavaScript files. If your theme exists as a JavaScript file, it must export an object.
Synergy recommends keeping your themes inside a themes
directory that exists alongside the modules
directory.
|-- modules
| | ...
|-- themes
| |-- myTheme.js
| | ...
A Core Theme is a base theme on which subsequent themes are built. Subsequently, a theme utilising a Core Theme may resemble:
import deepextend from 'deep-extend';
import core from './core';
export default deepextend(core, {
...
});
deep-extend
is a dependency of Synergy so can be freely imported
As you can see, there is no special functionality around using a Core Theme; it is merely merged with a new theme that wishes to use it.
Core Themes are useful when your different themes would other duplicate several/many values. A Core Theme can also serve as a default theme if no other themes can be found/are used.
Sometimes you may wish to access values of the theme from witin the theme itself. This is possible by passing the value as a function with a theme
parameter (which can be destructrued as in the below example):
export default {
spacing: '1em',
colors: {
primary: '#1E90FF',
secondary: '#00FFB2',
tertiary: '#01BFFF'
},
typography: {
primaryFont: 'sans-serif',
textColor: '#444444'
},
tokens: {
background: ({ colors }) => colors.primary,
margin: theme => theme.gutter
},
modules: {
Accordion: {
title: {
background: ({ colors }) => colors.tertiary
}
}
}
}
All values will be evaluated by the time you use them in your Modules
A theme can be provided to your Modules using either the <Provider>
or <Container>
Components, by passing the theme to the theme
prop:
import React from 'react';
import { Provider } from '@onenexus/synergy';
import theme from './themes/myTheme.js';
import MyModule from './modules/MyModule';
const App = () => (
<Provider theme={theme}>
<MyModule />
</Provider>
);
If a theme already exists, the theme you pass here will be merged with the existing theme
import React from 'react';
import { Module } from '@onenexus/synergy';
import theme from '../../themes/myTheme';
import config from './config';
import layout from './layout';
export default (props) => (
<Module name='MyModule' theme={theme} styles={styles} config={config} {...props}>
{props.children}
</Module>
);
Note that you can also expose some other useful objects to the Module's styles
export default ({ theme }) => ({
...
});
Accessing In Module Config (Learn More)
export default (theme) => ({
...
});
Using useTheme
Hook
This requires the theme to have been provided by either the
<Provider>
or<Container>
Component
import React from 'react';
import { Module, useTheme } from '@onenexus/synergy';
import config from './config';
import layout from './layout';
export default (props) => {
const theme = useTheme();
// do something with `theme`
return (
<Module name='MyModule' styles={styles} config={config} {...props}>
{props.children}
</Module>
);
}
Using Render Function
Note that using a render function with
<Module>
also exposes some other useful objects
import React from 'react';
import { Module } from '@onenexus/synergy';
import config from './config';
import layout from './layout';
export default (props) => (
<Module name='MyModule' styles={styles} config={config} {...props}>
{({ theme }) => {
// do something with `theme`
return props.children;
}}
</Module>
);
You can override a module's default configuration by creating a modules
object within the theme
object.
You must pass a name prop when using
<Module>
to utilise this feature
const theme = {
colors: {
primary: 'red',
secondary: 'blue'
}
modules: {
MyModule: {
// You can access the theme's properties by using a function
// with a `theme` parameter, they will be evaluated before being
// exposed to your styles (so no need to manually evaluate)
someProp: (theme) => theme.colors.secondary,
MyComponent: {
fontFamily: 'Comic Sans MS'
}
}
}
}
export default {
someProp: 'purple'
}
export default ({ config }) => ({
color: config.someProp // will be 'blue' (theme.colors.secondary)
});
import React from 'react';
import { Module, Component } from '@onenexus/synergy';
import theme from '../../themes/myTheme';
import config from './config';
import styles from './styles';
const MyModule = () => (
<Module name='MyModule' styles={styles} config={config} theme={theme}>
<Component name='MyComponent'>
This Component will be 'Comic Sans MS'
</Component>
...
</Module>
);
Combined with the dynamic cosmetic properties feature, this allows you to create distinctly different versions of the same Module without changing the source code.