Created
April 26, 2017 14:34
-
-
Save mbixby/5757d62192f0bb7a8de446ae06c91258 to your computer and use it in GitHub Desktop.
Extending Material UI styles
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { merge } from 'lodash' | |
// This module allows us to completely customize all of Material UI's JSS stylesheets | |
// to define our own theme. | |
// | |
// Note that you Material UI's JSS is often tied to application logic and you may | |
// deviate from the official Material UI spec. | |
// | |
// Unlike using the `overrides` feature of jss-theme-reactor, here you have access to | |
// the original calculated styles and theme. Notably you can do deep merge (lodash.merge) | |
// with the original styles. | |
export default { | |
MuiText: (styles, theme) => merge(styles, { | |
subheading: { | |
textTransform: 'uppercase', | |
fontSize: 14, | |
fontWeight: theme.typography.fontWeightMedium, | |
letterSpacing: '0.05em', | |
marginBottom: '1em', | |
marginTop: '1em' | |
} | |
}), | |
MuiList: styles => merge(styles, { | |
root: { | |
WebkitOverflowScrolling: 'touch', | |
} | |
}), | |
MuiFormLabel: (styles, theme) => merge(styles, { | |
error: { | |
color: theme.palette.text.primary | |
}, | |
focused: { | |
color: theme.palette.text.primary | |
} | |
}), | |
// ... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import MuiThemeProvider, { MUI_SHEET_ORDER } from 'material-ui/styles/MuiThemeProvider' | |
import jssGlobal from 'jss-global' | |
import { createStyleSheet } from 'jss-theme-reactor' | |
import { find, get, includes, forEach } from 'lodash' | |
import { createTheme } from './theme' | |
import materialUIStyles from './materialUIStyles' | |
// By default, jss-theme-reactor will compute Material UI stylesheet class names | |
// in format '[stylesheetName]-[className]-[hash]' (e.g. '.MuiButton-root-ca32cd'). | |
// Because stylesheets registered with the jss-theme-reactor have unique names, | |
// we can drop the hash. This way we can easily override any CSS rules with JSS. | |
// | |
// Use at your own risk. | |
// | |
// Example: | |
// ``` | |
// const jssStyles = { | |
// root: { | |
// // This will override styles of all material-ui's <Text /> components | |
// // under `.root` | |
// '& .MuiText-text': { | |
// color: 'white' | |
// } | |
// | |
// // Without this extension we would have to write something like the following: | |
// '& .MuiText-text-2eff32': { | |
// color: 'white' | |
// } | |
// } | |
// } | |
// ``` | |
const muiStylesheetNames = [...MUI_SHEET_ORDER, 'MuiFormControl', 'MuiInput', 'MuiInputLabel'] | |
export const overrideJssClassNameGeneration = (styleManager) => { | |
const origGenerateClassName = styleManager.jss.options.generateClassName | |
/* eslint-disable no-param-reassign */ | |
styleManager.jss.options.generateClassName = function generateClassName(...args) { | |
const rule = args[1] | |
const sheetName = get(rule, 'options.sheet.options.name') | |
const hashedStr = origGenerateClassName(...args) | |
if (includes(muiStylesheetNames, sheetName) && rule.name) { | |
return `${sheetName}-${rule.name}` | |
} | |
else { | |
return hashedStr | |
} | |
} | |
/* eslint-enable */ | |
} | |
const { styleManager, theme } = MuiThemeProvider.createDefaultContext({ | |
theme: createTheme() | |
}) | |
overrideJssClassNameGeneration(styleManager) | |
styleManager.jss.use(jssGlobal()) | |
// Rendering a stylesheet here ensures that all of MUI's styleManager's stylesheets | |
// will be rendered *before* any other custom app JSS styles. This way any styles defined | |
// per component will take precedence over any MUI styles | |
styleManager.render(createStyleSheet('_Prioritized_', () => ({}))) | |
const extendingStyleSheets = [] | |
// TODO Clean up | |
// @param {String} name | |
// @param {(rules, theme) -> rules} callback | |
export const extendStylesheet = (name, callback) => | |
extendingStyleSheets.push({ name, createRules: callback }) | |
// TODO Clean up | |
forEach(materialUIStyles, (callback, name) => | |
extendStylesheet(name, callback) | |
) | |
// Override styleManager.render to implement `extendStylesheet` | |
const origRender = styleManager.render | |
styleManager.render = (styleSheet) => { | |
const { name, createRules, options } = styleSheet | |
const extendingStyleSheet = find(extendingStyleSheets, { name }) | |
if (extendingStyleSheet) { | |
const createExtendedRules = () => { | |
const rules = createRules(theme) | |
return extendingStyleSheet.createRules(rules, theme) | |
} | |
return origRender({ name, createRules: createExtendedRules, options }) | |
} | |
else { | |
return origRender(styleSheet) | |
} | |
} | |
export { MuiThemeProvider, styleManager, theme } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment