refactor(header): split component in others and add feature for close menu mobile before click in others elements

This commit is contained in:
Henrique Santos Santana 2023-01-04 13:09:37 -03:00
parent d903be8c81
commit 7a72298d2a
6 changed files with 137 additions and 107 deletions

View File

@ -0,0 +1,5 @@
export type ISearchProps = HTMLAttributes<HTMLDivElement>
export interface ITopProps {
handleClickOpen: () => void
}

View 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>
)
}

View 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>
)
}

View 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>
)
}

View File

@ -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;
}

View File

@ -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>
)