Commit 2eaa49d5 authored by Lyza Danger Gardner's avatar Lyza Danger Gardner

Add (p)react-compatible theming utility

parent 2dd67de6
'use strict';
const { applyTheme } = require('../theme');
describe('sidebar/util/theme/applyTheme', () => {
let fakeSettings;
beforeEach(() => {
fakeSettings = {
branding: {
accentColor: '#f00', // color
appBackgroundColor: '#0f0', // backgroundColor
ctaBackgroundColor: '#00f', // backgroundColor
ctaTextColor: '#00f', // color
selectionFontFamily: 'Times New Roman', // fontFamily
annotationFontFamily: 'Helvetica', // fontFamily
},
};
});
it('populates the style object with values for defined, supported theme props', () => {
const style = applyTheme(
['accentColor', 'appBackgroundColor', 'selectionFontFamily'],
fakeSettings
);
assert.include(style, {
color: '#f00',
backgroundColor: '#0f0',
fontFamily: 'Times New Roman',
});
});
it('overwrites a prop value with one later in the passed properties if conflicting', () => {
const style = applyTheme(['ctaTextColor', 'accentColor'], fakeSettings);
assert.include(style, {
color: '#f00',
});
});
it('does not add style rules for properties not in whitelist', () => {
fakeSettings.branding.foobar = 'left';
const style = applyTheme(['foobar', 'selectionFontFamily'], fakeSettings);
assert.hasAllKeys(style, ['fontFamily']);
});
it('does not add style rules for values not defined in settings', () => {
fakeSettings.branding = {
appBackgroundColor: '#0f0',
};
const style = applyTheme(
['appBackgroundColor', 'ctaTextColor'],
fakeSettings
);
assert.hasAllKeys(style, ['backgroundColor']);
assert.doesNotHaveAnyKeys(style, ['color']);
});
it('does not add any style rules if no branding settings', () => {
fakeSettings = {};
const style = applyTheme(
['appBackgroundColor', 'ctaTextColor'],
fakeSettings
);
assert.isEmpty(style);
});
});
'use strict';
/**
* @const {Object} All supported options for theming and their corresponding
* CSS property names (JS-style)
*/
const supportedThemeProperties = {
accentColor: 'color',
appBackgroundColor: 'backgroundColor',
ctaBackgroundColor: 'backgroundColor',
ctaTextColor: 'color',
selectionFontFamily: 'fontFamily',
annotationFontFamily: 'fontFamily',
};
/**
* Return a React `style` object suitable for use as the value of the `style`
* attr in a React element, with styling rules for the requested set of
* `themeProperties`.
*
* `supportedThemeProperties` defines a whitelist of properties that may be
* set by a partner's configuration for theme customization. For a given theme
* property's styling to be present in the returned style object, all of the
* following must be true:
*
* - The theme property is present in the `supportedThemeProperties` whitelist
* - `settings.branding` (derived from client configuration) has an entry
* for this theme property
*
* See https://reactjs.org/docs/dom-elements.html#style
*
* @param {String[]} themeProperties Which of the supported theme properties
* should have applied rules in the `style`
* object
* @param {Object} settings A settings object, in which any `branding`
* property values are set
* @return {Object} An React-style style object
*
* @example
* let themeProperties = ['accentColor', 'ctaTextColor', 'foo'];
* let settings = { branding: {
* accentColor: '#ffc',
* selectionFontFamily: 'Times New Roman'
* }
* };
* // Only two of the `themeProperties` are whitelisted and
* // only one of those has a value in the `settings` object, so:
* applyTheme(themeProperties, settings); // -> { color: '#ffc '}
*/
function applyTheme(themeProperties, settings) {
const style = {};
if (!settings.branding) {
return style;
}
themeProperties.forEach(themeProp => {
const propertyName = supportedThemeProperties[themeProp];
const propertyValue = settings.branding[themeProp];
if (propertyName && propertyValue) {
style[propertyName] = propertyValue;
}
});
return style;
}
module.exports = {
applyTheme,
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment