Реактивное (react) гамбургер-меню

Реактивное (react) гамбургер-меню Сайтостроение

Реактивное (react) гамбургер-меню

От автора: создайте свое собственное меню, используя React, хуки, TypeScript и styled-component. Я предпочитаю простое меню, которое не будет выглядеть навязчивым на странице, отвлекая внимание от контента — но в то же время доступное для моих пользователей. Вместе мы создадим простое липкое гамбургер-меню!

Что такое гамбургер-меню?

Я думаю, что название «гамбургер» — это просто слово для визуализации иконки меню, которая выглядит как гамбургер. Держу пари, что вы уже видели раньше значок с 3 линиями?

Выше приведен рисунок, показывающий, как я создала гамбургер-меню для своей веб-страницы #onefortheocean. В этой статье мы собираемся сделать более простую версию.

Технические ингредиенты

Думаю, начинать перечислять ингредиенты гамбургеров опасно — у каждого человека свои сильные личные предпочтения! То же самое касается ингредиентов технического стека. В любом случае, если вам не нравятся некоторые из моих ингредиентов, вы можете их убрать. Код написан с использованием компонентов React (16.13), TypeScript (3.8) и Styled (5.1).

Если вы хотите добавить кетчуп или кожуру помидора, вы можете это сделать! Я не против.

Основные компоненты

Я буду создавать компоненты с нуля, добавляя больше деталей в процессе. Я надеюсь, что вы таким образом тоже сможете получить все необходимое. Если вы опытный разработчик, вы можете в любое время покопаться в коде, представленном внизу статьи.

С кодом, приведенным ниже, мы получаем минимальную базу для начала. Мы добавим мобильные настройки, переходы и хуки (события клика) позже. Я решила разделить код на Menu и Hamburger, после добавления основной части ваше меню должно выглядеть примерно так:

Menu — это коричневый фон, который действует как фактическое меню, содержащее ссылки навигации.

JavaScript

READ
Использование CSS-свойства line-height для улучшения читабельности текста
123456789101112131415161718192021222324252627282930313233343536373839404142434445import React, { useState } from “react”;import styled from “styled-components”; import { colors } from “../../global”; import Hamburger from “../Hamburger/Hamburger”; const StyledMenu = styled.nav<{ open: boolean }>`  top: 0;  left: 0;  height: 100vh;  width: 35vw;  position: fixed;  background-color: ${colors.lightbrown};  z-index: 1;  padding: 10rem 0;  flex-direction: column;  display: ${({ open }) => (open ? “flex” : “none”)};`;const StyledLink = styled.a`  padding: 0 2rem;  font-size: 2rem;  color: ${colors.pearl};  text-decoration: none;    :hover {    color: ${colors.yellowmellow};    cursor: pointer;  }`; const Menu = () => {  const [open, setOpen] = useState<boolean>(false);  const close = () => setOpen(false);  return (    <div>      <StyledMenu open={open}>        <StyledLink onClick={() => close()}>Link 1</StyledLink        <StyledLink onClick={() => close()}>Link 2</StyledLink        <StyledLink onClick={() => close()}>Link 3</StyledLink      </StyledMenu>      <Hamburger open={open} setOpen={setOpen} />     </div>   );};

Hamburger — это пиктограмма самого меню, используемая для переключения между видимым и скрытым Menu.

JavaScript

12345678910111213141516171819202122232425262728293031323334353637383940414243444546import React from “react”;import styled from “styled-components”; import { colors } from “../../global”; const StyledHamburger = styled.button<{ open: boolean }>`  position: fixed;  left: 3vw;  top: 3vw;  width: 2rem;  height: 2rem;  padding: 0;  background: transparent;    display: flex;  flex-direction: column;  justify-content: space-around;  border: none;  cursor: pointer;  outline: none;  z-index: 1;  div {    position: relative;    width: 2rem;    height: 0.25rem;    border-radius: 10px;    background-color: ${({ open }) =>      open ? colors.pearl : colors.lightbrown};  }`; type Props = {  open: boolean;  setOpen: (v: boolean) => void;}; const Hamburger = (props: Props) => (  <StyledHamburger    open={props.open}    onClick={() => props.setOpen(!props.open)}  >    <div />    <div />    <div />  </StyledHamburger>);

Добавляем движение с помощью переходов

Теперь у вас есть основное гамбургер-меню. Наверное, немного скучно? Давайте добавим движения! Во-первых, мы хотим задать плавный переход отображения и скрытия Menu.

Чтобы максимально использовать возможности Hamburger, вы можете преобразовать его из значка гамбургера в знак крестика, когда Menu открыто — две иконки в одной! Теперь меню должно выглядеть примерно так:

JavaScript

READ
Ссылки в PDF-файлах не имеют никакой ценности для SEO
1234567891011121314151617181920212223242526272829303132// Menuconst StyledMenu = styled.nav<{ open: boolean }>`  //…  transition: transform 0.3s ease-in-out;  transform: ${({ open }) =>    (open ? “translateX(0)” :”translateX(-100%)”)};`; // Hamburgerconst StyledHamburger = styled.button<{ open: boolean }>`  //…  left: ${({ open }) => (open ? “29vw” : “3vw”)};  div {    //…    transition: all 0.3s linear;    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)”)};    }  }`;

Для Menu мы задаем некоторую задержку. Для гамбургера мы поворачиваем первый и третий div на 45 градусов, образуя крест. Второй div мы просто делаем невидимым, потому что нам нужны только две линии, образующие значок закрытия. Вот и все — вы только что создали гамбургер-меню.

Настройка для мобильных устройств

Я обычно сохраняю дизайн простым без каких-либо значительных настроек для мобильных устройств, но меню слишком важно, чтобы не уделять ему больше внимания.

На маленьком экране Menu должно покрывать всю страницу. Я думаю, что это добавляет ощущение приложения — вы не согласны? В своем приложении я создала контрольную точку на 600px, где Menu разворачивается весь экран. К настоящему времени наше меню должно выглядеть на маленьких экранах примерно так:

JavaScript

1234567891011121314151617//Menuexport const StyledMenu = styled.nav<{ open: boolean }>`  //…  @media (max-width: 600px) {    width: 100%;  }`; //Hamburgerconst StyledHamburger = styled.button<{ open: boolean }>`  //…  @media (max-width: 600px) {    left: ${({ open }) => (open ? “initial” : “3vw”)};    right: ${({ open }) => (open ? “2vw” : “initial”)};  }  //…`;
READ
15 советов по производительности приложений React.js

Для Menu нам просто нужно создать медиа-запрос, при котором ширина меню становится 100% области просмотра, вместо 30%, когда ширина экрана составляет 600 пикселей или меньше. Для Hamburger я хотела переместить значок крестика при открытии меню на мобильном телефоне вправо. Свойство left используется для перемещения крестика от левого края. Когда вы работаете на мобильном телефоне, я хочу, чтобы значок (то есть когда меню охватывает весь экран) был на расстоянии x от правой стороны. Это имеет смысл?

Хуки

Для Menu требуется отслеживать его состояние — оно должно быть открытым или закрытым? Это простой хук useState с логическим значением open и функцией setOpen для изменения состояния open. Это мы уже добавили к Menu, поскольку это важная часть для его работы.

JavaScript

1const [open, setOpen] = useState<boolean>(false);

Что произойдет, если пользователь кликает за пределами Menu? На данный момент ничего.

Если Menu открыто и пользователь кликает за его пределами, он ожидает, что он Menu закроется. Чтобы иметь возможность выяснить, нажимает ли пользователь внутри или снаружи меню, мы добавим ссылку на узел в Menu. Таким образом, мы сможем спросить: «Пользователь нажал на Menu или за его пределами?». Вместе с узлом мы можем использовать пользовательский хук useOnClickOutside. Он должен вести себя так:

JavaScript

123456789101112131415161718192021222324252627282930313233import { useEffect, RefObject } from “react”; const useOnClickOutside = (  ref: RefObject<HTMLDivElement>,  closeMenu: () => void) => {  useEffect(() => {    const listener = (event: MouseEvent) => {      if (ref.current && event.target &&        ref.current.contains(event.target as Node)      ) {        return;      }      closeMenu();    };        document.addEventListener(“mousedown”, listener);    return () => {      document.removeEventListener(“mousedown”, listener);    };  }, [ref, closeMenu]);};const Menu = (props: Props) => {  const [open, setOpen] = useState<boolean>(false);    const node = useRef<HTMLDivElement>(null);  useOnClickOutside(node, () => props.setOpen(false));  return (    <div ref={node}>      ….    </div>  );};

Все ингредиенты собраны вместе — ваш стильный и реактивный гамбургер готов:

Я надеюсь, что вы нашли эту статью полезной!

Автор: Marte Løge

Редакция: Команда webformyself.

Источник

Оценить статью
Блог о самом интересном.
Добавить комментарий