Skip to content

Commit

Permalink
MUI setup with react-jss
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Alexeev committed Aug 1, 2017
1 parent d19d998 commit 738a654
Show file tree
Hide file tree
Showing 9 changed files with 501 additions and 26 deletions.
22 changes: 15 additions & 7 deletions components/City.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
import { createFragmentContainer, graphql } from 'react-relay';
import Typography from 'material-ui/Typography';
import List, { ListItem, ListItemIcon, ListItemText } from 'material-ui/List';

const styles = {
subItem: {
marginLeft: '10px'
}
};

const City = ({ data }) => {
if (!data) return null;
return (
<ul>
<li>
<List>
<ListItem>
City: {data.name}
</li>
<li>
</ListItem>
<ListItem>
Slug: {data.slug}
</li>
</ul>
</ListItem>
</List>
);
};

Expand All @@ -21,5 +29,5 @@ export default createFragmentContainer(
name
slug
}
`,
`
);
26 changes: 21 additions & 5 deletions components/Location.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
import { createFragmentContainer, graphql } from 'react-relay';
import Card, { CardActions, CardContent } from 'material-ui/Card';
import Typography from 'material-ui/Typography';
import Button from 'material-ui/Button';
import City from './City';

const Location = ({ data }) => {
return (
<li key={data.locationId}>
{data.name}
<City data={data.city} />
</li>
<Card key={data.locationId}>
<CardContent>
<Typography type="headline" component="h2">
{data.name}
</Typography>

<Typography component="div">
<City data={data.city} />
</Typography>
</CardContent>
<CardActions>
<div style={{ flex: '1 1 auto' }} />
<Button color="primary" dense>
Learn More
</Button>
</CardActions>
</Card>
);
};

Expand All @@ -20,5 +36,5 @@ export default createFragmentContainer(
...City
}
}
`,
`
);
48 changes: 40 additions & 8 deletions components/LocationsList.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,47 @@
import { createFragmentContainer, graphql } from 'react-relay';
import Typography from 'material-ui/Typography';
import List from 'material-ui/List';
import Paper from 'material-ui/Paper';
import Divider from 'material-ui/Divider';
import InboxIcon from 'material-ui-icons/Inbox';
import DraftsIcon from 'material-ui-icons/Drafts';
import Button from 'material-ui/Button';
import Location from './Location';

const styles = {
header: {
textAlign: 'center',
padding: '10px 0 5px 0'
},
container: {
margin: '100px auto 0 auto',
maxWidth: 400
},
list: {
width: '100%'
}
};

const LocationsList = ({ data }) => {
return (
<div>
Loaded: {data.allLocations.edges.length}
<ol>
{data.allLocations.edges.map(({ node, cursor }) =>
<Location data={node} key={cursor} />,
)}
</ol>
<div style={styles.container}>
<div style={styles.header}>
<Paper style={styles.header} elevation={4}>
<Typography type="display1" gutterBottom>
Locations
</Typography>
<Typography type="subheading" gutterBottom>
Loaded: {data.allLocations.edges.length}
</Typography>
</Paper>
</div>
<div className={styles.list}>
<List>
{data.allLocations.edges.map(({ node, cursor }) =>
<Location data={node} key={cursor} />
)}
</List>
</div>
</div>
);
};
Expand All @@ -27,5 +59,5 @@ export default createFragmentContainer(
}
}
}
`,
`
);
69 changes: 69 additions & 0 deletions components/withRoot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React, { Component } from 'react';
import { JssProvider } from 'react-jss';
import {
withStyles,
createStyleSheet,
MuiThemeProvider
} from 'material-ui/styles';
import { getContext } from '../styles/context';

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

let AppWrapper = props => props.children;

AppWrapper = withStyles(styleSheet)(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;
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
{
"dependencies": {
"material-ui": "next",
"material-ui-icons": "^1.0.0-alpha.19",
"next": "beta",
"react": "^15.6.1",
"react-dom": "^15.6.1",
"react-jss": "^7.0.2",
"react-relay": "^1.1.0"
},
"devDependencies": {
Expand Down
57 changes: 57 additions & 0 deletions pages/_document.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
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>
);
}
}
5 changes: 4 additions & 1 deletion pages/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import App from '../components/App';
import withRoot from '../components/withRoot';

export default () => <App />;
const Index = () => <App />;

export default withRoot(Index);
49 changes: 49 additions & 0 deletions 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__;
}
Loading

0 comments on commit 738a654

Please sign in to comment.