Skip to content

Commit

Permalink
Refactor: change wrapping strategy for theming
Browse files Browse the repository at this point in the history
With example from Next.js:

  - vercel/next.js@58c2d13

And some API changes that happened yesterday (MUI is still in beta):

  - https://github.com/callemall/material-ui/releases/tag/v1.0.0-beta.5
  - mui/material-ui#7730
  - mui/material-ui#7740
  • Loading branch information
iquabius committed Aug 17, 2017
1 parent 653cb31 commit 0dee25f
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 0 deletions.
63 changes: 63 additions & 0 deletions frontend-new/components/withRoot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React, { Component } from 'react'
import { JssProvider } from 'react-jss'
import { withStyles, MuiThemeProvider } from 'material-ui/styles'
import { getContext } from '../styles/context'

// Apply some reset
const styles = theme => ({
'@global': {
html: {
background: theme.palette.background.default,
fontFamily: theme.typography.fontFamily,
WebkitFontSmoothing: 'antialiased', // Antialiasing.
MozOsxFontSmoothing: 'grayscale' // Antialiasing.
},
body: {
margin: 0
}
}
})

let AppWrapper = props => props.children

AppWrapper = withStyles(styles, { name: 'AppWrapper' })(AppWrapper)

function withRoot (BaseComponent) {
class WithRoot extends Component {
static getInitialProps (ctx) {
if (BaseComponent.getInitialProps) {
return BaseComponent.getInitialProps(ctx)
}

return {}
}

componentDidMount () {
// Remove the server-side injected CSS.
const jssStyles = document.querySelector('#jss-server-side')
if (jssStyles && jssStyles.parentNode) {
jssStyles.parentNode.removeChild(jssStyles)
}
}

render () {
const context = getContext()

return (
<JssProvider registry={context.sheetsRegistry} jss={context.jss}>
<MuiThemeProvider theme={context.theme} sheetsManager={context.sheetsManager}>
<AppWrapper>
<BaseComponent {...this.props} />
</AppWrapper>
</MuiThemeProvider>
</JssProvider>
)
}
}

WithRoot.displayName = `withRoot(${BaseComponent.displayName})`

return WithRoot
}

export default withRoot
47 changes: 47 additions & 0 deletions frontend-new/pages/_document.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from 'react'
import Document, { Head, Main, NextScript } from 'next/document'
import { getContext, setContext } from '../styles/context'

export default class MyDocument extends Document {
static async getInitialProps (ctx) {
// Reset the context for handling a new request.
setContext()
const page = ctx.renderPage()
// Get the context with the collected side effects.
const context = getContext()
return {
...page,
styles: <style id='jss-server-side' dangerouslySetInnerHTML={{ __html: context.sheetsRegistry.toString() }} />
}
}

render () {
const context = getContext()
return (
<html lang='en'>
<Head>
<title>My page</title>
<meta charSet='utf-8' />
{/* Use minimum-scale=1 to enable GPU rasterization */}
<meta
name='viewport'
content={
'user-scalable=0, initial-scale=1, maximum-scale=1, ' +
'minimum-scale=1, width=device-width, height=device-height'
}
/>
{/* PWA primary color */}
<meta name='theme-color' content={context.theme.palette.primary[500]} />
<link
rel='stylesheet'
href='https://fonts.googleapis.com/css?family=Roboto:300,400,500'
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</html>
)
}
}
58 changes: 58 additions & 0 deletions frontend-new/pages/dashboard/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React, {Component} from 'react'
import Button from 'material-ui/Button'
import Dialog, {
DialogTitle,
DialogContent,
DialogContentText,
DialogActions
} from 'material-ui/Dialog'
import Typography from 'material-ui/Typography'
import withRoot from '../../components/withRoot'

const styles = {
container: {
textAlign: 'center',
paddingTop: 200
}
}

class Index extends Component {
state = {
open: false
};

handleRequestClose = () => {
this.setState({
open: false
})
};

handleClick = () => {
this.setState({
open: true
})
};

render () {
return (
<div style={styles.container}>
<Dialog open={this.state.open} onRequestClose={this.handleRequestClose}>
<DialogTitle>Super Secret Password</DialogTitle>
<DialogContent>
<DialogContentText>1-2-3-4-5</DialogContentText>
</DialogContent>
<DialogActions>
<Button color='primary' onClick={this.handleRequestClose}>OK</Button>
</DialogActions>
</Dialog>
<Typography type='display1' gutterBottom>Material-UI</Typography>
<Typography type='subheading' gutterBottom>example project</Typography>
<Button raised color='accent' onClick={this.handleClick}>
Super Secret Password
</Button>
</div>
)
}
}

export default withRoot(Index)
49 changes: 49 additions & 0 deletions frontend-new/styles/context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { create } from 'jss'
import preset from 'jss-preset-default'
import { SheetsRegistry } from 'react-jss'
import createPalette from 'material-ui/styles/palette'
import createMuiTheme from 'material-ui/styles/theme'
import { purple, green } from 'material-ui/colors'
import createGenerateClassName from 'material-ui/styles/createGenerateClassName'

const theme = createMuiTheme({
palette: createPalette({
primary: purple,
accent: green
})
})

// Configure JSS
const jss = create(preset())
jss.options.createGenerateClassName = createGenerateClassName

function createContext () {
return {
jss,
theme,
// This is needed in order to deduplicate the injection of CSS in the page.
sheetsManager: new WeakMap(),
// This is needed in order to inject the critical CSS.
sheetsRegistry: new SheetsRegistry()
}
}

export function setContext () {
// Singleton hack as there is no way to pass variables from _document.js to pages yet.
global.__INIT_MATERIAL_UI__ = createContext()
}

export function getContext () {
// Make sure to create a new store for every server-side request so that data
// isn't shared between connections (which would be bad)
if (!process.browser) {
return global.__INIT_MATERIAL_UI__
}

// Reuse context on the client-side
if (!global.__INIT_MATERIAL_UI__) {
global.__INIT_MATERIAL_UI__ = createContext()
}

return global.__INIT_MATERIAL_UI__
}

0 comments on commit 0dee25f

Please sign in to comment.