feature/vanilla-emotion - add an example of vanilla emotion (#20228)

Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
Co-authored-by: Tim Neutkens <tim@timneutkens.nl>
This commit is contained in:
MMT-LD 2021-01-22 11:16:50 +00:00 committed by GitHub
parent 4dc32ec0a7
commit 60b0267400
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 260 additions and 0 deletions

View file

@ -0,0 +1,4 @@
{
"presets": [["next/babel"]],
"plugins": ["@emotion/babel-plugin"]
}

View file

@ -0,0 +1,34 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
# vercel
.vercel

View file

@ -0,0 +1,24 @@
# Emotion Vanilla Example
Extract and inline critical css with
[emotion](https://github.com/emotion-js/emotion/tree/master/packages/emotion),
[@emotion/server](https://github.com/emotion-js/emotion/tree/master/packages/server),
[@emotion/css](https://github.com/emotion-js/emotion/tree/master/packages/css)
## Deploy your own
Deploy the example using [Vercel](https://vercel.com):
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/import/project?template=https://github.com/vercel/next.js/tree/canary/examples/with-emotion-vanilla)
## How to use
Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example:
```bash
npx create-next-app --example with-emotion-vanilla with-emotion-vanilla-app
# or
yarn create next-app --example with-emotion-vanilla with-emotion-vanilla-app
```
Deploy it to the cloud with [Vercel](https://vercel.com/import?filter=next.js&utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).

View file

@ -0,0 +1,20 @@
{
"name": "with-emotion-vanilla",
"version": "1.0.0",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
},
"license": "MIT",
"devDependencies": {
"@emotion/babel-plugin": "11.0.0"
},
"dependencies": {
"@emotion/css": "11.0.0",
"@emotion/server": "11.0.0",
"next": "latest",
"react": "^17.0.1",
"react-dom": "^17.0.1"
}
}

View file

@ -0,0 +1,34 @@
import Document, { Html, Head, Main, NextScript } from 'next/document'
import * as React from 'react'
import { renderStatic } from '../shared/renderer'
export default class AppDocument extends Document {
static async getInitialProps(ctx) {
const page = await ctx.renderPage()
const { css, ids } = await renderStatic(page.html)
const initialProps = await Document.getInitialProps(ctx)
return {
...initialProps,
styles: (
<React.Fragment>
{initialProps.styles}
<style
data-emotion={`css ${ids.join(' ')}`}
dangerouslySetInnerHTML={{ __html: css }}
/>
</React.Fragment>
),
}
}
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}

View file

@ -0,0 +1,30 @@
import Head from 'next/head'
import {
basicStyles,
otherStyles,
someMoreBasicStyles,
someCssAsObject,
combinedAsArray,
cxExample,
keyframesExample,
} from '../shared/styles'
const Home = () => (
<>
<Head>
<title>Emotion using the vanilla version supporting SSR</title>
</Head>
<div>
<h1>Emotion Vanilla example</h1>
<div className={basicStyles}>Basic styles using emotion</div>
<div className={otherStyles}>Some more styles using emotion</div>
<div className={someMoreBasicStyles}>Well why not here is some more</div>
<div className={someCssAsObject}>Object styles using emotion css</div>
<div className={combinedAsArray}>Array of styles using emotion css</div>
<div className={cxExample}>cx example from emotion</div>
<div className={keyframesExample} />
</div>
</>
)
export default Home

View file

@ -0,0 +1,12 @@
import createEmotionServer from '@emotion/server/create-instance'
import { cache } from '@emotion/css'
export const renderStatic = async (html) => {
if (html === undefined) {
throw new Error('did you forget to return html from renderToString?')
}
const { extractCritical } = createEmotionServer(cache)
const { ids, css } = extractCritical(html)
return { html, ids, css }
}

View file

@ -0,0 +1,102 @@
import { css, cx, keyframes, injectGlobal } from '@emotion/css'
injectGlobal`
* {
box-sizing: border-box;
}
body {
background: #DFCFBE;
font-family: Helvetica, sans-serif;
}
`
const basicStyles = css`
background-color: white;
color: cornflowerblue;
border: 1px solid lightgreen;
border-right: none;
border-bottom: none;
box-shadow: 5px 5px 0 0 lightgreen, 10px 10px 0 0 lightyellow;
transition: all 0.1s linear;
margin: 3rem 0;
padding: 1rem 0.5rem;
`
const otherStyles = css`
background-color: red;
padding: 10px;
margin-bottom: 10px;
`
const someMoreBasicStyles = css`
background-color: green;
color: white;
margin-bottom: 10px;
padding: 10px;
`
const someCssAsObject = css({
background: 'orange',
color: 'white',
padding: '10px',
marginBottom: '10px',
})
const combinedAsArray = css([someMoreBasicStyles, someCssAsObject])
const cls1 = css`
font-size: 20px;
padding: 5px;
background: green;
color: orange;
`
const cls2 = css`
font-size: 20px;
padding: 15px;
background: blue;
color: white;
`
const cxExample = cx(cls1, cls2)
const bounce = keyframes`
from, 20%, 53%, 80%, to {
transform: translate3d(0,0,0);
}
40%, 43% {
transform: translate3d(0, -30px, 0);
}
70% {
transform: translate3d(0, -15px, 0);
}
90% {
transform: translate3d(0,-4px,0);
}
`
const keyframesExample = css([
bounce,
css({
marginTop: '50px',
width: '20px',
height: '20px',
background: 'black',
borderRadius: '50%',
padding: '20px',
animation: `${bounce} 1s ease infinite`,
transformOrigin: 'center',
}),
])
export {
combinedAsArray,
cxExample,
keyframesExample,
someCssAsObject,
someMoreBasicStyles,
otherStyles,
basicStyles,
}