Merge pull request #57 from devandres-tech/storybook-init
Storybook init
This commit is contained in:
13
.gitignore
vendored
13
.gitignore
vendored
@@ -4,6 +4,9 @@ node_modules
|
|||||||
# Build files
|
# Build files
|
||||||
dist/
|
dist/
|
||||||
|
|
||||||
|
# tests
|
||||||
|
coverage/
|
||||||
|
|
||||||
# Environment varialbes
|
# Environment varialbes
|
||||||
.env
|
.env
|
||||||
|
|
||||||
@@ -18,3 +21,13 @@ npm-debug.log*
|
|||||||
.firebase.json
|
.firebase.json
|
||||||
|
|
||||||
.vercel
|
.vercel
|
||||||
|
|
||||||
|
# OS generated files #
|
||||||
|
######################
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
|||||||
35
.storybook/main.js
Normal file
35
.storybook/main.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||||
|
const custom = require('../webpack.config.js')()
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
|
||||||
|
addons: [
|
||||||
|
'@storybook/addon-links',
|
||||||
|
'@storybook/addon-essentials',
|
||||||
|
'@storybook/addon-interactions',
|
||||||
|
'@storybook/preset-create-react-app',
|
||||||
|
],
|
||||||
|
framework: '@storybook/react',
|
||||||
|
core: {
|
||||||
|
builder: '@storybook/builder-webpack5',
|
||||||
|
},
|
||||||
|
webpackFinal: (config) => {
|
||||||
|
return {
|
||||||
|
...config,
|
||||||
|
module: {
|
||||||
|
...config.module,
|
||||||
|
rules: custom.module.rules, // babel, sass, fonts and images loaders
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
...config.resolve,
|
||||||
|
...custom.resolve, // custom imports resolvers
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new MiniCssExtractPlugin({
|
||||||
|
filename: '[name].[contenthash].css',
|
||||||
|
}),
|
||||||
|
...config.plugins,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
22
.storybook/preview.js
Normal file
22
.storybook/preview.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
export const parameters = {
|
||||||
|
actions: { argTypesRegex: '^on[A-Z].*' },
|
||||||
|
controls: {
|
||||||
|
matchers: {
|
||||||
|
color: /(background|color)$/i,
|
||||||
|
date: /Date$/,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
backgrounds: {
|
||||||
|
default: 'dark',
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
name: 'dark',
|
||||||
|
value: '#141414',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'light',
|
||||||
|
value: '#fff',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -14,7 +14,9 @@ This project is a simplified front end clone of Netflix. It was created with Rea
|
|||||||
- [ ] Create user account page
|
- [ ] Create user account page
|
||||||
- [x] Migrate to Typescript
|
- [x] Migrate to Typescript
|
||||||
- [ ] Implement dynamic code splitting with dynamic imports
|
- [ ] Implement dynamic code splitting with dynamic imports
|
||||||
- [ ] Setup storybook
|
- [x] Setup storybook
|
||||||
|
- [ ] Implement internationalization with react-i18next
|
||||||
|
- [ ] Exclude storybook files from test coverage
|
||||||
|
|
||||||
### Tools used
|
### Tools used
|
||||||
|
|
||||||
|
|||||||
30387
package-lock.json
generated
30387
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
32
package.json
32
package.json
@@ -8,12 +8,16 @@
|
|||||||
"build:prod": "webpack --mode development",
|
"build:prod": "webpack --mode development",
|
||||||
"start:dev": "webpack serve --mode development --config webpack.config.js --open",
|
"start:dev": "webpack serve --mode development --config webpack.config.js --open",
|
||||||
"start:prod": "webpack serve --mode production --open",
|
"start:prod": "webpack serve --mode production --open",
|
||||||
"lint": "eslint --fix . && echo 'Lint complete.'"
|
"lint": "eslint --fix . && echo 'Lint complete.'",
|
||||||
|
"storybook": "start-storybook -p 6006",
|
||||||
|
"build-storybook": "build-storybook",
|
||||||
|
"test": "react-scripts test"
|
||||||
},
|
},
|
||||||
"author": "Andres Alcocer",
|
"author": "Andres Alcocer",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@reduxjs/toolkit": "^1.9.0",
|
"@reduxjs/toolkit": "^1.9.0",
|
||||||
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@types/jest": "^29.2.3",
|
"@types/jest": "^29.2.3",
|
||||||
"@types/node": "^18.11.9",
|
"@types/node": "^18.11.9",
|
||||||
"@types/react": "^18.0.25",
|
"@types/react": "^18.0.25",
|
||||||
@@ -45,7 +49,19 @@
|
|||||||
"@babel/polyfill": "^7.0.0-beta.51",
|
"@babel/polyfill": "^7.0.0-beta.51",
|
||||||
"@babel/preset-env": "^7.20.2",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@babel/preset-react": "^7.18.6",
|
||||||
|
"@storybook/addon-actions": "^6.5.13",
|
||||||
|
"@storybook/addon-essentials": "^6.5.13",
|
||||||
|
"@storybook/addon-interactions": "^6.5.13",
|
||||||
|
"@storybook/addon-links": "^6.5.13",
|
||||||
|
"@storybook/builder-webpack5": "^6.5.13",
|
||||||
|
"@storybook/manager-webpack5": "^6.5.13",
|
||||||
|
"@storybook/node-logger": "^6.5.13",
|
||||||
|
"@storybook/preset-create-react-app": "^4.1.2",
|
||||||
|
"@storybook/react": "^6.5.13",
|
||||||
|
"@storybook/testing-library": "^0.0.13",
|
||||||
|
"@testing-library/react": "^13.4.0",
|
||||||
"babel-loader": "^9.1.0",
|
"babel-loader": "^9.1.0",
|
||||||
|
"babel-plugin-named-exports-order": "^0.0.2",
|
||||||
"clean-webpack-plugin": "^4.0.0",
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
"copy-webpack-plugin": "^11.0.0",
|
"copy-webpack-plugin": "^11.0.0",
|
||||||
"css-loader": "^6.7.2",
|
"css-loader": "^6.7.2",
|
||||||
@@ -62,7 +78,7 @@
|
|||||||
"html-loader": "^4.2.0",
|
"html-loader": "^4.2.0",
|
||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"image-webpack-loader": "^8.1.0",
|
"image-webpack-loader": "^8.1.0",
|
||||||
"mini-css-extract-plugin": "^2.7.0",
|
"mini-css-extract-plugin": "^1.3.6",
|
||||||
"node-sass": "^8.0.0",
|
"node-sass": "^8.0.0",
|
||||||
"prettier": "^2.8.0",
|
"prettier": "^2.8.0",
|
||||||
"sass-loader": "^13.2.0",
|
"sass-loader": "^13.2.0",
|
||||||
@@ -75,5 +91,17 @@
|
|||||||
"webpack": "^5.75.0",
|
"webpack": "^5.75.0",
|
||||||
"webpack-cli": "^5.0.0",
|
"webpack-cli": "^5.0.0",
|
||||||
"webpack-dev-server": "^4.11.1"
|
"webpack-dev-server": "^4.11.1"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"**/*.stories.*"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"import/no-anonymous-default-export": "off"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
42
src/components/Button/Button.tsx
Normal file
42
src/components/Button/Button.tsx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import './button.scss'
|
||||||
|
|
||||||
|
export enum ButtonType {
|
||||||
|
Primary,
|
||||||
|
Secondary,
|
||||||
|
IconRound,
|
||||||
|
IconRoundSecondary,
|
||||||
|
Alternate,
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IButton {
|
||||||
|
label?: string
|
||||||
|
onClick?: () => void
|
||||||
|
buttonType: ButtonType
|
||||||
|
Icon?: JSX.Element
|
||||||
|
}
|
||||||
|
|
||||||
|
const Button = ({ label, onClick, buttonType, Icon }: IButton) => {
|
||||||
|
const getIconClassName = (): '' | ' with-icon' => {
|
||||||
|
return Icon ? ' with-icon' : ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const getLabelClassName = (): '' | ' with-label' => {
|
||||||
|
return label ? ' with-label' : ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPrimaryClassName = (): string => {
|
||||||
|
return ButtonType[buttonType ? buttonType : ButtonType.Primary]
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className={`n-button${getIconClassName()}${getLabelClassName()} ${getPrimaryClassName()}`}
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
|
{Icon && Icon}
|
||||||
|
{label && <span>{label}</span>}
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Button
|
||||||
73
src/components/Button/__tests__/Button.stories.tsx
Normal file
73
src/components/Button/__tests__/Button.stories.tsx
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { ComponentStory, ComponentMeta } from '@storybook/react'
|
||||||
|
|
||||||
|
import Button from '../Button'
|
||||||
|
import { ButtonType } from '../Button'
|
||||||
|
import PlayLogo from '../../../static/images/play-button.svg'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Button',
|
||||||
|
component: Button,
|
||||||
|
parameters: {
|
||||||
|
parameters: {
|
||||||
|
backgrounds: {
|
||||||
|
default: '#141414',
|
||||||
|
values: [
|
||||||
|
{ name: 'dark', value: '#141414' },
|
||||||
|
{ name: 'light', value: '#fff' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
docs: {
|
||||||
|
description: {
|
||||||
|
component: 'Primary and secondary styles for all buttons',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as ComponentMeta<typeof Button>
|
||||||
|
|
||||||
|
const Template: ComponentStory<typeof Button> = (args) => <Button {...args} />
|
||||||
|
|
||||||
|
export const Primary = Template.bind({})
|
||||||
|
Primary.args = {
|
||||||
|
label: 'Primary',
|
||||||
|
buttonType: ButtonType.Primary,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Secondary = Template.bind({})
|
||||||
|
Secondary.args = {
|
||||||
|
label: 'Secondary',
|
||||||
|
buttonType: ButtonType.Secondary,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Alternate = Template.bind({})
|
||||||
|
Alternate.args = {
|
||||||
|
label: 'Alternate',
|
||||||
|
buttonType: ButtonType.Alternate,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const IconRound = Template.bind({})
|
||||||
|
IconRound.args = {
|
||||||
|
Icon: <PlayLogo />,
|
||||||
|
buttonType: ButtonType.IconRound,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const IconRoundSecondary = Template.bind({})
|
||||||
|
IconRoundSecondary.args = {
|
||||||
|
Icon: <PlayLogo />,
|
||||||
|
buttonType: ButtonType.IconRoundSecondary,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PrimaryWithIcon = Template.bind({})
|
||||||
|
PrimaryWithIcon.args = {
|
||||||
|
label: 'Primary Ic',
|
||||||
|
buttonType: ButtonType.Primary,
|
||||||
|
Icon: <PlayLogo />,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SecondaryWithIcon = Template.bind({})
|
||||||
|
SecondaryWithIcon.args = {
|
||||||
|
label: 'Secondary Ic',
|
||||||
|
buttonType: ButtonType.Secondary,
|
||||||
|
Icon: <PlayLogo />,
|
||||||
|
}
|
||||||
51
src/components/Button/__tests__/Button.test.tsx
Normal file
51
src/components/Button/__tests__/Button.test.tsx
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import {
|
||||||
|
Primary,
|
||||||
|
Secondary,
|
||||||
|
IconRound,
|
||||||
|
PrimaryWithIcon,
|
||||||
|
SecondaryWithIcon,
|
||||||
|
Alternate,
|
||||||
|
IconRoundSecondary,
|
||||||
|
} from './Button.stories'
|
||||||
|
import { render } from '@testing-library/react'
|
||||||
|
|
||||||
|
describe('Button constructor', (): void => {
|
||||||
|
test('should render primary button', (): void => {
|
||||||
|
const { container } = render(<Primary {...Primary.args} />)
|
||||||
|
expect(container).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should render primary button with icon', (): void => {
|
||||||
|
const { container } = render(<PrimaryWithIcon {...PrimaryWithIcon.args} />)
|
||||||
|
expect(container).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should render secondary button', (): void => {
|
||||||
|
const { container } = render(<Secondary {...Secondary.args} />)
|
||||||
|
expect(container).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should render secondary button with icon', (): void => {
|
||||||
|
const { container } = render(
|
||||||
|
<SecondaryWithIcon {...SecondaryWithIcon.args} />
|
||||||
|
)
|
||||||
|
expect(container).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should render icon round button', (): void => {
|
||||||
|
const { container } = render(<IconRound {...IconRound.args} />)
|
||||||
|
expect(container).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should render secondary icon round button', (): void => {
|
||||||
|
const { container } = render(
|
||||||
|
<IconRoundSecondary {...IconRoundSecondary.args} />
|
||||||
|
)
|
||||||
|
expect(container).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should render alternate button', (): void => {
|
||||||
|
const { container } = render(<Alternate {...Alternate.args} />)
|
||||||
|
expect(container).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`Button constructor should render alternate button 1`] = `
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
class="n-button with-label Alternate"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
Alternate
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Button constructor should render icon round button 1`] = `
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
class="n-button with-icon IconRound"
|
||||||
|
>
|
||||||
|
<play-button.svg />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Button constructor should render primary button 1`] = `
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
class="n-button with-label Primary"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
Primary
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Button constructor should render primary button with icon 1`] = `
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
class="n-button with-icon with-label Primary"
|
||||||
|
>
|
||||||
|
<play-button.svg />
|
||||||
|
<span>
|
||||||
|
Primary Ic
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Button constructor should render secondary button 1`] = `
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
class="n-button with-label Secondary"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
Secondary
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Button constructor should render secondary button with icon 1`] = `
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
class="n-button with-icon with-label Secondary"
|
||||||
|
>
|
||||||
|
<play-button.svg />
|
||||||
|
<span>
|
||||||
|
Secondary Ic
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Button constructor should render secondary icon round button 1`] = `
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
class="n-button with-icon IconRoundSecondary"
|
||||||
|
>
|
||||||
|
<play-button.svg />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
167
src/components/Button/button.scss
Normal file
167
src/components/Button/button.scss
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
@import '../../static/sass/abstracts/functions';
|
||||||
|
|
||||||
|
.n-button {
|
||||||
|
cursor: pointer;
|
||||||
|
outline: none;
|
||||||
|
appearance: none;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0.8rem;
|
||||||
|
opacity: 1;
|
||||||
|
user-select: none;
|
||||||
|
will-change: background-color, color;
|
||||||
|
word-break: break-word;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 17px;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 2.4rem;
|
||||||
|
font-family: 'Netflix Sans', 'Helvetica Neue', 'Segoe UI', 'Roboto', 'Ubuntu',
|
||||||
|
'sans-serif';
|
||||||
|
|
||||||
|
@include responsive(phone) {
|
||||||
|
top: 24rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.with-icon {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
height: 24px;
|
||||||
|
fill: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.with-label {
|
||||||
|
padding-left: 2.4rem;
|
||||||
|
padding-right: 2.8rem;
|
||||||
|
|
||||||
|
& > span {
|
||||||
|
margin-left: 1rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.Primary {
|
||||||
|
color: #000;
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
fill: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:disabled):hover {
|
||||||
|
background-color: rgba(255, 255, 255, 0.75);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:disabled):active {
|
||||||
|
background-color: rgba(255, 255, 255, 0.5);
|
||||||
|
color: rgba(0, 0, 0, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:disabled):focus::before {
|
||||||
|
box-sizing: content-box;
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
border: 2px solid white;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 2px;
|
||||||
|
position: absolute;
|
||||||
|
left: -4px;
|
||||||
|
top: -4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.Secondary {
|
||||||
|
background-color: rgba(109, 109, 110, 0.7);
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&:not(:disabled):hover {
|
||||||
|
background-color: rgba(109, 109, 110, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:disabled):active {
|
||||||
|
background-color: rgba(109, 109, 110, 0.4);
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:disabled):focus::before {
|
||||||
|
box-sizing: content-box;
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
border: 2px solid white;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 2px;
|
||||||
|
position: absolute;
|
||||||
|
left: -4px;
|
||||||
|
top: -4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.Alternate {
|
||||||
|
background-color: #d22f27;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.IconRound,
|
||||||
|
&.IconRoundSecondary {
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
height: 42px;
|
||||||
|
width: 42px;
|
||||||
|
border: 2px solid rgba(255, 255, 255, 0.7);
|
||||||
|
color: white;
|
||||||
|
background-color: rgba(42, 42, 42, 0.6);
|
||||||
|
border-color: hsla(0, 0%, 100%, 0.5);
|
||||||
|
border-width: 2px;
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
fill: #fff;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.with-label):hover {
|
||||||
|
background-color: #2a2a2a;
|
||||||
|
border-color: #fff;
|
||||||
|
border-width: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.with-label):focus {
|
||||||
|
background-color: #2a2a2a;
|
||||||
|
border: 2px solid white;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:disabled):focus::before {
|
||||||
|
box-sizing: content-box;
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
border: 2px solid white;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 2px;
|
||||||
|
position: absolute;
|
||||||
|
left: -4px;
|
||||||
|
top: -4px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.IconRoundSecondary {
|
||||||
|
background-color: #fff;
|
||||||
|
& > * {
|
||||||
|
fill: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.with-label):hover {
|
||||||
|
background-color: #e3e3e3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,6 @@ const footer = () => (
|
|||||||
className='footer__copyright--link'
|
className='footer__copyright--link'
|
||||||
href='https://github.com/devandres-tech'
|
href='https://github.com/devandres-tech'
|
||||||
>
|
>
|
||||||
{' '}
|
|
||||||
Dev Andres
|
Dev Andres
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
|
|
||||||
import PlayLogo from '../static/images/play-button.svg'
|
import PlayLogo from '../static/images/play-button.svg'
|
||||||
import AddLogo from '../static/images/add.svg'
|
import { ButtonType } from './Button/Button'
|
||||||
|
import Button from './Button/Button'
|
||||||
|
import MoreInfo from '../static/images/more-info.svg'
|
||||||
import MuteIcon from '../static/images/mute.svg'
|
import MuteIcon from '../static/images/mute.svg'
|
||||||
import UnmuteIcon from '../static/images/unmute.svg'
|
import UnmuteIcon from '../static/images/unmute.svg'
|
||||||
import ReactPlayer from 'react-player'
|
import ReactPlayer from 'react-player'
|
||||||
@@ -27,17 +29,18 @@ const Header = ({ name, overview }: IHeader) => {
|
|||||||
url='https://vimeo.com/384025132'
|
url='https://vimeo.com/384025132'
|
||||||
/>
|
/>
|
||||||
<h1 className='header__container-heading'>{name}</h1>
|
<h1 className='header__container-heading'>{name}</h1>
|
||||||
<button
|
<Button
|
||||||
|
Icon={<PlayLogo />}
|
||||||
|
buttonType={ButtonType.Primary}
|
||||||
onClick={() => alert('not a movie!')}
|
onClick={() => alert('not a movie!')}
|
||||||
className='header__container-btnPlay'
|
label={'Play'}
|
||||||
>
|
/>
|
||||||
<PlayLogo className='header__container-btnMyList-play' />
|
<Button
|
||||||
Play
|
Icon={<MoreInfo />}
|
||||||
</button>
|
buttonType={ButtonType.Secondary}
|
||||||
<button className='header__container-btnMyList'>
|
label={'More Info'}
|
||||||
<AddLogo className='header__container-btnMyList-add' />
|
/>
|
||||||
My List
|
|
||||||
</button>
|
|
||||||
{isMuted ? (
|
{isMuted ? (
|
||||||
<MuteIcon
|
<MuteIcon
|
||||||
onClick={() => setIsMuted(false)}
|
onClick={() => setIsMuted(false)}
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ import { NavLink } from 'react-router-dom'
|
|||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
import { useScroll } from '../hooks/useScroll'
|
import { useScroll } from '../hooks/useScroll'
|
||||||
import SearchLogo from '../static/images/search-icon.svg'
|
import Search from '../static/images/search-icon.svg'
|
||||||
import NetflixLogo from '../static/images/Netflix_Logo_RGB.png'
|
import NetflixLogo from '../static/images/Netflix_Logo_RGB.png'
|
||||||
|
import AddLogo from '../static/images/add.svg'
|
||||||
import BellLogo from '../static/images/bell-logo.svg'
|
import BellLogo from '../static/images/bell-logo.svg'
|
||||||
import DropdownArrow from '../static/images/drop-down-arrow.svg'
|
import DropdownArrow from '../static/images/drop-down-arrow.svg'
|
||||||
import DropdownContent from './DropdownContent'
|
import DropdownContent from './DropdownContent'
|
||||||
@@ -52,9 +53,8 @@ const Navbar = () => {
|
|||||||
Recently Added
|
Recently Added
|
||||||
</div>
|
</div>
|
||||||
<div className='navigation__container-link pseudo-link'>My List</div>
|
<div className='navigation__container-link pseudo-link'>My List</div>
|
||||||
|
|
||||||
<div className='navigation__container--left'>
|
<div className='navigation__container--left'>
|
||||||
<SearchLogo className='logo' />
|
<Search className='logo' />
|
||||||
<input
|
<input
|
||||||
ref={searchInput}
|
ref={searchInput}
|
||||||
value={userInput}
|
value={userInput}
|
||||||
@@ -64,7 +64,6 @@ const Navbar = () => {
|
|||||||
placeholder='Title, genres, people'
|
placeholder='Title, genres, people'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='navigation__container-link pseudo-link'>KIDS</div>
|
<div className='navigation__container-link pseudo-link'>KIDS</div>
|
||||||
<div className='navigation__container-link pseudo-link'>DVD</div>
|
<div className='navigation__container-link pseudo-link'>DVD</div>
|
||||||
<BellLogo className='navigation__container--bellLogo' />
|
<BellLogo className='navigation__container--bellLogo' />
|
||||||
|
|||||||
BIN
src/fonts/NetflixSans_W_Bd.woff2
Normal file
BIN
src/fonts/NetflixSans_W_Bd.woff2
Normal file
Binary file not shown.
BIN
src/fonts/NetflixSans_W_Md.woff2
Normal file
BIN
src/fonts/NetflixSans_W_Md.woff2
Normal file
Binary file not shown.
BIN
src/fonts/NetflixSans_W_Rg.woff2
Normal file
BIN
src/fonts/NetflixSans_W_Rg.woff2
Normal file
Binary file not shown.
1
src/static/images/add-round.svg
Normal file
1
src/static/images/add-round.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="Hawkins-Icon Hawkins-Icon-Standard"><path fill-rule="evenodd" clip-rule="evenodd" d="M11 2V11H2V13H11V22H13V13H22V11H13V2H11Z" fill="currentColor"></path></svg>
|
||||||
|
After Width: | Height: | Size: 263 B |
1
src/static/images/more-info.svg
Normal file
1
src/static/images/more-info.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="Hawkins-Icon Hawkins-Icon-Standard"><path fill-rule="evenodd" clip-rule="evenodd" d="M12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3ZM1 12C1 5.92487 5.92487 1 12 1C18.0751 1 23 5.92487 23 12C23 18.0751 18.0751 23 12 23C5.92487 23 1 18.0751 1 12ZM13 10V18H11V10H13ZM12 8.5C12.8284 8.5 13.5 7.82843 13.5 7C13.5 6.17157 12.8284 5.5 12 5.5C11.1716 5.5 10.5 6.17157 10.5 7C10.5 7.82843 11.1716 8.5 12 8.5Z" fill="currentColor"></path></svg>
|
||||||
|
After Width: | Height: | Size: 602 B |
@@ -1,38 +1 @@
|
|||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="Hawkins-Icon Hawkins-Icon-Standard"><path d="M4 2.69127C4 1.93067 4.81547 1.44851 5.48192 1.81506L22.4069 11.1238C23.0977 11.5037 23.0977 12.4963 22.4069 12.8762L5.48192 22.1849C4.81546 22.5515 4 22.0693 4 21.3087V2.69127Z" fill="currentColor"></path></svg>
|
||||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 41.999 41.999" style="enable-background:new 0 0 41.999 41.999;" xml:space="preserve">
|
|
||||||
<path d="M36.068,20.176l-29-20C6.761-0.035,6.363-0.057,6.035,0.114C5.706,0.287,5.5,0.627,5.5,0.999v40
|
|
||||||
c0,0.372,0.206,0.713,0.535,0.886c0.146,0.076,0.306,0.114,0.465,0.114c0.199,0,0.397-0.06,0.568-0.177l29-20
|
|
||||||
c0.271-0.187,0.432-0.494,0.432-0.823S36.338,20.363,36.068,20.176z"/>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 824 B After Width: | Height: | Size: 361 B |
@@ -1,12 +1,2 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<svg width="251px" height="251px" viewBox="0 0 251 251" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="search-icon"><path fill-rule="evenodd" clip-rule="evenodd" d="M14 11C14 14.3137 11.3137 17 8 17C4.68629 17 2 14.3137 2 11C2 7.68629 4.68629 5 8 5C11.3137 5 14 7.68629 14 11ZM14.3623 15.8506C12.9006 17.7649 10.5945 19 8 19C3.58172 19 0 15.4183 0 11C0 6.58172 3.58172 3 8 3C12.4183 3 16 6.58172 16 11C16 12.1076 15.7749 13.1626 15.368 14.1218L24.0022 19.1352L22.9979 20.8648L14.3623 15.8506Z" fill="currentColor"></path></svg>
|
||||||
<!-- Generator: Sketch 49.3 (51167) - http://www.bohemiancoding.com/sketch -->
|
|
||||||
<title>Slice 1</title>
|
|
||||||
<desc>Created with Sketch.</desc>
|
|
||||||
<defs></defs>
|
|
||||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
||||||
<g id="musica-searcher" fill="#FFFFFF" fill-rule="nonzero">
|
|
||||||
<path d="M244.186,214.604 L189.807,160.226 C189.518,159.937 189.179,159.735 188.877,159.466 C199.577,143.235 205.822,123.806 205.822,102.912 C205.822,46.075 159.747,0 102.911,0 C46.075,0 0,46.075 0,102.911 C0,159.746 46.074,205.822 102.91,205.822 C123.805,205.822 143.233,199.577 159.464,188.877 C159.733,189.178 159.934,189.517 160.223,189.806 L214.603,244.186 C222.772,252.354 236.016,252.354 244.186,244.186 C252.354,236.017 252.354,222.773 244.186,214.604 Z M102.911,170.146 C65.777,170.146 35.675,140.044 35.675,102.911 C35.675,65.777 65.778,35.675 102.911,35.675 C140.043,35.675 170.146,65.778 170.146,102.911 C170.146,140.044 140.043,170.146 102.911,170.146 Z" id="Shape"></path>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 566 B |
@@ -123,9 +123,15 @@
|
|||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
}
|
}
|
||||||
|
// prettier-ignore
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Netflix Sans';
|
||||||
|
src: url('../../../fonts/NetflixSans_W_Rg.woff2') format('woff2'), url('../../../fonts/NetflixSans_W_Md.woff2') format('woff2'), url('../../../fonts/NetflixSans_W_Bd.woff2') format('woff2');
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'Hind', sans-serif;
|
font-family: 'Netflix Sans', 'Helvetica Neue', 'Segoe UI', 'Roboto', 'Ubuntu',
|
||||||
|
'sans-serif';
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
background-color: $color-background;
|
background-color: $color-background;
|
||||||
}
|
}
|
||||||
@@ -133,6 +139,7 @@ body {
|
|||||||
html {
|
html {
|
||||||
// this defines what 1rem is --> font root size
|
// this defines what 1rem is --> font root size
|
||||||
font-size: 62.5%; // 10/16, 1rem = 10px;
|
font-size: 62.5%; // 10/16, 1rem = 10px;
|
||||||
|
// font-weight: bold;
|
||||||
|
|
||||||
@include responsive(tab_port) {
|
@include responsive(tab_port) {
|
||||||
font-size: 50%;
|
font-size: 50%;
|
||||||
|
|||||||
@@ -3,6 +3,28 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
padding-top: 56.25%;
|
padding-top: 56.25%;
|
||||||
|
|
||||||
|
& > button.Primary,
|
||||||
|
button.Secondary {
|
||||||
|
top: 40rem;
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
@include responsive(phone) {
|
||||||
|
top: 24rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& > button.Primary {
|
||||||
|
left: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > button.Secondary {
|
||||||
|
left: 17rem;
|
||||||
|
|
||||||
|
@include responsive(tab_port) {
|
||||||
|
left: 18.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@include responsive(phone) {
|
@include responsive(phone) {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
height: 32rem;
|
height: 32rem;
|
||||||
@@ -34,64 +56,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-btnPlay,
|
|
||||||
&-btnMyList {
|
|
||||||
top: 40rem;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 1.6rem;
|
|
||||||
color: #fff;
|
|
||||||
outline: none;
|
|
||||||
border: none;
|
|
||||||
font-weight: 700;
|
|
||||||
border-radius: 5px;
|
|
||||||
padding-left: 3.5rem;
|
|
||||||
padding-right: 3.5rem;
|
|
||||||
margin-right: 1rem;
|
|
||||||
padding-top: 1rem;
|
|
||||||
background-color: rgba(112, 111, 111, 0.5);
|
|
||||||
padding-bottom: 1rem;
|
|
||||||
|
|
||||||
@include responsive(phone) {
|
|
||||||
top: 24rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-add {
|
|
||||||
width: 15px;
|
|
||||||
height: 15px;
|
|
||||||
fill: #fff;
|
|
||||||
margin-right: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-play {
|
|
||||||
width: 15px;
|
|
||||||
height: 15px;
|
|
||||||
fill: #fff;
|
|
||||||
margin-right: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-btnPlay {
|
|
||||||
color: #000;
|
|
||||||
background-color: #e6e6e6;
|
|
||||||
transition: all 0.2s;
|
|
||||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
|
|
||||||
|
|
||||||
& > * {
|
|
||||||
fill: #000;
|
|
||||||
}
|
|
||||||
left: 4rem;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-btnMyList {
|
|
||||||
left: 18.5rem;
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgb(37, 37, 37);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-btnVolume {
|
&-btnVolume {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
|
|||||||
@@ -35,7 +35,6 @@
|
|||||||
&--bellLogo {
|
&--bellLogo {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
height: 2.2rem;
|
height: 2.2rem;
|
||||||
fill: red;
|
|
||||||
width: 2.2rem;
|
width: 2.2rem;
|
||||||
padding-right: 2.5rem;
|
padding-right: 2.5rem;
|
||||||
|
|
||||||
@@ -109,13 +108,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-link {
|
&-link {
|
||||||
font-weight: 500;
|
|
||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
color: rgb(221, 221, 221);
|
color: rgb(221, 221, 221);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
margin-right: 2rem;
|
margin-right: 2rem;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
|
|
||||||
|
@media screen and (min-width: 1200px) {
|
||||||
|
.pinning-header .main-header {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
padding-right: 2.6rem;
|
padding-right: 2.6rem;
|
||||||
}
|
}
|
||||||
@@ -162,8 +166,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
width: 1.8rem;
|
position: relative;
|
||||||
height: 1.8rem;
|
left: 10px;
|
||||||
|
bottom: 4px;
|
||||||
transform: translateX(2.4rem) translateY(1rem);
|
transform: translateX(2.4rem) translateY(1rem);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
@@ -171,7 +176,6 @@
|
|||||||
.dropdownContent {
|
.dropdownContent {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
// align-items: center;
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
||||||
color: #fff;
|
color: #fff;
|
||||||
@@ -196,7 +200,6 @@
|
|||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-bottom: 1px solid #fff;
|
border-bottom: 1px solid #fff;
|
||||||
// border-width: 2%;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"module": "es6",
|
"module": "es6",
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"jsx": "react",
|
"jsx": "react-jsx",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
|
|||||||
@@ -2,14 +2,13 @@ const HtmlWebPackPlugin = require('html-webpack-plugin')
|
|||||||
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
||||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||||
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
|
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
|
||||||
const TerserPlugin = require('terser-webpack-plugin')
|
|
||||||
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
|
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
|
||||||
const dotenv = require('dotenv')
|
const dotenv = require('dotenv')
|
||||||
const webpack = require('webpack')
|
const webpack = require('webpack')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
const prod =
|
const prod =
|
||||||
(process.env.NODE_ENV ? process.env.NODE_ENV : '').trim() === 'production'
|
(process.env.NODE_ENV ? process.env.NODE_ENV : '').trim() === 'production'
|
||||||
const path = require('path')
|
|
||||||
|
|
||||||
module.exports = () => {
|
module.exports = () => {
|
||||||
dotenv.config({
|
dotenv.config({
|
||||||
@@ -21,10 +20,11 @@ module.exports = () => {
|
|||||||
output: {
|
output: {
|
||||||
filename: '[name].[contenthash].js',
|
filename: '[name].[contenthash].js',
|
||||||
path: path.resolve(__dirname, 'dist'),
|
path: path.resolve(__dirname, 'dist'),
|
||||||
|
assetModuleFilename: 'assets/[name][ext]',
|
||||||
clean: true,
|
clean: true,
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.tsx', '.ts', '.js'],
|
extensions: ['.js', '.ts', '.tsx'],
|
||||||
},
|
},
|
||||||
optimization: {
|
optimization: {
|
||||||
runtimeChunk: 'single',
|
runtimeChunk: 'single',
|
||||||
@@ -67,7 +67,15 @@ module.exports = () => {
|
|||||||
patterns: [
|
patterns: [
|
||||||
{
|
{
|
||||||
from: 'src/static/images',
|
from: 'src/static/images',
|
||||||
to: 'static/images',
|
to: 'resources/',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
new CopyWebpackPlugin({
|
||||||
|
patterns: [
|
||||||
|
{
|
||||||
|
from: 'src/fonts',
|
||||||
|
to: 'fonts/',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
@@ -93,24 +101,17 @@ module.exports = () => {
|
|||||||
{
|
{
|
||||||
test: /\.svg$/,
|
test: /\.svg$/,
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
use: {
|
use: ['@svgr/webpack'],
|
||||||
loader: 'svg-react-loader',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.css$/i,
|
test: /\.(sass|less|css|scss)$/,
|
||||||
use: [MiniCssExtractPlugin.loader, 'css-loader'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.scss$/,
|
|
||||||
use: [
|
use: [
|
||||||
{
|
// fallback to style-loader in development
|
||||||
loader: MiniCssExtractPlugin.loader,
|
process.env.NODE_ENV !== 'production'
|
||||||
options: {
|
? 'style-loader'
|
||||||
publicPath: '../',
|
: MiniCssExtractPlugin.loader,
|
||||||
},
|
|
||||||
},
|
|
||||||
'css-loader',
|
'css-loader',
|
||||||
|
'resolve-url-loader',
|
||||||
'sass-loader',
|
'sass-loader',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -127,6 +128,13 @@ module.exports = () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
test: /\.(woff|woff2|eot|ttf|otf)$/,
|
||||||
|
type: 'asset/resource',
|
||||||
|
generator: {
|
||||||
|
filename: './fonts/[name][ext]',
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user