Setup Design System with NextJS Web App

Also replaced the local fonts with Google fonts since they are more performant and easier to package. Created a custom
Link component to render the ChakraUI link inside the NextJS Link properly.
This commit is contained in:
Hammad Jutt
2020-07-26 09:45:10 -06:00
parent c7f74aa211
commit 0f9c790351
24 changed files with 140 additions and 95 deletions

View File

@@ -12,7 +12,7 @@
"docker:clean": "docker-compose down -v",
"app:start": "CI=true lerna run start --parallel --scope @metafam/app-react --scope @metafam/utils",
"app:build": "lerna run build --scope @metafam/app-react --include-dependencies --stream",
"web:dev": "lerna run dev --parallel --scope @metafam/web",
"web:dev": "lerna run dev --parallel --scope @metafam/web --scope @metafam/ds",
"web:build": "lerna run build --parallel --scope @metafam/web",
"backend:dev": "lerna run dev --parallel --scope @metafam/backend --include-dependencies",
"backend:build": "lerna run build --scope @metafam/backend --include-dependencies --stream",

View File

@@ -9,6 +9,7 @@
"build-storybook": "build-storybook",
"prepare": "yarn build",
"typecheck": "yarn build",
"dev": "tsc -w",
"build": "tsc",
"precommit": "yarn lint-staged"
},

View File

@@ -2,67 +2,9 @@ import { CSSReset } from '@chakra-ui/core';
import { Global } from '@emotion/core';
import React from 'react';
import ibmPlexMonoBoldWoff from './fonts/ibm-plex-mono-v5-latin-700.woff';
import ibmPlexMonoBoldWoff2 from './fonts/ibm-plex-mono-v5-latin-700.woff2';
import ibmPlexMonoWoff from './fonts/ibm-plex-mono-v5-latin-regular.woff';
import ibmPlexMonoWoff2 from './fonts/ibm-plex-mono-v5-latin-regular.woff2';
import ibmPlexSansBoldWoff from './fonts/ibm-plex-sans-v7-latin-700.woff';
import ibmPlexSansBoldWoff2 from './fonts/ibm-plex-sans-v7-latin-700.woff2';
import ibmPlexSansWoff from './fonts/ibm-plex-sans-v7-latin-regular.woff';
import ibmPlexSansWoff2 from './fonts/ibm-plex-sans-v7-latin-regular.woff2';
import pressStartFontWoff from './fonts/press-start-2p-regular.woff';
import pressStartFontWoff2 from './fonts/press-start-2p-regular.woff2';
export const GlobalStyle = () => (
export const GlobalStyle: React.FC = () => (
<>
<CSSReset />
<Global
styles={`
@font-face {
font-family: 'Press Start 2P';
font-style: normal;
font-weight: 400;
src: local('Press Start 2P Regular'), local('PressStart2P-Regular'),
url(${pressStartFontWoff2}) format('woff2'),
url(${pressStartFontWoff}) format('woff');
}
@font-face {
font-family: 'IBM Plex Mono';
font-style: normal;
font-weight: 400;
src: local('IBM Plex Mono'), local('IBMPlexMono'),
url(${ibmPlexMonoWoff2}) format('woff2'),
url(${ibmPlexMonoWoff}) format('woff');
}
@font-face {
font-family: 'IBM Plex Mono';
font-style: normal;
font-weight: 700;
src: local('IBM Plex Mono Bold'), local('IBMPlexMono-Bold'),
url(${ibmPlexMonoBoldWoff2}) format('woff2'),
url(${ibmPlexMonoBoldWoff}) format('woff');
}
@font-face {
font-family: 'IBM Plex Sans';
font-style: normal;
font-weight: 400;
src: local('IBM Plex Sans'), local('IBMPlexSans'),
url(${ibmPlexSansWoff2}) format('woff2'),
url(${ibmPlexSansWoff}) format('woff');
}
@font-face {
font-family: 'IBM Plex Sans';
font-style: normal;
font-weight: 700;
src: local('IBM Plex Sans Bold'), local('IBMPlexSans-Bold'),
url(${ibmPlexSansBoldWoff2}) format('woff2'),
url(${ibmPlexSansBoldWoff}) format('woff');
}
`}
/>
<Global styles={{}} />
</>
);

View File

@@ -1,2 +0,0 @@
declare module '*.woff';
declare module '*.woff2';

View File

@@ -1,3 +1,26 @@
export { ThemeProvider } from '@chakra-ui/core';
export {
ThemeProvider,
Heading,
Box,
Image,
Text,
Avatar,
Button,
Grid,
SimpleGrid,
Flex,
Divider,
Icon,
IconButton,
Link,
List,
Input,
Select,
Skeleton,
Spinner,
Stack,
useTheme,
useToast,
} from '@chakra-ui/core';
export { theme } from './theme';
export { GlobalStyle } from './GlobalStyle';

View File

@@ -2,6 +2,10 @@
"rules": {
"react/react-in-jsx-scope": "off"
},
"parserOptions": {
"project": "./tsconfig.json",
"ecmaVersion": 6
},
"overrides": [
{
"files": ["./pages/**/*.{ts,tsx}"],

View File

@@ -0,0 +1,13 @@
import { Link } from '@metafam/ds';
import NextLink, { LinkProps } from 'next/link';
import React from 'react';
type Props = LinkProps;
export const MetaLink: React.FC<Props> = ({ children, ...props }) => (
<NextLink {...props} passHref>
{/* NextLink passes the href */}
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
<Link>{children}</Link>
</NextLink>
);

View File

@@ -10,14 +10,18 @@
"precommit": "yarn lint-staged"
},
"dependencies": {
"@types/node": "^14.0.23",
"@types/react": "^16.9.43",
"@types/react-dom": "^16.9.8",
"@metafam/ds": "0.1.0",
"graphql": "^15.0.0",
"isomorphic-unfetch": "^3.0.0",
"next": "latest",
"next-google-fonts": "^1.2.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"urql": "^1.9.7"
},
"devDependencies": {
"@types/node": "^14.0.23",
"@types/react": "^16.9.43",
"@types/react-dom": "^16.9.8"
}
}

View File

@@ -0,0 +1,13 @@
import { GlobalStyle, ThemeProvider } from '@metafam/ds';
import { AppProps } from 'next/app';
const app: React.FC<AppProps> = ({ pageProps, Component }) => {
return (
<ThemeProvider>
<GlobalStyle />
<Component {...pageProps} />
</ThemeProvider>
);
};
export default app;

View File

@@ -0,0 +1,39 @@
import GoogleFonts from 'next-google-fonts';
import Document, {
DocumentContext,
DocumentInitialProps,
Head,
Html,
Main,
NextScript,
} from 'next/document';
class MetaDocument extends Document {
static async getInitialProps(
ctx: DocumentContext,
): Promise<DocumentInitialProps> {
const initialProps = await Document.getInitialProps(ctx);
return { ...initialProps };
}
render(): JSX.Element {
return (
<Html>
<GoogleFonts href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;700&family=IBM+Plex+Sans:wght@400;700&family=Press+Start+2P&display=swap" />
<Head>
<meta charSet="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MetaDocument;

View File

@@ -1,36 +1,34 @@
import { Box, Heading, Image, SimpleGrid } from '@metafam/ds';
import { GetStaticProps } from 'next';
import Link from 'next/link'
import { getPokemons } from '../graphql/getPokemons'
import { MetaLink } from '../components/Link';
import { getPokemons } from '../graphql/getPokemons';
import { Pokemon } from '../types/pokemon';
type Props = {
pokemon: Array<Pokemon>
}
pokemon: Array<Pokemon>;
};
const Home: React.FC<Props> = ({ pokemon }) => (
<ul>
<SimpleGrid columns={{ sm: 2, lg: 3 }} spacing={6}>
{pokemon.map((p) => (
<li key={p.name}>
<Link as={`/pokemon/${p.name}`} href="pokemon/[name]">
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
<a>
<h2 style={{ textTransform: 'capitalize' }}>{p.name}</h2>
<img src={p.image} alt={p.name}/>
</a>
</Link>
</li>
<MetaLink as={`/pokemon/${p.name}`} href="pokemon/[name]">
<Box key={p.name}>
<Heading style={{ textTransform: 'capitalize' }}>{p.name}</Heading>
<Image src={p.image} alt={p.name} />
</Box>
</MetaLink>
))}
</ul>
</SimpleGrid>
);
export const getStaticProps: GetStaticProps<Props> = async () => {
const pokemon = await getPokemons()
const pokemon = await getPokemons();
return {
props: {
pokemon,
},
}
}
};
};
export default Home;

View File

@@ -1,3 +1,4 @@
import { Box, Flex, Heading, Image } from '@metafam/ds';
import { GetStaticPaths, GetStaticProps } from 'next';
import Error from 'next/error';
@@ -6,20 +7,21 @@ import { getPokemons } from '../../graphql/getPokemons';
import { Pokemon } from '../../types/pokemon';
type Props = {
pokemon: Pokemon | null
}
pokemon: Pokemon | null;
};
const PokemonPage: React.FC<Props> = ({ pokemon }) => {
if (!pokemon) {
return <Error statusCode={404}/>;
return <Error statusCode={404} />;
}
return (
<div>
<h1>{pokemon.name}</h1>
<img src={pokemon.image} alt={pokemon.name}/>
</div>
<Flex align="center" justify="center">
<Box>
<Heading textAlign="center">{pokemon.name}</Heading>
<Image src={pokemon.image} alt={pokemon.name} />
</Box>
</Flex>
);
};
export default PokemonPage;
@@ -35,7 +37,9 @@ export const getStaticPaths: GetStaticPaths = async () => {
};
};
export const getStaticProps: GetStaticProps<Props, { name: string }> = async (context) => {
export const getStaticProps: GetStaticProps<Props, { name: string }> = async (
context,
) => {
const name = context.params?.name;
const pokemon = await getPokemon(name);

View File

@@ -17,5 +17,6 @@
"path": "../design-system/tsconfig.json"
}
],
"include": ["**/*.ts", "**/*.tsx", "next-env.d.ts"]
"include": ["**/*.ts", "**/*.tsx", "next-env.d.ts"],
"exclude": ["out", ".next", "node_modules"]
}

View File

@@ -20059,6 +20059,11 @@ neo-async@2.6.1, neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1:
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c"
integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==
next-google-fonts@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/next-google-fonts/-/next-google-fonts-1.2.1.tgz#0b517cff3f34b8f7836f81eb9427973c8b4ac03e"
integrity sha512-BhVSldP1oZBTwXeJdMtjmu2qbDT1EkbQO2rG83Oj6APYm6aUsIcMu00Pzkzd8TTkrQW9HyC08Pzr10PY4pE6jA==
next-tick@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"