forked from M3-Academy/desafio-react-e-typescript
refactor(header): split component in others and add feature for close menu mobile before click in others elements
This commit is contained in:
parent
d903be8c81
commit
7a72298d2a
5
src/template/Header/containers/@types/index.d.ts
vendored
Normal file
5
src/template/Header/containers/@types/index.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
export type ISearchProps = HTMLAttributes<HTMLDivElement>
|
||||
|
||||
export interface ITopProps {
|
||||
handleClickOpen: () => void
|
||||
}
|
45
src/template/Header/containers/_Bottom.tsx
Normal file
45
src/template/Header/containers/_Bottom.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
import { HTMLAttributes } from 'react'
|
||||
import closeIcon from '../../../assets/icons/x.svg'
|
||||
|
||||
import styles from '../index.module.scss'
|
||||
|
||||
export interface IBottomProps {
|
||||
isMenuOpen: boolean
|
||||
handleClose: () => void
|
||||
}
|
||||
|
||||
export function Bottom({ isMenuOpen, handleClose }: IBottomProps) {
|
||||
function closeMenu(e: any) {
|
||||
if (e.target.classList.contains(styles.menu)) {
|
||||
if (e.target.children[0] !== e.target) {
|
||||
handleClose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
onClick={(e) => closeMenu(e)}
|
||||
className={`${styles.menu} ${isMenuOpen ? styles.active : ''}`}
|
||||
>
|
||||
<div className={styles['menu-content']}>
|
||||
<div className={styles['actions-bottom']}>
|
||||
<a href="/">Entrar</a>
|
||||
<button type="button" onClick={handleClose} className={styles.close}>
|
||||
<img src={closeIcon} alt="ícone do botão para fechar o menu" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<ul className={styles.list}>
|
||||
{['Cursos', 'Saiba Mais', 'Institucionais'].map((item, index) => {
|
||||
return (
|
||||
<li key={'header-bottom-list-' + index}>
|
||||
<a href="/">{item}</a>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
14
src/template/Header/containers/_Search.tsx
Normal file
14
src/template/Header/containers/_Search.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import { ISearchProps } from './@types'
|
||||
|
||||
import searchIcon from '../../../assets/icons/search.svg'
|
||||
|
||||
export function Search({ ...props }: ISearchProps) {
|
||||
return (
|
||||
<div {...props}>
|
||||
<input type="search" placeholder="Buscar..." />
|
||||
<button type="button">
|
||||
<img src={searchIcon} alt="Search icon" />
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
37
src/template/Header/containers/_Top.tsx
Normal file
37
src/template/Header/containers/_Top.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
import { ITopProps } from './@types'
|
||||
|
||||
import { Search } from './_Search'
|
||||
|
||||
import cartIcon from '../../../assets/icons/minicart.svg'
|
||||
import openIcon from '../../../assets/icons/hamburger.svg'
|
||||
import logoImg from '../../../assets/m3-logo-small.png'
|
||||
import logoMediumImg from '../../../assets/m3-logo-medium.png'
|
||||
|
||||
import styles from '../index.module.scss'
|
||||
|
||||
export function Top({ handleClickOpen }: ITopProps) {
|
||||
return (
|
||||
<div className={styles['content']}>
|
||||
<button type="button" onClick={handleClickOpen} className={styles.open}>
|
||||
<img src={openIcon} alt="ícone do botão para abrir o menu" />
|
||||
</button>
|
||||
|
||||
<a className={styles.logo} href="/">
|
||||
<picture>
|
||||
<source media="(min-width:1025px)" srcSet={logoMediumImg} />
|
||||
<img src={logoImg} alt="logo da M3 Academy" />
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
<Search className={`${styles.search} ${styles['search-top']}`} />
|
||||
|
||||
<div className={styles['actions-top']}>
|
||||
<a href="/">Entrar</a>
|
||||
|
||||
<button type="button">
|
||||
<img src={cartIcon} alt="ícone de carrinho" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -7,7 +7,7 @@ $containers: (
|
||||
'xl': 2299.68px,
|
||||
);
|
||||
|
||||
.header {
|
||||
.component {
|
||||
padding: 25px 0;
|
||||
|
||||
position: sticky;
|
||||
@ -18,7 +18,7 @@ $containers: (
|
||||
background-color: var(--clr-common-black);
|
||||
}
|
||||
|
||||
.header {
|
||||
.component {
|
||||
@media only screen and (min-width: 1025px) {
|
||||
padding: 25px 0 0;
|
||||
}
|
||||
|
@ -1,119 +1,48 @@
|
||||
import logoImg from '../../assets/m3-logo-small.png'
|
||||
import logoMediumImg from '../../assets/m3-logo-medium.png'
|
||||
import searchIcon from '../../assets/icons/search.svg'
|
||||
import cartIcon from '../../assets/icons/minicart.svg'
|
||||
import openIcon from '../../assets/icons/hamburger.svg'
|
||||
import closeIcon from '../../assets/icons/x.svg'
|
||||
import { useMemo, useState } from 'react'
|
||||
|
||||
import css from './index.module.scss'
|
||||
import { HTMLAttributes, useMemo, useState } from 'react'
|
||||
import { Top } from './containers/_Top'
|
||||
import { Bottom } from './containers/_Bottom'
|
||||
import { Search } from './containers/_Search'
|
||||
|
||||
interface SearchProps extends HTMLAttributes<HTMLDivElement> {}
|
||||
|
||||
export function Search({ ...props }: SearchProps) {
|
||||
return (
|
||||
<div {...props}>
|
||||
<input type="search" placeholder="Buscar..." />
|
||||
<button type="button">
|
||||
<img src={searchIcon} alt="Search icon" />
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
interface ContainerBottomProps {
|
||||
isOpen: boolean
|
||||
handleClose: () => void
|
||||
}
|
||||
|
||||
const ContainerBottom = ({ isOpen, handleClose }: ContainerBottomProps) => {
|
||||
return (
|
||||
<div
|
||||
className={`${css.menu} ${isOpen ? css.active : ''}`}
|
||||
data-jsx="target"
|
||||
>
|
||||
<div className={css['menu-content']}>
|
||||
<div className={css['actions-bottom']}>
|
||||
<a href="/">Entrar</a>
|
||||
<button
|
||||
onClick={handleClose}
|
||||
className={css.close}
|
||||
type="button"
|
||||
data-jsx="event"
|
||||
>
|
||||
<img src={closeIcon} alt="ícone do botão para fechar o menu" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<ul className={css.list}>
|
||||
{['Cursos', 'Saiba Mais', 'Institucionais'].map((item, index) => {
|
||||
return (
|
||||
<li key={'header-bottom-list-' + index}>
|
||||
<a href="/">{item}</a>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
import styles from './index.module.scss'
|
||||
|
||||
export const Header = () => {
|
||||
const [isOpenMenu, setIsOpenMenu] = useState(false)
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false)
|
||||
|
||||
const handleOpen = useMemo(
|
||||
() =>
|
||||
function () {
|
||||
if (window.innerWidth <= 1024) setIsOpenMenu(true)
|
||||
},
|
||||
[]
|
||||
)
|
||||
const TopProps = {
|
||||
handleClickOpen: useMemo(
|
||||
() =>
|
||||
function () {
|
||||
if (window.innerWidth <= 1024) setIsMenuOpen(true)
|
||||
},
|
||||
[]
|
||||
),
|
||||
}
|
||||
|
||||
const handleClose = useMemo(
|
||||
() =>
|
||||
function () {
|
||||
if (window.innerWidth <= 1024) setIsOpenMenu(false)
|
||||
},
|
||||
[]
|
||||
)
|
||||
const BottomProps = {
|
||||
isMenuOpen,
|
||||
handleClose: useMemo(
|
||||
() =>
|
||||
function () {
|
||||
if (window.innerWidth <= 1024) setIsMenuOpen(false)
|
||||
},
|
||||
[]
|
||||
),
|
||||
}
|
||||
|
||||
return (
|
||||
<header className={css.header}>
|
||||
<nav className={css.nav}>
|
||||
<div className={css.content}>
|
||||
<button
|
||||
onClick={handleOpen}
|
||||
className={css.open}
|
||||
type="button"
|
||||
data-jsx="event"
|
||||
>
|
||||
<img src={openIcon} alt="ícone do botão para abrir o menu" />
|
||||
</button>
|
||||
<header className={styles['component']}>
|
||||
<nav>
|
||||
<Top {...TopProps} />
|
||||
|
||||
<a className={css.logo} href="/">
|
||||
<picture>
|
||||
<source media="(min-width:1025px)" srcSet={logoMediumImg} />
|
||||
<img src={logoImg} alt="logo da M3 Academy" />
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
<Search className={`${css.search} ${css['search-top']}`} />
|
||||
|
||||
<div className={css['actions-top']}>
|
||||
<a href="/">Entrar</a>
|
||||
|
||||
<button type="button">
|
||||
<img src={cartIcon} alt="ícone de carrinho" />
|
||||
</button>
|
||||
</div>
|
||||
<div className={`${styles['search-bottom']}`}>
|
||||
<Search
|
||||
className={`${styles.search} ${styles['search-bottom-content']}
|
||||
`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={`${css['search-bottom']}`}>
|
||||
<Search className={`${css.search} ${css['search-bottom-content']}`} />
|
||||
</div>
|
||||
|
||||
<ContainerBottom isOpen={isOpenMenu} handleClose={handleClose} />
|
||||
<Bottom {...BottomProps} />
|
||||
</nav>
|
||||
</header>
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user