Menu素子


import React, { useEffect, useRef } from 'react';
import { useMediaQuery } from 'react-responsive';
import './Menu.css';
import { Link } from 'react-router-dom';
import styled from "styled-components";

const StyledLink = styled(Link)`
  text-decoration: none;
  color: white;
`

function Menu() {
  let isMb = useMediaQuery({
    query: "(max-width:414px)"
  })
  let ManipulatedObj = {
    listObj: useRef(),
    button: useRef(),
  }
  let sw = 0;
  const fadein = fadeIn.bind(ManipulatedObj);
  const fadeout = fadeOut.bind(ManipulatedObj);

  function fadeIn() {
    this.listObj.current.style.visibility = 'visible';
    for (let i = 0; i < this.listObj.current.children.length; i++) {
      this.listObj.current.children[i].style.opacity = 1;
    }
  }

  function fadeOut() {
    this.listObj.current.style.visibility = 'hidden';
    for (let i = 0; i < this.listObj.current.children.length; i++) {
        this.listObj.current.children[i].style.opacity = 0;
    }
  }

  function ButtonPointerEnter() {
    fadein();
  }

  function ButtonMouseLeave(event) {
    if (event.relatedTarget === window || event.relatedTarget === null) {
      fadeout();
    }
    else if (!event.relatedTarget.closest('.list')) {
      fadeout();
    }
  }

  function ListMouseLeave(event) {
    if (event.relatedTarget === window || event.relatedTarget === null) {
      fadeout();
    }
    else if (event.relatedTarget === this.button.current) {
    }
    else if (!event.relatedTarget.closest('.list')) {
      fadeout();
    }
  }

  function ButtonOnClick() {
    if (!sw) {
      this.listObj.current.style.visibility = 'visible';
      fadein();
      sw = !sw;
    }
    else {
      this.listObj.current.style.visibility = 'hidden';
      fadeout();
      sw = !sw;
    }
  }

  useEffect(() => {
    if (!isMb) {
      ManipulatedObj.button.current.onpointerenter = ButtonPointerEnter.bind(ManipulatedObj);
      ManipulatedObj.button.current.onmouseleave = ButtonMouseLeave.bind(ManipulatedObj);
      ManipulatedObj.listObj.current.onmouseleave = ListMouseLeave.bind(ManipulatedObj);
      ManipulatedObj.button.current.onclick = undefined;
    }
    else {
      ManipulatedObj.button.current.onpointerenter = undefined;
      ManipulatedObj.button.current.onmouseleave = undefined;
      ManipulatedObj.listObj.current.onmouseleave = undefined;
      ManipulatedObj.button.current.onclick = ButtonOnClick.bind(ManipulatedObj);
    }
  }, [isMb]);

  return (
    <div className="container">
      <button className="button" ref={ManipulatedObj.button}>MENU</button>
      <ul className="list" ref={ManipulatedObj.listObj}>
        <li><StyledLink to='/'>HOME</StyledLink></li>
        <li><StyledLink to='/music'>MUSIC</StyledLink></li>
        <li><StyledLink to='/contact'>CONTACT</StyledLink></li>
      </ul>
    </div>
  );
}

export default Menu;
styled componentsを使用してstyledメソッドを通過
飾ります重要な点は、useMediaQuery hookを使用して画面サイズを追跡し、useEffect hookコンポーネントのライフサイクルの更新を実現することです.PCで設定されているイベントと移動中に設定されているイベントは、更新のたびに異なるため、初期化と再設定が必要な部分があります.

css

.container {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    margin: 0;
    padding: 0;
}

.list {
    padding: 0;
    margin: 0;
    font-size: 3rem;
    list-style: none;
    display: table-cell;
    visibility: hidden;
    cursor: pointer;
    z-index: 1;
    -webkit-tap-highlight-color: black;  
}

.button {
    font-size: 4rem;
    padding: 0;
    margin: 0;
    background-color: black;
    color: white;
    border: none;
    cursor: pointer;
    z-index: 1;
}

.list li:hover {
    background-color: gray;
}

.list li:nth-child(1){
    opacity: 0;
    transition: opacity 0.2s;
}
.list li:nth-child(2){
    opacity: 0;
    transition: opacity 0.6s;
}
.list li:nth-child(3){
    opacity: 0;
    transition: opacity 1s;
}

.button {
    -webkit-tap-highlight-color: black;    
}

@media screen and (max-width: 414px) {
    .button {
        font-size: 3rem;
        padding: 0;
        margin: 0;
        background-color: black;
        color: white;
        border: none;
        cursor: pointer;
    }

    .list {
        font-size: 1.8rem;
        -webkit-tap-highlight-color: transparent;
    }

    .list li:hover {
        background-color: black;
    }

    .button {
        -webkit-tap-highlight-color: transparent;    
    }
}
ボタンの全部分を囲む親コンテナのdisplayはflex、directionはcolumn、align-items部分はdirectionの反対部分なので、flex-endを使用して上部右端に位置決めできます.
リストでは、マウスのサスペンションに適用する部分は文字に密着し、スペースを残さないようにするため、display:table-cell構造を採用します.
:nth-child(n)のように、コレクタに対応するグループからn順に抽出して適用できる医師類である.