Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(example): add an example of using emotion css prop #1607

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions contributors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
- GregBrimble
- hardingmatt
- HenryVogt
- himorishige
- hkan
- Holben888
- hollandThomas
Expand Down
5 changes: 5 additions & 0 deletions examples/emotion-css-prop/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules

/.cache
/build
/public/build
26 changes: 26 additions & 0 deletions examples/emotion-css-prop/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Example app with [Emotion](https://emotion.sh/docs/introduction) - css Prop

This example features how to use [Emotion](https://emotion.sh/docs/introduction) - css Prop with Remix.

## Preview

Open this example on [CodeSandbox](https://codesandbox.com):

[![Open in CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/remix-run/remix/tree/main/examples/emotion-css-prop)

## Example

This example shows how to use Emotion - css Prop with Remix.

Relevant files:

- [app/root.tsx](./app/root.tsx) - This is where we render the app and if we're rendering on the server we have placeholder text of __STYLES__.
- [app/entry.server.tsx](./app/entry.server.tsx) - This is where we render the app on the server and replace __STYLES__ with the styles that emotion collect.
- [app/routes/index.tsx](./app/routes/index.tsx) - Here's where we use the css Prop to styling component.
- [tsconfig.json](./tsconfig.json) - Add `jsxImportSource` to use the css Prop in tsx file.

## Related Links

- [Emotion](https://emotion.sh/docs/introduction)
- [The css Prop](https://emotion.sh/docs/css-prop)
- [emotion-reset](https://github.com/sayegh7/emotion-reset)
4 changes: 4 additions & 0 deletions examples/emotion-css-prop/app/entry.client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { hydrate } from "react-dom";
import { RemixBrowser } from "remix";

hydrate(<RemixBrowser />, document);
49 changes: 49 additions & 0 deletions examples/emotion-css-prop/app/entry.server.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { renderToString } from "react-dom/server";
import { RemixServer } from "remix";
import createEmotionServer from "@emotion/server/create-instance";
import createCache from "@emotion/cache";
import { css, CacheProvider, Global } from "@emotion/react";
import emotionReset from "emotion-reset";
import type { EntryContext } from "remix";

const key = "emotion";
const cache = createCache({ key });
const { extractCriticalToChunks, constructStyleTagsFromChunks } =
createEmotionServer(cache);

export default function handleRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext
) {
let markup = renderToString(
<CacheProvider value={cache}>
{/* Set the global style. */}
<Global
styles={css`
${emotionReset}
*, *::after, *::before {
box-sizing: border-box;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
font-smoothing: antialiased;
}
`}
/>
<RemixServer context={remixContext} url={request.url} />
</CacheProvider>
);

const chunks = extractCriticalToChunks(markup);

const styles = constructStyleTagsFromChunks(chunks);
markup = markup.replace("__STYLES__", styles);

responseHeaders.set("Content-Type", "text/html");

return new Response("<!DOCTYPE html>" + markup, {
status: responseStatusCode,
headers: responseHeaders
});
}
28 changes: 28 additions & 0 deletions examples/emotion-css-prop/app/root.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {
Links,
LiveReload,
Meta,
Outlet,
Scripts,
ScrollRestoration
} from "remix";

export default function App() {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<Meta />
<Links />
{typeof document === "undefined" ? "__STYLES__" : null}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you confident this doesn't result in hydration mismatches? What about client side navigations, does emotion replace the contents here? Is it stable on rerenders in App?

Copy link
Contributor Author

@himorishige himorishige Jan 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review.
There were some implementation mistakes...
I've committed the adjusted version again.

</head>
<body>
<Outlet />
<ScrollRestoration />
<Scripts />
<LiveReload />
</body>
</html>
);
}
25 changes: 25 additions & 0 deletions examples/emotion-css-prop/app/routes/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/** @jsx jsx */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does esbuild respect this pragma?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

esbuild supports jsx annotations.
However, it seems that jsxImportSource support is not yet implemented without babel support.

ref:
Support JSX annotation
evanw/esbuild#138

Support /** @jsx pragma
evanw/esbuild#389

Add support for jsxImportSource
evanw/esbuild#1172

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although it is limited, it seems to be possible to remove the pragma by adopting the patch in this issue.

import { jsx, css } from "@emotion/react";

// Object Styles
const wrapperStyle = {
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
};

// String Styles
const headingStyle = css`
font-size: 2rem;
font-weight: 700;
color: hotpink;
`;

export default function Index() {
return (
<div css={wrapperStyle}>
<h1 css={headingStyle}>Welcome to Remix (With Emotion css Prop)</h1>
</div>
);
}
Loading