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
|
||||
dist/
|
||||
|
||||
# tests
|
||||
coverage/
|
||||
|
||||
# Environment varialbes
|
||||
.env
|
||||
|
||||
@@ -18,3 +21,13 @@ npm-debug.log*
|
||||
.firebase.json
|
||||
|
||||
.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
|
||||
- [x] Migrate to Typescript
|
||||
- [ ] 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
|
||||
|
||||
|
||||
30375
package-lock.json
generated
30375
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",
|
||||
"start:dev": "webpack serve --mode development --config webpack.config.js --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",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@reduxjs/toolkit": "^1.9.0",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@types/jest": "^29.2.3",
|
||||
"@types/node": "^18.11.9",
|
||||
"@types/react": "^18.0.25",
|
||||
@@ -45,7 +49,19 @@
|
||||
"@babel/polyfill": "^7.0.0-beta.51",
|
||||
"@babel/preset-env": "^7.20.2",
|
||||
"@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-plugin-named-exports-order": "^0.0.2",
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"css-loader": "^6.7.2",
|
||||
@@ -62,7 +78,7 @@
|
||||
"html-loader": "^4.2.0",
|
||||
"html-webpack-plugin": "^5.5.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",
|
||||
"prettier": "^2.8.0",
|
||||
"sass-loader": "^13.2.0",
|
||||
@@ -75,5 +91,17 @@
|
||||
"webpack": "^5.75.0",
|
||||
"webpack-cli": "^5.0.0",
|
||||
"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'
|
||||
href='https://github.com/devandres-tech'
|
||||
>
|
||||
{' '}
|
||||
Dev Andres
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import React, { useState } from 'react'
|
||||
|
||||
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 UnmuteIcon from '../static/images/unmute.svg'
|
||||
import ReactPlayer from 'react-player'
|
||||
@@ -27,17 +29,18 @@ const Header = ({ name, overview }: IHeader) => {
|
||||
url='https://vimeo.com/384025132'
|
||||
/>
|
||||
<h1 className='header__container-heading'>{name}</h1>
|
||||
<button
|
||||
<Button
|
||||
Icon={<PlayLogo />}
|
||||
buttonType={ButtonType.Primary}
|
||||
onClick={() => alert('not a movie!')}
|
||||
className='header__container-btnPlay'
|
||||
>
|
||||
<PlayLogo className='header__container-btnMyList-play' />
|
||||
Play
|
||||
</button>
|
||||
<button className='header__container-btnMyList'>
|
||||
<AddLogo className='header__container-btnMyList-add' />
|
||||
My List
|
||||
</button>
|
||||
label={'Play'}
|
||||
/>
|
||||
<Button
|
||||
Icon={<MoreInfo />}
|
||||
buttonType={ButtonType.Secondary}
|
||||
label={'More Info'}
|
||||
/>
|
||||
|
||||
{isMuted ? (
|
||||
<MuteIcon
|
||||
onClick={() => setIsMuted(false)}
|
||||
|
||||
@@ -3,8 +3,9 @@ import { NavLink } from 'react-router-dom'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
|
||||
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 AddLogo from '../static/images/add.svg'
|
||||
import BellLogo from '../static/images/bell-logo.svg'
|
||||
import DropdownArrow from '../static/images/drop-down-arrow.svg'
|
||||
import DropdownContent from './DropdownContent'
|
||||
@@ -52,9 +53,8 @@ const Navbar = () => {
|
||||
Recently Added
|
||||
</div>
|
||||
<div className='navigation__container-link pseudo-link'>My List</div>
|
||||
|
||||
<div className='navigation__container--left'>
|
||||
<SearchLogo className='logo' />
|
||||
<Search className='logo' />
|
||||
<input
|
||||
ref={searchInput}
|
||||
value={userInput}
|
||||
@@ -64,7 +64,6 @@ const Navbar = () => {
|
||||
placeholder='Title, genres, people'
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='navigation__container-link pseudo-link'>KIDS</div>
|
||||
<div className='navigation__container-link pseudo-link'>DVD</div>
|
||||
<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"?>
|
||||
<!-- 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>
|
||||
<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>
|
||||
|
||||
|
Before Width: | Height: | Size: 824 B After Width: | Height: | Size: 361 B |
@@ -1,12 +1,2 @@
|
||||
<?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">
|
||||
<!-- 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>
|
||||
<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>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 566 B |
@@ -123,9 +123,15 @@
|
||||
border-collapse: collapse;
|
||||
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 {
|
||||
font-family: 'Hind', sans-serif;
|
||||
font-family: 'Netflix Sans', 'Helvetica Neue', 'Segoe UI', 'Roboto', 'Ubuntu',
|
||||
'sans-serif';
|
||||
box-sizing: border-box;
|
||||
background-color: $color-background;
|
||||
}
|
||||
@@ -133,6 +139,7 @@ body {
|
||||
html {
|
||||
// this defines what 1rem is --> font root size
|
||||
font-size: 62.5%; // 10/16, 1rem = 10px;
|
||||
// font-weight: bold;
|
||||
|
||||
@include responsive(tab_port) {
|
||||
font-size: 50%;
|
||||
|
||||
@@ -3,6 +3,28 @@
|
||||
position: relative;
|
||||
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) {
|
||||
padding-top: 0;
|
||||
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 {
|
||||
position: absolute;
|
||||
height: 3rem;
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
&--bellLogo {
|
||||
cursor: pointer;
|
||||
height: 2.2rem;
|
||||
fill: red;
|
||||
width: 2.2rem;
|
||||
padding-right: 2.5rem;
|
||||
|
||||
@@ -109,13 +108,18 @@
|
||||
}
|
||||
|
||||
&-link {
|
||||
font-weight: 500;
|
||||
font-size: 1.4rem;
|
||||
color: rgb(221, 221, 221);
|
||||
text-decoration: none;
|
||||
margin-right: 2rem;
|
||||
transition: all 0.2s;
|
||||
|
||||
@media screen and (min-width: 1200px) {
|
||||
.pinning-header .main-header {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-right: 2.6rem;
|
||||
}
|
||||
@@ -162,8 +166,9 @@
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 1.8rem;
|
||||
height: 1.8rem;
|
||||
position: relative;
|
||||
left: 10px;
|
||||
bottom: 4px;
|
||||
transform: translateX(2.4rem) translateY(1rem);
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -171,7 +176,6 @@
|
||||
.dropdownContent {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
// align-items: center;
|
||||
opacity: 0;
|
||||
|
||||
color: #fff;
|
||||
@@ -196,7 +200,6 @@
|
||||
|
||||
&:hover {
|
||||
border-bottom: 1px solid #fff;
|
||||
// border-width: 2%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"noImplicitAny": true,
|
||||
"module": "es6",
|
||||
"target": "es5",
|
||||
"jsx": "react",
|
||||
"jsx": "react-jsx",
|
||||
"sourceMap": true,
|
||||
"allowJs": true,
|
||||
"moduleResolution": "node",
|
||||
|
||||
@@ -2,14 +2,13 @@ const HtmlWebPackPlugin = require('html-webpack-plugin')
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
|
||||
const TerserPlugin = require('terser-webpack-plugin')
|
||||
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
|
||||
const dotenv = require('dotenv')
|
||||
const webpack = require('webpack')
|
||||
const path = require('path')
|
||||
|
||||
const prod =
|
||||
(process.env.NODE_ENV ? process.env.NODE_ENV : '').trim() === 'production'
|
||||
const path = require('path')
|
||||
|
||||
module.exports = () => {
|
||||
dotenv.config({
|
||||
@@ -21,10 +20,11 @@ module.exports = () => {
|
||||
output: {
|
||||
filename: '[name].[contenthash].js',
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
assetModuleFilename: 'assets/[name][ext]',
|
||||
clean: true,
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.tsx', '.ts', '.js'],
|
||||
extensions: ['.js', '.ts', '.tsx'],
|
||||
},
|
||||
optimization: {
|
||||
runtimeChunk: 'single',
|
||||
@@ -67,7 +67,15 @@ module.exports = () => {
|
||||
patterns: [
|
||||
{
|
||||
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$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'svg-react-loader',
|
||||
},
|
||||
use: ['@svgr/webpack'],
|
||||
},
|
||||
{
|
||||
test: /\.css$/i,
|
||||
use: [MiniCssExtractPlugin.loader, 'css-loader'],
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
test: /\.(sass|less|css|scss)$/,
|
||||
use: [
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
options: {
|
||||
publicPath: '../',
|
||||
},
|
||||
},
|
||||
// fallback to style-loader in development
|
||||
process.env.NODE_ENV !== 'production'
|
||||
? 'style-loader'
|
||||
: MiniCssExtractPlugin.loader,
|
||||
'css-loader',
|
||||
'resolve-url-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