Commit 60a93ae7 by Moorthy G

chore: initial setup

parents
{
"presets": ["next/babel"],
"plugins": []
}
{
"path": "cz-conventional-changelog"
}
/node_modules
/build
/.git
/.next
README.md
Dockerfile
*.log
*.log*
.vscode
.DS_Store
.gitignore
.editorconfig
.env
.env.local
.gitlab-ci.yml
.eslintrc.js
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
\ No newline at end of file
NEXT_PUBLIC_API_URL=https://smarten-spaces-testing.eu-staging.kacdn.net
# 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
*.log
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
{
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS --extends @commitlint/config-conventional",
"pre-commit": "pretty-quick --staged"
}
}
{
"jsxBracketSameLine": true,
"singleQuote": true,
"jsxSingleQuote": false,
"trailingComma": "none"
}
const path = require('path');
module.exports = {
core: {
builder: 'webpack5'
},
stories: ['../stories/**/*.stories.@(ts|tsx|js|jsx|mdx)'],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
{
name: '@storybook/preset-scss',
options: {
cssLoaderOptions: {
modules: {
localIdentName: '[local]--[hash:base64:5]'
}
}
}
}
],
webpackFinal: (config) => {
config.resolve = {
...config.resolve,
alias: {
...config.resolve.alias,
'next/link': path.resolve(__dirname, '../stories/__mocks__/link.js'),
'@components': path.resolve(__dirname, '../components'),
'@containers': path.resolve(__dirname, '../containers'),
'@lib': path.resolve(__dirname, '../lib'),
'@styles': path.resolve(__dirname, '../styles')
}
};
return config;
}
};
<!-- Include any tags that should go into document head of each story
For ex: You can use this to include google web font through "link" tag
-->
import '!style-loader!css-loader!sass-loader!@styles/global.scss';
export const parameters = {
options: {
storySort: (a, b) => {
// We want the Welcome story at the top
if (b[1].kind === 'Welcome') {
return 1;
}
// Sort the other stories by ID
// https://github.com/storybookjs/storybook/issues/548#issuecomment-530305279
return a[1].kind === b[1].kind
? 0
: a[1].id.localeCompare(b[1].id, { numeric: true });
}
}
};
# Next.js starter template
## Tools Configured
- Next.js
- React Storybook
- webpack 5
- Commitizen
- Editorconfig
- Prettier
- Husky (to lint commit messages)
## Important Notes
- Install commitizen globally `yarn global add commitizen`
- Then, use `git cz` to commit changes
- Commit messages must follow [angular conventional commit
standards](https://github.com/conventional-changelog/commitlint)
- Install prettier extension in editor. Enable "Format on save" option.
- Install editorconfig extension in editor.
- All files will be formatted using prettier before commit
### Development Server
```bash
yarn dev
```
### Build Task
```bash
yarn build
```
### Production Server
```bash
yarn start
```
### Run Storybook
```bash
yarn storybook
```
### Build Static Storybook
```bash
yarn build-storybook
```
import PropTypes from 'prop-types';
import cn from 'classnames';
import Link from 'next/link';
import styles from './styles.module.scss';
export default function Button({
type = 'primary',
size = 'medium',
block = false,
loading = false,
disabled = false,
href = null,
children,
...rest
}) {
const classNames = cn({
[styles.button]: true,
/** assign styles[type], so that, undefined
* doesn't show up in class names
*/
[styles[type]]: styles[type],
[styles[size]]: styles[size],
[styles.block]: block,
[styles.loading]: loading,
[styles.disabled]: disabled
});
return href !== null ? (
<Link href={href}>
<a className={classNames} {...rest}>
{children}
</a>
</Link>
) : (
<button {...rest} className={classNames}>
{children}
</button>
);
}
Button.propTypes = {
/** Type of the button, link renders <a> tag */
type: PropTypes.oneOf([
'default',
'primary',
'secondary',
'tertiary',
'link'
]),
/** The size of the button */
size: PropTypes.oneOf(['small', 'medium', 'large']),
/** displays the button in full width */
block: PropTypes.bool,
/** Shows loading state of button. It disables interaction */
loading: PropTypes.bool,
/** Disables the button */
disabled: PropTypes.bool,
/** href renders anchor tag with href attribute */
href: PropTypes.string
};
@use '@styles/vars.scss';
.button {
border: none;
color: #19a0f0;
font-size: 0.86em;
padding: 1em 1.8em;
cursor: pointer;
font-weight: bold;
min-width: 13em;
text-align: center;
text-decoration: none;
text-transform: uppercase;
background-color: #fff;
display: inline-block;
vertical-align: top;
position: relative;
user-select: none;
transition: background-color 0.4s, opacity 0.4s, color 0.4s;
box-sizing: border-box;
&.small {
font-size: 0.76em;
padding: 0.8em 0.8em;
}
&.large {
font-size: 1em;
}
&:hover {
background: #19a0f0;
color: #fff;
}
}
.primary {
background-color: #d91c5c;
color: #fff;
&:hover {
background-color: #19a0f0;
}
}
.secondary {
background-color: #19a0f0;
color: #fff;
&:hover {
background-color: #d91c5c;
}
}
.tertiary {
background: #784cdd;
color: #fff;
&:hover {
background: #d91c5c;
color: #fff;
}
}
.link {
padding: 0 1.5em 0 0;
color: vars.$primary;
background-color: transparent;
min-width: auto;
margin-top: 0.5em;
text-align: left;
&.block:before {
transform-origin: center center;
}
&:before {
content: '';
width: 1.7em;
margin-bottom: 0.3em;
height: 1px;
display: block;
background-color: vars.$primary;
transition: transform 0.4s;
transform-origin: left center;
}
&:hover {
background-color: inherit;
color: lighten(vars.$primary, 20%);
}
&:hover:before {
transform: scaleX(1.7);
}
&.disabled {
background-color: transparent;
color: #c0bebe;
&:before {
background-color: #c0bebe;
}
}
}
.loading {
pointer-events: none;
cursor: default;
}
.loading:after {
content: '';
width: 1em;
height: 1em;
vertical-align: middle;
border-radius: 50%;
border: 3px solid #fff;
border-left-color: rgba(0, 0, 0, 0.3);
border-right-color: rgba(0, 0, 0, 0.3);
margin-left: 0.5em;
animation: loading 0.5s linear;
animation-iteration-count: infinite;
position: absolute;
top: 50%;
margin-top: -0.7em;
}
.primary.loading:after,
.secondary.loading:after,
.tertiary.loading:after {
border-left-color: rgba(255, 255, 255, 0.3);
border-right-color: rgba(255, 255, 255, 0.3);
}
@keyframes loading {
100% {
transform: rotate(360deg);
}
}
.button i {
display: none;
}
.link.loading:after {
border-color: lighten(vars.$primary, 20%);
border-left-color: lighten(vars.$primary, 80%);
border-right-color: lighten(vars.$primary, 80%);
}
.block {
display: block;
width: 100%;
}
.block.link {
text-align: center;
}
.block:before {
margin: 0 auto 0.5em;
}
.disabled,
.button[disabled] {
background-color: #e3e3e3;
pointer-events: none;
color: #a3a3a3;
}
import React from 'react';
import Button from '@components/button';
import styles from './styles.module.scss';
export default function PageNotFound() {
return (
<div className={styles.notFound}>
<img src={require('./img/404.png')} alt="" />
<p>The page you're looking for is not found</p>
<Button href="/" onClick={() => sendGA('page-not-found', 'cta')}>
Back to home
</Button>
</div>
);
}
@use '@styles/vars.scss';
.notFound {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 10vh 1em;
box-sizing: border-box;
h2 {
font-size: 10em;
font-weight: 100;
line-height: 0.8;
margin: 0;
color: #1ea7fd;
}
a {
margin-top: 2em;
}
}
@include vars.mQuery(xl) {
.notFound {
font-size: 0.9em;
}
}
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@components/*": ["components/*"],
"@containers/*": ["containers/*"],
"@img/*": ["public/img/*"],
"@lib/*": ["lib/*"],
"@styles/*": ["styles/*"]
},
"experimentalDecorators": true
}
}
module.exports = {
webpack: (config, { isServer }) => {
if (process.env.ANALYZE && !isServer) {
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
config.plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: 'server',
analyzerPort: 8888,
openAnalyzer: true
})
);
}
config.module.rules.push({
test: /\.(png|svg|jpg|jpeg|gif|mp3|mp4)$/i,
type: 'asset/resource',
generator: {
filename: 'static/[name]-[hash:8][ext]'
}
});
return config;
},
images: {
disableStaticImages: true
},
webpack5: true,
async rewrites() {
return [
{
source: '/',
destination: '/home'
}
];
},
env: {
homeUrl: '/home'
},
poweredByHeader: false,
compress: false,
generateEtags: false
};
{
"name": "nextjs-storybook-starter",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"storybook": "start-storybook -s ./public -p 6006",
"build-storybook": "build-storybook",
"analyze": "cross-env ANALYZE=true next build"
},
"dependencies": {
"classnames": "^2.3.1",
"css-loader": "^6.3.0",
"next": "11.1.2",
"next-images": "^1.8.1",
"normalize.css": "^8.0.1",
"react": "17.0.2",
"react-dom": "17.0.2",
"sass": "^1.42.1",
"sass-loader": "^12.1.0",
"sharp": "^0.29.1",
"style-loader": "^3.3.0"
},
"devDependencies": {
"@commitlint/cli": "^13.1.0",
"@commitlint/config-conventional": "^13.1.0",
"@storybook/addon-essentials": "^6.3.8",
"@storybook/addon-links": "^6.3.8",
"@storybook/builder-webpack5": "^6.3.8",
"@storybook/manager-webpack5": "^6.3.8",
"@storybook/preset-scss": "^1.0.3",
"@storybook/react": "^6.3.8",
"add": "^2.0.6",
"babel-loader": "^8.2.2",
"cross-env": "^7.0.3",
"cz-conventional-changelog": "^3.3.0",
"husky": "^7.0.2",
"prettier": "^2.4.1",
"pretty-quick": "^3.1.1",
"webpack-bundle-analyzer": "^4.4.2",
"yarn": "^1.22.11"
}
}
import PageNotFound from '@components/page-not-found';
import '@styles/global.scss';
function MyApp({ Component, pageProps }) {
return pageProps.statusCode === 404 ? (
<PageNotFound />
) : (
<Component {...pageProps} />
);
}
export default MyApp;
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
export default (req, res) => {
res.status(200).json({ name: 'John Doe' })
}
import Head from 'next/head';
import Image from 'next/image';
export default function Home() {
return (
<div className="container">
<Head>
<title>Create Next App</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<center style={{ padding: '2em' }}>
<Image
src={require('../public/img/nextjs.png')}
width="200"
height="120"
alt=""
/>
<h3 style={{ fontWeight: 'normal' }}>Welcome to Next.js App</h3>
</center>
</div>
);
}
import React from 'react';
import { Space, DarkBg } from '../_helpers';
import Button from '@components/button';
export default {
title: 'Basic/Button',
component: Button
};
const Template = ({ type }) => {
return (
<div>
<h6>Size</h6>
<Space>
<Button type={type} size="small">
Small button
</Button>
<Button type={type}>Medium button</Button>
<Button type={type} size="large">
Large button
</Button>
</Space>
<Space>
<Button type={type} href="/" size="small">
Small Anchor
</Button>
<Button type={type} href="/">
Medium Anchor
</Button>
<Button type={type} href="/" size="large">
Large Anchor
</Button>
</Space>
<h6>Loading</h6>
<Space>
<Button type={type} size="small" loading>
Small button
</Button>
<Button type={type} loading>
Medium button
</Button>
<Button type={type} size="large" loading>
Large button
</Button>
</Space>
<Space>
<Button type={type} href="/" size="small" loading>
Small Anchor
</Button>
<Button type={type} href="/" loading>
Medium Anchor
</Button>
<Button type={type} href="/" size="large" loading>
Large Anchor
</Button>
</Space>
<h6>Disabled</h6>
<Space>
<Button type={type} size="small" disabled>
Small button
</Button>
<Button type={type} disabled>
Medium button
</Button>
<Button type={type} size="large" disabled>
Large button
</Button>
</Space>
<h6>Disabled & Loading</h6>
<Space>
<Button type={type} size="small" loading disabled>
Small button
</Button>
<Button type={type} loading disabled>
Medium button
</Button>
<Button type={type} size="large" loading disabled>
Large button
</Button>
</Space>
<h6>Multiline</h6>
<Space>
<Button type={type} size="small">
Lorem ipsum dolor sit <br /> amet consectetur adipisicing elit. <br />{' '}
Quas exercitationem unde voluptate iure dolore laudantium.
</Button>
<Button type={type}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. <br /> Quas
exercitationem unde voluptate iure dolore laudantium.
</Button>
<Button type={type} size="large">
Lorem ipsum dolor sit amet consectetur adipisicing elit. <br /> Quas
exercitationem unde voluptate iure dolore laudantium.
</Button>
</Space>
<br />
<Space>
<Button type={type} size="small" loading>
Lorem ipsum dolor sit <br /> amet consectetur adipisicing elit. <br />{' '}
Quas exercitationem unde voluptate iure dolore laudantium.
</Button>
<Button type={type} loading>
Lorem ipsum dolor sit amet consectetur adipisicing elit. <br /> Quas
exercitationem unde voluptate iure dolore laudantium.
</Button>
<Button type={type} size="large" loading>
Lorem ipsum dolor sit amet consectetur adipisicing elit. <br /> Quas
exercitationem unde voluptate iure dolore laudantium.
</Button>
</Space>
<h6>Block</h6>
<Button type={type} size="small" block>
Small button
</Button>
<br />
<Button type={type} block>
Medium button
</Button>
<br />
<Button type={type} size="large" block>
Large button
</Button>
<br />
<Button type={type} size="small" block loading>
Small button
</Button>
<br />
<Button type={type} block loading>
Medium button
</Button>
<br />
<Button type={type} size="large" block loading>
Large button
</Button>
<br />
<Button type={type} size="small" block loading disabled>
Small button
</Button>
<br />
<Button type={type} block loading disabled>
Medium button
</Button>
<br />
<Button type={type} size="large" block loading disabled>
Small button
</Button>
</div>
);
};
export const Primary = () => <Template type="primary" />;
export const Secondary = () => <Template type="secondary" />;
export const Link = () => <Template type="link" />;
export default {
title: 'Basic/Typography'
};
export const TitleAndParagraph = () => (
<div className="container">
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<h5>Heading 5</h5>
<h6>Heading 6</h6>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Nemo et quae
consequuntur voluptatum quibusdam, autem velit quidem laborum, dignissimos
doloremque ullam eos fugit repellendus maiores eveniet repellat dolor eius
perspiciatis? Lorem ipsum dolor sit amet, consectetur adipisicing elit.
</p>
<p>
Quasi aliquam impedit magnam tempora doloribus voluptatibus, at ea dolores
facilis et quod hic, cumque repellendus quidem expedita explicabo
architecto, possimus minima!
</p>
</div>
);
import React from 'react';
import { NoPadding } from '../_helpers';
import PageNotFound from '@components/page-not-found';
export default {
title: 'Layout/PageNotFound',
component: PageNotFound
};
export const Default = (args) => (
<NoPadding>
<PageNotFound />
</NoPadding>
);
/** Mock for next/link */
export default function ({ children }) {
return children;
}
import { useEffect } from 'react';
export const NoPadding = (props) => {
useEffect(() => {
document.body.style.padding = '0';
return () => (document.body.style.padding = '');
});
return <div {...props} />;
};
export const DarkBg = (props) => {
useEffect(() => {
document.body.style.background = '#333';
document.body.style.color = '#ccc';
return () => {
document.body.style.background = '';
document.body.style.color = '';
};
});
return <>{props.children}</>;
};
export const Space = (props) =>
props.children.map((element) => (
<div style={{ padding: '0.5em', display: 'inline-block' }}>{element}</div>
));
@import '~normalize.css';
@import 'vars.scss';
html,
body {
font-family: Helvetica, Arial, sans-serif;
font-weight: 400;
margin: 0;
padding: 0;
}
a {
color: inherit;
text-decoration: none;
}
html {
font-size: 14px;
font-weight: 300;
height: 100%;
overflow-x: hidden;
@include mQuery(md) {
font-size: 16px;
}
@include mQuery(xl) {
font-size: 18px;
}
@include mQuery(xxl) {
font-size: 20px;
}
}
button:active,
button:focus {
outline: none;
}
h1,
h2,
h3,
h4,
h5,
h6,
p {
margin: 0 0 0.75rem;
}
h1 {
font-size: $titleBaseSize;
}
h2 {
font-size: $titleBaseSize - 0.5;
}
h3 {
font-size: $titleBaseSize - 0.7;
}
h4 {
font-size: $titleBaseSize - 0.9;
}
h5 {
font-size: $titleBaseSize - 1.1;
}
h6 {
font-size: $titleBaseSize - 1.3;
margin-bottom: 0.6em;
}
p {
font-size: 14px;
line-height: 1.6;
margin: 0 0 0.5em 0;
}
.container {
width: $containerWidth;
max-width: $containerMaxWidth;
margin: 0 auto;
}
$primary: #19a0f0;
$secondary: #d91c5c;
$titleBaseSize: 2em;
$containerWidth: 88vw;
$containerMaxWidth: 1400px;
$containerMargin: ($containerWidth - 100) * 0.5;
@mixin mQuery($point) {
$breakpoints: (
sm: 'only screen and (min-width: 540px)',
md: 'only screen and (min-width: 768px)',
lg: 'only screen and (min-width: 992px)',
xl: 'only screen and (min-width: 1200px)',
xxl: 'only screen and (min-width: 1600px)'
);
@if map-has-key($breakpoints, $point) {
$breakpoint: map-get($breakpoints, $point);
@media #{$breakpoint} {
@content;
}
} @else {
@media only screen and #{$point} {
@content;
}
}
}
@mixin scrollbar($light: false) {
&::-webkit-scrollbar {
width: 14px;
height: 18px;
}
&::-webkit-scrollbar-thumb {
height: 1px;
border: 4px solid rgba(0, 0, 0, 0);
background-clip: padding-box;
border-radius: 7px;
@if $light {
background-color: rgba(255, 255, 255, 0.15);
box-shadow: inset -1px -1px 0px rgba(255, 255, 255, 0.05),
inset 1px 1px 0px rgba(255, 255, 255, 0.05);
} @else {
background-color: rgba(0, 0, 0, 0.15);
box-shadow: inset -1px -1px 0px rgba(0, 0, 0, 0.05),
inset 1px 1px 0px rgba(0, 0, 0, 0.05);
}
}
&::-webkit-scrollbar-button {
width: 0;
height: 0;
display: none;
}
&::-webkit-scrollbar-corner {
background-color: transparent;
}
}
@mixin noScrollbar() {
&::-webkit-scrollbar {
width: 0;
height: 0;
display: none;
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment