Skip to content

Commit

Permalink
Add css-in-js examples
Browse files Browse the repository at this point in the history
  • Loading branch information
Vadorequest committed May 21, 2020
1 parent 3cca48d commit 3feb1c0
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 18 deletions.
23 changes: 23 additions & 0 deletions src/components/doc/BuiltInFeaturesSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ const BuiltInFeaturesSection: React.FunctionComponent<Props> = (props): JSX.Elem
<ExternalLink href={'https://unlyed.github.io/next-right-now/concepts/i18n.html'}>
<Button color={'link'}>Learn more about the "i18n" concept</Button>
</ExternalLink>
<ExternalLink href={'https://unlyed.github.io/next-right-now/guides/i18n/use-locize.html'}>
<Button color={'link'}>Learn how to use the "Locize" vendor</Button>
</ExternalLink>
<I18nLink href={'/examples/static-i18n'}>
<Button color={'link'}>See usage examples</Button>
</I18nLink>
Expand All @@ -46,6 +49,9 @@ const BuiltInFeaturesSection: React.FunctionComponent<Props> = (props): JSX.Elem
<ExternalLink href={'https://unlyed.github.io/next-right-now/concepts/monitoring.html'}>
<Button color={'link'}>Learn more about the "Monitoring" concept</Button>
</ExternalLink>
<ExternalLink href={'https://unlyed.github.io/next-right-now/guides/monitoring/use-sentry.html'}>
<Button color={'link'}>Learn how to use the "Sentry" vendor</Button>
</ExternalLink>
<I18nLink href={'/examples/monitoring'}>
<Button color={'link'}>See usage examples</Button>
</I18nLink>
Expand Down Expand Up @@ -73,6 +79,23 @@ const BuiltInFeaturesSection: React.FunctionComponent<Props> = (props): JSX.Elem
</CardText>
</CardBody>
</Card>

<Card>
<CardBody>
<CardTitle><h3>CSS-in-JS</h3></CardTitle>
<CardSubtitle>&ldquo;Styling components with Emotion&rdquo;</CardSubtitle>
<CardText tag={'div'}>
<div className={'buttons'}>
<ExternalLink href={'https://unlyed.github.io/next-right-now/guides/css-in-js/use-emotion.html'}>
<Button color={'link'}>Learn how to use the "Emotion" library</Button>
</ExternalLink>
<I18nLink href={'/examples/css-in-js'}>
<Button color={'link'}>See usage examples</Button>
</I18nLink>
</div>
</CardText>
</CardBody>
</Card>
</Cards>
</DocSection>
);
Expand Down
9 changes: 3 additions & 6 deletions src/components/doc/NativeFeaturesSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,21 +83,18 @@ const NativeFeaturesSection: React.FunctionComponent<Props> = (props): JSX.Eleme
>
<li>
<ExternalLink href={'https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation'}>Static app</ExternalLink> (without any option)
{' - '}<Button color={'link'}>See example</Button>
</li>
<li>
<ExternalLink href={'https://nextjs.org/docs/basic-features/data-fetching#the-fallback-key-required'}>Using fallback</ExternalLink> (on-the-fly static builds)
{' - '}<Button color={'link'}>See example</Button>
</li>
<li>
<ExternalLink href={'https://nextjs.org/blog/next-9-4#incremental-static-regeneration-beta'}>Using revalidate</ExternalLink> (incremental static regeneration)
{' - '}<Button color={'link'}>See example</Button>
</li>
</ul>
</div>

<div className={'buttons'}>
<Button color={'link'}>Simple example</Button>
<Button color={'link'}>Example with fallback</Button>
<Button color={'link'}>Example with revalidate</Button>
</div>
</CardText>
</CardBody>
</Card>
Expand Down
148 changes: 148 additions & 0 deletions src/pages/[locale]/examples/css-in-js.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/** @jsx jsx */
import { jsx } from '@emotion/core';
import { createLogger } from '@unly/utils-simple-logger';
import { GetStaticPaths, GetStaticProps, NextPage } from 'next';
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-unused-vars
import React from 'react';
import { Alert } from 'reactstrap';
import DocPage from '../../../components/doc/DocPage';
import DefaultLayout from '../../../components/pageLayouts/DefaultLayout';
import Code from '../../../components/utils/Code';
import ExternalLink from '../../../components/utils/ExternalLink';
import withApollo from '../../../hocs/withApollo';
import { StaticParams } from '../../../types/nextjs/StaticParams';
import { OnlyBrowserPageProps } from '../../../types/pageProps/OnlyBrowserPageProps';
import { SSGPageProps } from '../../../types/pageProps/SSGPageProps';
import { getCommonStaticPaths, getCommonStaticProps } from '../../../utils/nextjs/SSG';

const fileLabel = 'pages/[locale]/docs/css-in-js';
const logger = createLogger({ // eslint-disable-line no-unused-vars,@typescript-eslint/no-unused-vars
label: fileLabel,
});

/**
* Only executed on the server side at build time.
*
* Note that when a page uses "getStaticProps", then "_app:getInitialProps" is executed (if defined) but not actually used by the page,
* only the results from getStaticProps are actually injected into the page (as "SSGPageProps").
*
* @return Props (as "SSGPageProps") that will be passed to the Page component, as props
*
* @see https://github.com/zeit/next.js/discussions/10949#discussioncomment-6884
* @see https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation
*/
export const getStaticProps: GetStaticProps<SSGPageProps, StaticParams> = getCommonStaticProps;

/**
* Only executed on the server side at build time
* Necessary when a page has dynamic routes and uses "getStaticProps"
*/
export const getStaticPaths: GetStaticPaths<StaticParams> = getCommonStaticPaths;

/**
* SSG pages are first rendered by the server (during static bundling)
* Then, they're rendered by the client, and gain additional props (defined in OnlyBrowserPageProps)
* Because this last case is the most common (server bundle only happens during development stage), we consider it a default
* To represent this behaviour, we use the native Partial TS keyword to make all OnlyBrowserPageProps optional
*
* Beware props in OnlyBrowserPageProps are not available on the server
*/
type Props = {} & SSGPageProps<Partial<OnlyBrowserPageProps>>;

const StaticI18n: NextPage<Props> = (props): JSX.Element => {
return (
<DefaultLayout
{...props}
pageName={'css-in-js'}
headProps={{
title: 'CSS-in-JS examples - Next Right Now',
}}
>
<DocPage>
<h2 className={'pcolor'}>CSS-in-JS using Emotion library</h2>

<Alert color={'info'}>
Emotion allows to use both the <code>styled component</code> and JSX-like ways of writing your CSS styles.<br />
<br />
A lot of research has been done to select the most robust css-in-js library, and we eventually chose
<ExternalLink href={'https://emotion.sh/docs/introduction'} suffix={null}>Emotion</ExternalLink>.<br />
After more than a year working with it at a production-grade level, we haven't noticed any drawbacks.
</Alert>

<Alert color={'warning'}>
Our personal preference is to use JSX-like way of writing styles, instead of the Styled Components approach.<br />
We want to make it clear that such choice is personal, and we have selected on purpose Emotion, because it allows both.<br />
In our opinion, the JSX way is better for iterating quickly when you don't know exactly the shape of your components.<br />
The choice is yours, do as you like!
</Alert>

<p>
The below example uses the JSX way, with CSS written directly in the element.
</p>

<Code
text={`
/** @jsx jsx */
import { css, jsx } from '@emotion/core';
<div
css={css\`
# Those rules apply to the top-level element (the "div")
justify-content: center;
text-align: center;
margin-left: auto;
margin-right: auto;
# Those rules apply to children elements using the "child-class" css class
.child-class {
margin: auto;
width: 50%;
@media screen and (min-width: 576px) {
margin: 50px
}
}
\`}
>
Top-level content
<p className={'child-class'}>Child content</p>
</div>
`}
/>

<hr />

<p>
The below example uses the Styled Component way, with CSS written in a dedicated React Component.
</p>

<Code
text={`
/** @jsx jsx */
import { jsx } from '@emotion/core';
import styled from '@emotion/styled';
const StyledImage = styled.img\`
width: 50px;
height: 100px;
@media screen and (min-width: 576px) {
height: 50px
}
\`;
const Image = (props): JSX.Element => {
const { onClick } = props;
return (
<StyledImage onClick={onClick}
);
`}
/>

</DocPage>
</DefaultLayout>
);
};

export default withApollo()(StaticI18n);
24 changes: 15 additions & 9 deletions src/pages/[locale]/examples/graphql.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,12 @@ const StaticI18n: NextPage<Props> = (props): JSX.Element => {

<Alert color={'warning'}>
Fetching APIs works slightly differently depending on whether you use SSG or SSR.<br />
<br />
When you're using SSG, all queries are executed from the server side, during build generation, on your computer or your CI server.<br />
When using SSR, queries are executed on the fly, from the client or from the server depending on how the page is served (CSR vs SSR).
Therefore, you need to be careful about tokens and other credentials you might use. And you also need to consider performances (e.g: running all queries at once)<br />
When using SSR, queries are executed on the fly, from the client or from the server depending on how the page is served (CSR vs SSR).<br />
<br />
Therefore, you need to be careful about tokens and other <b>credentials</b> you might use.
And you also need to consider performances (e.g: running all queries at once)<br />
<br />
The below examples will focus on SSG, because that's what we recommend to use. But know that you may use both.<br />
Also, you might want to run GraphQL queries from the browser even when using SSG, it's also possible but we don't provide such example at this time.
Expand All @@ -79,9 +82,11 @@ const StaticI18n: NextPage<Props> = (props): JSX.Element => {
displayName: 'LAYOUT_QUERY', // Naming queries makes debugging easier
query: LAYOUT_QUERY, // This is our actual GQL query (see /gql folder)
variables,
context: {
context: { // Per-request context override/overload
headers: {
'gcms-locale': gcmsLocales, // This is how we handle "Dynamic i18n", by only fetching content for this language
// This is how we handle "Dynamic i18n", by only fetching content for one language
// With languages fallback if content isn't available (e.g: ['FR', 'DE', 'EN']
'gcms-locale': gcmsLocales,
},
},
};
Expand Down Expand Up @@ -120,21 +125,22 @@ const StaticI18n: NextPage<Props> = (props): JSX.Element => {
export const LAYOUT_QUERY = gql\`
query LAYOUT_QUERY($customerRef: String!){
customer(where: {
ref: $customerRef,
}){
ref: $customerRef, // Use the variables that were provided to the GQL query
}){ // Fields that are being fetched
id
label
theme {
...themeFields
...themeFields // This uses a GQL fragment (code reusability)
}
}
}
\${theme.themeFields}
\${theme.themeFields} // Fragment(s) import
\`;
`}
/>

<p>
Note that it uses the <code>theme.themeFields</code> fragment.
All our pages fetch some data from GraphCMS, because we need those in shared components (i.e: Footer, Nav)
</p>

</DocPage>
Expand Down
5 changes: 2 additions & 3 deletions src/pages/[locale]/examples/static-i18n.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,8 @@ const StaticI18n: NextPage<Props> = (props): JSX.Element => {
<ExternalLink href={'https://github.com/i18next/react-i18next'}><code>react-i18next</code> package</ExternalLink>: What we actually use in NRN, mostly throught the <code>t</code> and <code>Trans</code> component.
</li>
<li>
<ExternalLink href={'https://locize.com/'}>Locize vendor packages (paid)</ExternalLink>: Vendor meant to help with static content localisation. <ExternalLink
href={'https://unlyed.github.io/next-right-now/guides/i18n/use-locize.html'}
>Read our "How to use" and learn more about what benefits it brings</ExternalLink>
<ExternalLink href={'https://locize.com/'}>Locize vendor packages (paid)</ExternalLink>: Vendor meant to help with static content localisation.
<ExternalLink href={'https://unlyed.github.io/next-right-now/guides/i18n/use-locize.html'}>Read our "How to use" and learn more about what benefits it brings</ExternalLink>
</li>
</ul>

Expand Down

0 comments on commit 3feb1c0

Please sign in to comment.