Skip to content

Commit

Permalink
[examples] Improve the Gastby integration (#14552)
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviertassinari authored Feb 16, 2019
1 parent 617c095 commit ebd0d1f
Show file tree
Hide file tree
Showing 22 changed files with 413 additions and 56 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
/.nyc_output
/coverage
/docs/export
/examples/**/.cache
/packages/material-ui-codemod/lib
/packages/material-ui-icons/material-io-tools-icons
/test/regressions/screenshots
Expand Down
60 changes: 27 additions & 33 deletions docs/src/modules/components/Link.js
Original file line number Diff line number Diff line change
@@ -1,64 +1,58 @@
/* eslint-disable jsx-a11y/click-events-have-key-events */
/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/anchor-has-content */

import React from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
import { withRouter } from 'next/router';
import NextLink from 'next/link';
import MuiLink from '@material-ui/core/Link';

function NextWrapper(props) {
const { className, activeClassName, onClick, router, href, prefetch, ...other } = props;
function NextComposed(props) {
const { as, href, prefetch, ...other } = props;

return (
<NextLink href={href} prefetch={prefetch}>
<a
onClick={onClick}
className={clsx(className, {
[activeClassName]: router.pathname === href && activeClassName,
})}
{...other}
/>
<NextLink href={href} prefetch={prefetch} as={as}>
<a {...other} />
</NextLink>
);
}

NextWrapper.defaultProps = {
activeClassName: 'active',
};

NextWrapper.propTypes = {
activeClassName: PropTypes.string,
className: PropTypes.string,
NextComposed.propTypes = {
as: PropTypes.string,
href: PropTypes.string,
onClick: PropTypes.func,
prefetch: PropTypes.bool,
router: PropTypes.shape({
pathname: PropTypes.string.isRequired,
}).isRequired,
};

// A styled version of the Next.js Link component:
// https://nextjs.org/docs/#with-link
function Link(props) {
const { naked, ...other } = props;
const { activeClassName, router, className: classNameProps, naked, ...other } = props;

const ToRender = {
component: NextWrapper,
...other,
};
const className = clsx(classNameProps, {
[activeClassName]: router.pathname === props.href && activeClassName,
});

if (naked) {
const { component: Component, ...rest } = ToRender;

return <Component {...rest} />;
return <NextComposed className={className} {...other} />;
}

return <MuiLink {...ToRender} />;
return <MuiLink component={NextComposed} className={className} {...other} />;
}

Link.propTypes = {
activeClassName: PropTypes.string,
as: PropTypes.string,
className: PropTypes.string,
href: PropTypes.string,
naked: PropTypes.bool,
onClick: PropTypes.func,
prefetch: PropTypes.bool,
router: PropTypes.shape({
pathname: PropTypes.string.isRequired,
}).isRequired,
};

Link.defaultProps = {
activeClassName: 'active',
};

export default withRouter(Link);
1 change: 1 addition & 0 deletions examples/create-react-app-next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"private": true,
"dependencies": {
"@material-ui/core": "next",
"jss": "next",
"prop-types": "latest",
"react": "latest",
"react-dom": "latest",
Expand Down
19 changes: 19 additions & 0 deletions examples/gatsby-next/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# See https://help.github.com/ignore-files/ for more about ignoring files.

# dependencies
/node_modules

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Gatsby.js
/public
/.cache
21 changes: 21 additions & 0 deletions examples/gatsby-next/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Gatsby v4-alpha example

## How to use

Download the example [or clone the repo](https://github.com/mui-org/material-ui):

```sh
curl https://codeload.github.com/mui-org/material-ui/tar.gz/next | tar -xz --strip=2 material-ui-next/examples/gatsby-next
cd gatsby-next
```

Install it and run:

```sh
npm install
npm run develop
```

## The idea behind the example

[Gatsby](https://github.com/gatsbyjs/gatsby) is a static site generator for React.
13 changes: 13 additions & 0 deletions examples/gatsby-next/gatsby-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module.exports = {
plugins: [
{
resolve: 'gatsby-plugin-material-ui',
options: {
pathToTheme: 'src/utils/theme.js',
},
},
],
siteMetadata: {
title: 'Gatsby Material-UI next',
},
};
17 changes: 17 additions & 0 deletions examples/gatsby-next/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "gatsby-next",
"version": "4.0.0",
"private": true,
"dependencies": {
"@material-ui/core": "next",
"@material-ui/styles": "next",
"gatsby": "latest",
"react": "latest",
"react-dom": "latest"
},
"scripts": {
"develop": "gatsby develop",
"build": "gatsby build",
"serve": "gatsby serve"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* eslint-disable react/prop-types */

import React from 'react';
import { install } from '@material-ui/styles';
import { ThemeProvider } from '@material-ui/styles';
import theme from './.cache/theme';

install();

export const onInitialClientRender = () => {
if (process.env.BUILD_STAGE === `develop`) {
return;
}

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

export const wrapRootElement = ({ element }) => {
return <ThemeProvider theme={theme}>{element}</ThemeProvider>;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const fs = require(`fs`);
const path = require(`path`);
const os = require(`os`);

// Write out a theme module to .cache.
// https://github.com/gatsbyjs/gatsby/blob/9bb587df3faed2f75af571d8d69e3bc4d7f65193/packages/gatsby-plugin-typography/src/gatsby-node.js

exports.onPreBootstrap = ({ store }, pluginOptions) => {
const program = store.getState().program;

let module;
if (pluginOptions.pathToTheme) {
module = `module.exports = require("${
path.isAbsolute(pluginOptions.pathToTheme)
? pluginOptions.pathToTheme
: path.join(program.directory, pluginOptions.pathToTheme)
}")`;
if (os.platform() === `win32`) {
module = module.split(`\\`).join(`\\\\`);
}
} else {
module = `const styles = require("@material-ui/core/styles");
const theme = styles.createMuiTheme();
module.exports = theme;`;
}

const dir = `${__dirname}/.cache`;

if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}

fs.writeFileSync(`${dir}/theme.js`, module);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* eslint-disable react/no-danger, react/prop-types */

import React from 'react';
import { install } from '@material-ui/styles';
import { SheetsRegistry } from 'jss';
import { StylesProvider, ThemeProvider } from '@material-ui/styles';
import theme from './.cache/theme';

install();

// Keep track of sheetsRegistry for each page
const globalLeak = new Map();

export const wrapRootElement = ({ element, pathname }) => {
const sheetsRegistry = new SheetsRegistry();
globalLeak.set(pathname, sheetsRegistry);

return (
<StylesProvider sheetsRegistry={sheetsRegistry} sheetsManager={new Map()}>
<ThemeProvider theme={theme}>{element}</ThemeProvider>
</StylesProvider>
);
};

export const onRenderBody = ({ setHeadComponents, pathname }) => {
// onRenderBody is called in develop mode. It's strange?
if (!pathname) {
return;
}

const sheetsRegistry = globalLeak.get(pathname);
setHeadComponents([
<style
id="jss-server-side"
key="jss-server-side"
dangerouslySetInnerHTML={{ __html: sheetsRegistry.toString() }}
/>,
]);
globalLeak.delete(pathname);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "gatsby-plugin-material-ui"
}
9 changes: 9 additions & 0 deletions examples/gatsby-next/src/components/Link.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';
import MuiLink from '@material-ui/core/Link';
import { Link as GastsbyLink } from 'gatsby';

function Link(props) {
return <MuiLink component={GastsbyLink} {...props} />;
}

export default Link;
40 changes: 40 additions & 0 deletions examples/gatsby-next/src/pages/about.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';
import PropTypes from 'prop-types';
import Button from '@material-ui/core/Button';
import Typography from '@material-ui/core/Typography';
import { withStyles } from '@material-ui/styles';
import Link from '../components/Link';

const styles = theme => ({
root: {
textAlign: 'center',
paddingTop: theme.spacing(20),
},
});

function About(props) {
const { classes } = props;

return (
<div className={classes.root}>
<Typography variant="h4" component="h1" gutterBottom>
Material-UI
</Typography>
<Typography variant="subtitle1" component="h2" gutterBottom>
about page
</Typography>
<Typography gutterBottom>
<Link to="/">Go to the main page</Link>
</Typography>
<Button variant="contained" color="primary">
Do nothing button
</Button>
</div>
);
}

About.propTypes = {
classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(About);
60 changes: 60 additions & 0 deletions examples/gatsby-next/src/pages/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react';
import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import DialogTitle from '@material-ui/core/DialogTitle';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import DialogActions from '@material-ui/core/DialogActions';
import Typography from '@material-ui/core/Typography';
import { makeStyles } from '@material-ui/styles';
import Link from '../components/Link';

const useStyles = makeStyles(theme => ({
root: {
textAlign: 'center',
paddingTop: theme.spacing(20),
},
}));

function Index() {
const classes = useStyles();
const [open, setOpen] = React.useState(false);
const handleClose = () => {
setOpen(false);
};
const handleClick = () => {
setOpen(true);
};

return (
<div className={classes.root}>
<Dialog open={open} onClose={handleClose}>
<DialogTitle>Super Secret Password</DialogTitle>
<DialogContent>
<DialogContentText>1-2-3-4-5</DialogContentText>
</DialogContent>
<DialogActions>
<Button color="primary" onClick={handleClose}>
OK
</Button>
</DialogActions>
</Dialog>
<Typography variant="h4" gutterBottom>
Material-UI
</Typography>
<Typography variant="subtitle1" gutterBottom>
home page
</Typography>
<Typography gutterBottom>
<Link color="secondary" to="/about">
Go to the about page
</Link>
</Typography>
<Button variant="contained" color="secondary" onClick={handleClick}>
Super Secret Password
</Button>
</div>
);
}

export default Index;
Loading

0 comments on commit ebd0d1f

Please sign in to comment.