Side Nav React.js - 튜토리얼

51731 단어 javascriptreactwebdev

목차


  • Intro & Prerequisites
  • Basic Setup
  • Creating The Burger
  • Creating The Side Menu
  • Finishing Touches



  • 소개 및 전제 조건

    Okay, so for today's tutorial, I thought I'd do something in React. If you want to follow along, I recommend that you have some knowledge of React, otherwise some of the stuff might be very confusing to you. And as always there will be a YouTube version of this tutorial, you can find it here :)

    This is what we're building today:


    기본 설정

    Okay, so a fun thing I thought of doing, is everyone having the same website, but with different color themes.
    What you're going to do, is open this
    website . 기본적으로 40가지 색상 테마를 보여주는 블로그입니다(항상 이 웹사이트를 사용합니다).

    지금 할 일은 Google에서 난수 생성기를 열고 돌려보는 것입니다. 어떤 숫자를 얻든 색상 테마가 됩니다. 이것이 내가 얻은 것입니다.




    색상 테마를 기억하세요!

    이제 코드를 저장할 폴더를 열고 React 프로젝트를 시작한 후 다음 패키지를 다운로드합니다.

    npx create-react-app frontend
    cd frontend
    yarn add hamburger-react react-focus-lock react-icons styled-components
    

    그런 다음 코드 편집기를 열고 다음 파일을 유지/생성합니다.

    참고: 다른 self-created 파일은 필요하지 않으므로 자유롭게 delete 사용하고 plain CSS 를 사용하지 않을 것입니다. 구성 요소의 스타일을 styled-components 로 지정합니다.

    이제 내부 코드App.js를 다음과 같이 변경합니다.

    import { ThemeProvider } from "styled-components";
    import { GlobalStyles } from "./global";
    import { theme } from "./theme";
    
    function App() {
      return (
        <ThemeProvider theme={theme}>
          <GlobalStyles />
          <div class="main-text">
            <h1>Hello World</h1>
          </div>
        </ThemeProvider>
      );
    }
    
    export default App;
    

    그리고 내부 코드index.js는 다음과 같습니다.

    import React from "react";
    import ReactDOM from "react-dom/client";
    
    import App from "./App";
    
    const root = ReactDOM.createRoot(document.getElementById("root"));
    root.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>
    );
    

    이제 내부theme.js에서 테마를 정의합니다.

    export const theme = {
      primaryDark: "#2B3252",
      primaryLight: "#EF5455",
      primaryHover: "#FAD744",
    
      mobile: "576px",
    };
    

    여기에서 색상 테마를 사용할 수 있습니다. primaryDark의 경우 테마에서 더 어두운 색상을 사용하십시오. 그리고 primaryLight에는 더 밝은 색상을 사용하십시오. 테마에 세 번째 색상이 없으면 #FFFFFF 또는 #000000primaryHover를 사용하십시오.

    이제 내부global.js에서 기본 CSS 규칙을 정의합니다.

    import { createGlobalStyle } from "styled-components";
    
    export const GlobalStyles = createGlobalStyle`
      html, body {
        margin: 0;
        padding: 0;
      }
      *, *::after, *::before {
        box-sizing: border-box;
      }
      body {
        display: flex;
        justify-content: center;
        align-items: center;
    
        background: ${({ theme }) => theme.primaryDark};
        color: ${({ theme }) => theme.primaryLight};
    
        height: 100vh;
        line-height: 1.6;
    
        font-family: "Roboto", sans-serif;
        font-size: 1.2rem;
        font-weight: normal;
      }
      h1 {
        font-size: 2rem;
        text-align: center;
        text-transform: uppercase;
      }
      div {
        text-align: center;
      }
      small {
        display: block;
      }
      a {
        color: ${({ theme }) => theme.primaryHover};
        text-decoration: none;
      }
      .main-text {
        margin-left: 20rem;
        margin-right: 20rem;
      }
    `;
    
    styled-components로 CSS를 정의하는 방법에 대해 질문이 있는 경우 의견에 자유롭게 질문하십시오!

    이것이 우리에게 남은 것입니다:



    버거 만들기

    Over at, ./components/Burger create the following files:

    • index.js ( we're going to use for importing.)
    • Burger.styled.js ( we're going to use for styling(CSS))
    • Burger.js ( contains all the JSX code)

    Inside of index.js write:

    export { default } from "./Burger";
    

    Inside of Burger.styled.js write:

    import styled from "styled-components";
    
    export const StyledBurger = styled.button`
      position: absolute;
      top: 5%;
      left: 2rem;
      display: flex;
      flex-direction: column;
      justify-content: space-around;
      width: 2rem;
      height: 2rem;
      background: transparent;
      border: none;
      cursor: pointer;
      padding: 0;
      z-index: 10;
      span {
        width: 2rem;
        height: 0.25rem;
        background: ${({ theme, open }) =>
          open ? theme.primaryDark : theme.primaryLight};
        border-radius: 10px;
        transition: all 0.3s linear;
        position: relative;
        transform-origin: 1px;
        :first-child {
          transform: ${({ open }) => (open ? "rotate(45deg)" : "rotate(0)")};
        }
        :nth-child(2) {
          opacity: ${({ open }) => (open ? "0" : "1")};
          transform: ${({ open }) => (open ? "translateX(20px)" : "translateX(0)")};
        }
        :nth-child(3) {
          transform: ${({ open }) => (open ? "rotate(-45deg)" : "rotate(0)")};
        }
      }
    `;
    
    Inside of Burger.js , we're going to utilize hamburger-react which we installed earlier. It's a package built just for hamburger menu's. You can learn more about it from the official website .
    이제 Burger.js 안에 다음 코드를 추가합니다.

    import React from "react";
    import { bool, func } from "prop-types";
    
    import { Twirl as Hamburger } from "hamburger-react";
    
    import { StyledBurger } from "./Burger.styled";
    
    const Burger = ({ open, setOpen, ...props }) => {
      const isExpanded = open ? true : false;
    
      return (
        <StyledBurger>
          <Hamburger
            toggled={open}
            toggle={setOpen}
            size={32}
            direction="right"
            duration={0.4}
            distance="lg"
            aria-expanded={isExpanded}
            color={open ? "#2B3252" : "#EF5455"}
          ></Hamburger>
        </StyledBurger>
      );
    };
    
    Burger.propTypes = {
      open: bool.isRequired,
      setOpen: func.isRequired,
    };
    
    export default Burger;
    

    빠른 참고: color<Hamburger> 속성에서 다음 공식을 사용합니다(다른 테마를 사용하고 있으므로).color={open? "primaryDarkColor" : "primaryLightColor"}
    거의 끝났습니다! ./components/index.js 내부에 다음을 추가합니다.

    export { default as Burger } from "./Burger";
    

    그리고 App.js 안에 다음과 같이 씁니다.

    import React, { useState } from "react";
    
    import { ThemeProvider } from "styled-components";
    import { GlobalStyles } from "./global";
    import { theme } from "./theme";
    
    import { Burger } from "./components";
    
    function App() {
      const [open, setOpen] = useState(false);
    
      return (
        <ThemeProvider theme={theme}>
          <GlobalStyles />
    
          <Burger open={open} setOpen={setOpen} aria-controls={menuId} />
    
          <div class="main-text">
            <h1>Hello World!</h1>
          </div>
        </ThemeProvider>
      );
    }
    
    export default App;
    

    이제 앱을 실행하면 왼쪽 상단에 hamburger icon가 표시됩니다 :)

    사이드 메뉴 만들기

    Just like the Burger in the Menu folder, create:

    • index.js ( we're going to use for importing.)
    • Menu.styled.js ( we're going to use for styling(CSS))
    • Menu.js ( contains all the JSX code)

    Inside of index.js add:

    export { default } from "./Menu";
    

    Inside of Menu.styled.js add:

    import styled from "styled-components";
    
    export const StyledMenu = styled.nav`
      display: flex;
      flex-direction: column;
      justify-content: center;
      background: ${({ theme }) => theme.primaryLight};
      transform: ${({ open }) => (open ? "translateX(0)" : "translateX(-100%)")};
      height: 100vh;
      text-align: left;
      padding: 2rem;
      position: absolute;
      top: 0;
      left: 0;
      transition: transform 0.3s ease-in-out;
      @media (max-width: ${({ theme }) => theme.mobile}) {
        width: 100%;
      }
      a {
        font-size: 2rem;
        text-transform: uppercase;
        padding: 2rem 0;
        font-weight: bold;
        letter-spacing: 0.5rem;
        color: ${({ theme }) => theme.primaryDark};
        text-decoration: none;
        transition: color 0.6s linear;
        @media (max-width: ${({ theme }) => theme.mobile}) {
          font-size: 1.5rem;
          text-align: center;
        }
        &:hover {
          color: ${({ theme }) => theme.primaryHover};
        }
      }
      .icon {
        margin-right: 10px;
      }
    `;
    

    And finally inside of Menu.js add:

    import React from "react";
    import { bool } from "prop-types";
    
    import { AiOutlineFileText } from "react-icons/ai";
    import { RiPriceTag3Line, RiContactsBookLine } from "react-icons/ri";
    import { StyledMenu } from "./Menu.styled";
    
    const Menu = ({ open, ...props }) => {
      const isHidden = open ? true : false;
      const tabIndex = isHidden ? 0 : -1;
    
      return (
        <StyledMenu open={open} aria-hidden={!isHidden} {...props}>
          <a href="#" tabIndex={tabIndex}>
            <span aria-hidden="true">
              <AiOutlineFileText className="icon" />
            </span>
            About us
          </a>
          <a href="#" tabIndex={tabIndex}>
            <span aria-hidden="true">
              <RiPriceTag3Line className="icon" />
            </span>
            Pricing
          </a>
          <a href="#" tabIndex={tabIndex}>
            <span aria-hidden="true">
              <RiContactsBookLine className="icon" />
            </span>
            Contact
          </a>
        </StyledMenu>
      );
    };
    
    Menu.propTypes = {
      open: bool.isRequired,
    };
    
    export default Menu;
    

    And don't forget inside of ./components/index.js add:

    ...
    export { default as Menu } from "./Menu";
    

    And in App.js add:

    import React, { useState, useRef } from "react";
    
    import { ThemeProvider } from "styled-components";
    import { GlobalStyles } from "./global";
    import { theme } from "./theme";
    
    import FocusLock from "react-focus-lock";
    import { useOnClickOutside } from "./hooks";
    
    import { Burger, Menu } from "./components";
    
    function App() {
      const [open, setOpen] = useState(false);
    
      const node = useRef();
      const menuId = "main-menu";
    
      useOnClickOutside(node, () => setOpen(false));
    
      return (
        <ThemeProvider theme={theme}>
          <GlobalStyles />
          <Burger open={open} setOpen={setOpen} aria-controls={menuId} />
          <Menu open={open} setOpen={setOpen} id={menuId} />
          <div class="main-text">
            <h1>Hello World</h1>
          </div>
        </ThemeProvider>
      );
    }
    
    export default App;
    

    And, we're done! However, there are a couple of finishing touches we could add. If you don't want to do this, it's ok, the side nav works perfectly well like this :)

    마무리

    So, the thing I'm talking about, is the fact that if you click outside of the side nav, it won't close. Now, this is ok, if you want the user to click the X icon to close it. However, I don't like that :)

    Inside of hooks.js ( which we created in the beginning) add:

    import { useEffect } from "react";
    
    export const useOnClickOutside = (ref, handler) => {
      useEffect(() => {
        const listener = (event) => {
          if (!ref.current || ref.current.contains(event.target)) {
            return;
          }
          handler(event);
        };
        document.addEventListener("mousedown", listener);
    
        return () => {
          document.removeEventListener("mousedown", listener);
        };
      }, [ref, handler]);
    };
    

    And change the code in App.js to:

    import React, { useState, useRef } from "react";
    
    import { ThemeProvider } from "styled-components";
    import { GlobalStyles } from "./global";
    import { theme } from "./theme";
    
    import FocusLock from "react-focus-lock";
    import { useOnClickOutside } from "./hooks";
    
    import { Burger, Menu } from "./components";
    
    function App() {
      const [open, setOpen] = useState(false);
    
      const node = useRef();
      const menuId = "main-menu";
    
      useOnClickOutside(node, () => setOpen(false));
    
      return (
        <ThemeProvider theme={theme}>
          <GlobalStyles />
          <div ref={node}>
            <FocusLock disabled={!open}>
              <Burger open={open} setOpen={setOpen} aria-controls={menuId} />
              <Menu open={open} setOpen={setOpen} id={menuId} />
            </FocusLock>
          </div>
          <div class="main-text">
            <h1>Hello World!</h1>
          </div>
        </ThemeProvider>
      );
    }
    
    export default App;
    
    Notice, here we used a couple of things. Firstly we used useRef which is a React hook. You can read more about useRef here . 그리고 우리는 react-focus-lock를 사용했습니다. 공식(제 생각에는)documentation입니다.

    이제 끝났습니다!

    github 페이지로 연결됩니다.

    당신이 이것을 즐겼기를 바랍니다. 마음에 드셨다면 저를 팔로우하는 것을 잊지 마세요.
    내 소셜 링크:





    24YoungMamba (영맘바) · GitHub



    나는 웹사이트를 만든다 :)
    귀하의 웹사이트를 구축할 수 있습니다. 24YoungMamba에는 하나의 저장소가 있습니다. GitHub에서 코드를 따르십시오.



    github.com









    영 맘바 – Medium



    Medium에서 Young Mamba의 글을 읽어보세요. 웹사이트👨‍💻를 만듭니다. 매일 Young Mamba와 수천 명의 다른 목소리가 Medium에서 중요한 이야기를 읽고 쓰고 공유합니다.



    medium.com



    액체 오류: 내부

    tiktok.com

    좋은 웹페이지 즐겨찾기