1
0
mirror of https://github.com/phuoc-ng/csslayout.git synced 2025-08-06 06:07:33 +02:00

Add layout

This commit is contained in:
Phuoc Nguyen
2021-09-27 20:32:58 +07:00
parent 88200a6983
commit bced6a1df5
21 changed files with 351 additions and 148 deletions

View File

@@ -1,14 +0,0 @@
{
"plugins": [
"@loadable/babel-plugin",
["prismjs", {
"languages": ["css", "html", "javascript", "jsx", "tsx"],
// "theme": "okaidia",
"css": true
}]
],
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
}

3
.gitignore vendored
View File

@@ -1,6 +1,7 @@
.DS_Store
.netlify
dist
.next
node_modules
out
package-lock.json
tslint.log

3
.prettierignore Normal file
View File

@@ -0,0 +1,3 @@
.netlify
.next
node_modules

View File

@@ -18,7 +18,7 @@ const main = () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(`http://localhost:1234/patterns/${pattern}`);
await page.goto(`http://localhost:3000/patterns/${pattern}`);
await page.waitForSelector('.demo__live');
const element = await page.$('.demo__live');

View File

@@ -0,0 +1,32 @@
import * as React from 'react';
import { Footer, FooterGroup, FooterLink } from '@1milligram/design';
export const FooterBlock = () => (
<footer className="block-footer">
<div className="block-container">
<Footer>
<FooterGroup title="Products">
<FooterLink href="https://blur.page">Blur Page</FooterLink>
<FooterLink href="https://formvalidation.io">Form Validation</FooterLink>
<FooterLink href="https://intersectionobserver.io">IntersectionObserver Examples</FooterLink>
<FooterLink href="https://react-pdf-viewer.dev">React PDF Viewer</FooterLink>
</FooterGroup>
<FooterGroup title="Open sources">
<FooterLink href="https://1loc.dev">1 LOC</FooterLink>
<FooterLink href="https://csslayout.io">CSS Layout</FooterLink>
<FooterLink href="https://getfrontend.tips">Front-end Tips</FooterLink>
<FooterLink href="https://htmldom.dev">HTML DOM</FooterLink>
<FooterLink href="https://thisthat.dev">this VS that</FooterLink>
</FooterGroup>
<FooterGroup title="Follow us">
<FooterLink href="https://github.com/1milligram">GitHub</FooterLink>
<FooterLink href="https://twitter.com/nghuuphuoc">Twitter</FooterLink>
</FooterGroup>
</Footer>
<div className="block-footer__copyright">
© 2020 {new Date().getFullYear()}, 1 milligram. All rights reserved.
</div>
</div>
</footer>
);

View File

@@ -0,0 +1,37 @@
import Link from 'next/link';
import * as React from 'react';
import { Logo } from '@1milligram/design';
export const HeaderBlock = () => {
const [totalStars, setTotalStars] = React.useState(0);
React.useEffect(() => {
fetch('https://api.github.com/repos/1milligram/csslayout')
.then((res) => res.json())
.then((data) => setTotalStars(data.stargazers_count))
.catch(console.log);
}, []);
const HeaderLogo = React.forwardRef<HTMLAnchorElement, React.LinkHTMLAttributes<HTMLAnchorElement>>(
(props, ref) => (
<a href={props.href} onClick={props.onClick} ref={ref}>
<Logo brand="CSS Layout" />
</a>
)
);
return (
<header className="block-header">
<div className="block-container">
<div className="block-header__inner">
<Link href="/" passHref>
<HeaderLogo />
</Link>
<Link href="https://github.com/1milligram/csslayout">
<a className="block-header__cta">GitHub {totalStars}</a>
</Link>
</div>
</div>
</header>
);
};

25
layouts/Layout.tsx Normal file
View File

@@ -0,0 +1,25 @@
import Head from 'next/head';
import * as React from 'react';
import { FooterBlock } from '../components/FooterBlock';
import { HeaderBlock } from '../components/HeaderBlock';
interface LayoutProps {
title: string;
}
export const Layout: React.FC<LayoutProps> = ({ children, title }) => (
<>
<Head>
<title>{title} - CSS Layout</title>
<meta name="description" content={title} />
<meta name="twitter:title" content={`${title} - CSS Layout`} />
<meta name="twitter:description" content={title} />
<meta property="og:title" content={`${title} - CSS Layout`} />
<meta property="og:description" content={title} />
</Head>
<HeaderBlock />
{children}
<FooterBlock />
</>
);

6
next-env.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

9
next.config.js Normal file
View File

@@ -0,0 +1,9 @@
const withMDX = require('@next/mdx')({
extension: /\.mdx?$/,
});
module.exports = withMDX({
// `true` will transform `/about` to `/about/index.html`
trailingSlash: true,
pageExtensions: ['js', 'jsx', 'tsx', 'mdx'],
});

View File

@@ -1,61 +1,61 @@
{
"name": "csslayout",
"description": "A collection of popular layouts and patterns made with CSS",
"author": {
"name": "Nguyen Huu Phuoc",
"email": "me@phuoc.ng",
"url": "https://twitter.com/nghuuphuoc"
},
"homepage": "https://csslayout.io",
"keywords": [
"CSS grid",
"CSS flexbox",
"CSS layout",
"CSS patterns"
],
"repository": {
"type": "git",
"url": "https://github.com/1milligram/csslayout"
},
"bugs": {
"url": "https://github.com/1milligram/csslayout/issues"
},
"license": "MIT",
"scripts": {
"copy": "rimraf dist && mkdir dist && cpx 'public/**/*' dist",
"dev": "npm run copy && webpack --mode=development",
"dev-server": "npm run copy && NODE_ENV=development webpack serve",
"build": "npm run copy && webpack --mode=production && npm run export",
"export": "react-snap",
"deploy": "npm run build && netlify deploy --dir=dist --prod",
"analyse": "NODE_ENV=analyse webpack --config webpack.config.js -p",
"build": "next build",
"dev": "next dev",
"format": "prettier --write \"**/*.+(css|html|json|js|jsx|mdx|scss|ts|tsx)\"",
"preexport": "npm run build",
"export": "next export",
"deploy": "npm run export && netlify deploy --prod --dir=out",
"lint": "tslint -c tslint.json -o tslint.log 'client/**/*.{ts,tsx}'",
"screenshot": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node bin/generateScreenshot.ts"
},
"dependencies": {
"@loadable/component": "^5.14.1",
"prismjs": "^1.23.0",
"@1milligram/design": "^0.4.0",
"@1milligram/frame": "^1.0.0",
"@mdx-js/loader": "^1.6.22",
"@mdx-js/react": "^1.6.22",
"@next/mdx": "^11.1.2",
"next": "^11.1.2",
"prism-react-renderer": "^1.2.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-helmet": "^6.1.0",
"react-router-dom": "^5.2.0"
"react-dom": "^17.0.2"
},
"devDependencies": {
"@babel/core": "^7.13.13",
"@babel/preset-env": "^7.13.12",
"@babel/preset-react": "^7.13.13",
"@loadable/babel-plugin": "^5.13.2",
"@types/linkifyjs": "^2.1.4",
"@types/loadable__component": "^5.13.3",
"@types/prismjs": "^1.16.4",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.3",
"@types/react-helmet": "^6.1.0",
"@types/react-router-dom": "^5.1.7",
"babel-loader": "^8.2.2",
"babel-plugin-prismjs": "^2.0.1",
"cpx2": "^3.0.0",
"css-loader": "^5.2.0",
"html-webpack-plugin": "^5.3.1",
"mini-css-extract-plugin": "^1.4.0",
"puppeteer": "^1.20.0",
"react-snap": "^1.23.0",
"rimraf": "^3.0.2",
"source-map-loader": "^2.0.1",
"style-loader": "^2.0.0",
"@types/react": "^17.0.20",
"@types/react-dom": "^17.0.9",
"puppeteer": "^10.4.0",
"prettier": "^2.4.0",
"sass": "^1.39.2",
"serve": "^12.0.1",
"typescript": "^4.4.3",
"ts-loader": "^8.1.0",
"ts-node": "^9.1.1",
"tslint": "^6.1.3",
"tslint-react": "^5.0.0",
"typescript": "^4.2.3",
"webpack": "^5.28.0",
"webpack-bundle-analyzer": "^4.4.0",
"webpack-cli": "^4.6.0",
"webpack-dev-server": "^3.11.2"
},
"reactSnap": {
"source": "dist",
"minifyHtml": {
"collapseWhitespace": false,
"removeComments": false
}
"tslint-react": "^5.0.0"
}
}

17
pages/_app.tsx Normal file
View File

@@ -0,0 +1,17 @@
import Head from 'next/head';
// Design
import '@1milligram/design/lib/styles/index.css';
import '@1milligram/frame/lib/styles/index.css';
import '../styles/index.scss';
export default function MyApp({ Component, pageProps }) {
return (
<>
<Head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>
<Component {...pageProps} />
</>
);
}

44
pages/_document.tsx Normal file
View File

@@ -0,0 +1,44 @@
import Document, { Html, Head, Main, NextScript } from 'next/document';
class MyDocument extends Document {
render() {
return (
<Html>
<Head>
<link href="/favicon.png" rel="icon" />
<meta charSet="utf-8" />
<meta content="A collection of popular layouts and patterns made with CSS" name="description" />
<meta content="CSS flexbox, CSS grid, CSS layout, CSS patterns" name="keywords" />
<meta content="Nguyen Huu Phuoc" name="author" />
<meta content="@nghuuphuoc" name="twitter:site" />
<meta content="summary" name="twitter:card" />
<meta content="A collection of popular layouts and patterns made with CSS" name="twitter:description" />
<meta content="A collection of popular layouts and patterns made with CSS" name="twitter:title" />
<meta content="/assets/logo.png" name="twitter:image" />
<meta content="A collection of popular layouts and patterns made with CSS" property="og:title" />
<meta content="A collection of popular layouts and patterns made with CSS" property="og:description" />
<meta content="article" property="og:type" />
<meta content="https://csslayout.io" property="og:url" />
<meta content="/assets/logo.png" property="og:image" />
<meta content="CSS Layout" property="og:site_name" />
<link rel="icon" href="/assets/favicon.png" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="true" />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?&family=Source+Code+Pro:wght@400&family=Inter:wght@400;700&display=swap"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;

13
pages/index.tsx Normal file
View File

@@ -0,0 +1,13 @@
import * as React from 'react';
import { Layout } from '../layouts/Layout';
const HomePage = () => {
return (
<Layout title="A collection of popular layouts and patterns made with CSS">
</Layout>
);
};
export default HomePage;

5
prettier.config.js Normal file
View File

@@ -0,0 +1,5 @@
module.exports = {
printWidth: 120,
singleQuote: true,
tabWidth: 4,
};

30
styles/_reset.scss Normal file
View File

@@ -0,0 +1,30 @@
body {
-webkit-font-smoothing: antialiased;
color: #333;
font-family: 'Inter', sans-serif;
line-height: 1.5;
margin: 0;
}
* {
box-sizing: border-box;
}
a {
text-decoration: none;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0;
}
img {
max-width: 100%;
}
ol,
ul {
list-style-type: none;
margin: 0;
padding: 0;
}

View File

@@ -0,0 +1,11 @@
/* Footer */
.block-footer {
border-top: 1px solid #e1e1e1;
padding-top: 4rem;
}
.block-footer__copyright {
color: #afafaf;
margin: 2rem 0 4rem 0;
padding: 1rem 0;
text-align: center;
}

View File

@@ -0,0 +1,23 @@
.block-header {
background: #fff;
border-bottom: 1px solid #e4e4e4;
position: sticky;
top: 0;
z-index: 9999;
}
.block-header__inner {
align-items: center;
display: flex;
height: 3rem;
justify-content: space-between;
}
.block-header__cta {
align-items: center;
background-color: var(--mgd-color-primary);
border-radius: 9999px;
color: #fff;
display: flex;
font-weight: 600;
height: 2rem;
padding: 0 1.5rem;
}

View File

@@ -0,0 +1,13 @@
.block-container {
margin-left: auto;
margin-right: auto;
max-width: 64rem;
}
.block-hero {
text-align: center;
}
.block-hero__heading--secondary {
color: #808080;
font-size: 1.25rem;
font-weight: 600;
}

6
styles/index.scss Normal file
View File

@@ -0,0 +1,6 @@
@import './reset';
// Blocks
@import 'blocks/footer';
@import 'blocks/header';
@import 'blocks/layout';

View File

@@ -1,12 +1,32 @@
{
"compilerOptions": {
"outDir": "./dist/",
"esModuleInterop": true,
"sourceMap": true,
"noImplicitAny": true,
"module": "esnext",
"moduleResolution": "node",
"target": "esnext",
"jsx": "react"
}
"compilerOptions": {
"outDir": "./dist/",
"esModuleInterop": true,
"sourceMap": true,
"noImplicitAny": true,
"module": "esnext",
"moduleResolution": "node",
"target": "esnext",
"jsx": "preserve",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"resolveJsonModule": true,
"isolatedModules": true
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
],
"exclude": [
"node_modules"
]
}

View File

@@ -1,78 +0,0 @@
/**
* A collection of popular layouts and patterns made with CSS (https://csslayout.io)
* (c) 2019 - 2021 Nguyen Huu Phuoc <https://twitter.com/nghuuphuoc>
*/
const path = require('path');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const plugins = [
new HtmlWebPackPlugin({
template: './client/index.html',
filename: './index.html',
}),
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
ignoreOrder: false, // Enable to remove warnings about conflicting order
}),
];
if (process.env.NODE_ENV === "analyse") {
plugins.push(new BundleAnalyzerPlugin());
}
module.exports = {
mode: process.env.NODE_ENV,
entry: {
client: './client/index.tsx',
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].[contenthash].js',
// If user browser enables ad blocking, then the pattern likes `Cookie banner` can't be loaded
// In order to fix that, we remove the `[name]` from the bundled output
chunkFilename: '[contenthash].js',
// It's very important
// All the chunk generated by webpack then will be loaded such as
// <script charset="utf-8" src="/[chunk-name].bundle.js"></script>
// The script is accessible from any page that exported by a 3rd party such as react-snap
publicPath: '/',
},
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
'css-loader',
],
},
{
test: /\.ts(x?)$/,
exclude: /node_modules/,
// The order of loaders are very important
// It will make the @loadable/component work
use: ['babel-loader', 'ts-loader'],
},
{
enforce: "pre",
test: /\.js$/,
loader: 'source-map-loader',
},
],
},
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
devtool: process.env.NODE_ENV === 'production' ? false : 'source-map',
devServer: {
contentBase: path.join(__dirname, 'dist'),
historyApiFallback: true,
port: 1234,
},
plugins,
};